# SpamAssassin rules file: tests. ########################################################################### header NO_REAL_NAME From =~ /^["\s]*\?\s*$/ describe NO_REAL_NAME From: does not include a real name header FROM_ENDS_IN_NUMS From =~ /\d\d\@/ describe FROM_ENDS_IN_NUMS From: ends in numbers test FROM_ENDS_IN_NUMS ok matt1234@sergeant.org test FROM_ENDS_IN_NUMS fail matt@sergeant.org header FROM_STARTS_WITH_NUMS From =~ /^\d\d/ describe FROM_STARTS_WITH_NUMS From: starts with nums test FROM_STARTS_WITH_NUMS ok 1234matt@sergeant.org test FROM_STARTS_WITH_NUMS fail matt@sergeant.org header FROM_HAS_MIXED_NUMS From =~ /\d+[a-z]+\d+\S*@/i describe FROM_HAS_MIXED_NUMS From: contains numbers mixed in with letters # (contrib: David Hull - fixed to support "foo @ foo . com" ) header FROM_NO_USER From =~ /(?:^\@|<\@| \@[^<]*$|<>)/ [if-unset: unset@unset.unset] describe FROM_NO_USER From: has no local-part before @ sign header TO_NO_USER To =~ /(?:^\@|<\@| \@[^<]*$|<>)/ [if-unset: unset@unset.unset] describe TO_NO_USER To: has no local-part before @ sign header TO_MALFORMED To !~ /(?:(?:\"[^\"]+\"|\S+)\@\S+\.\S+|undisclosed-recipients:|<\S+(\!\S+){1,}>)/ [if-unset: unset@unset.unset] describe TO_MALFORMED To: has a malformed address header TO_LOCALPART_EQ_REAL To =~ /^\s*(\"?)([\w%\+\-=_\.]+)\1\s*<\2\@[\w%\+\-=_\.]+>/i describe TO_LOCALPART_EQ_REAL To: repeats local-part as real name header FROM_MALFORMED From !~ /(?:\"[^\"]+\"|\S+)\@\S+\.\S+|<\S+(\!\S+){1,}>/ [if-unset: unset@unset.unset] describe FROM_MALFORMED From: has a malformed address header PLING Subject =~ /\!/ describe PLING Subject has an exclamation mark header PLING_PLING Subject =~ /\!\!\!+/ describe PLING_PLING Subject has lots of exclamation marks header SUBJ_HAS_UNIQ_ID eval:check_for_unique_subject_id() describe SUBJ_HAS_UNIQ_ID Subject contains a unique ID number header SUBJ_HAS_SPACES Subject =~ /(?:\s{6,}|\t)/ describe SUBJ_HAS_SPACES Subject contains lots of white space header UNDISC_RECIPS To =~ /^undisclosed-recipients?:\s*;$/ describe UNDISC_RECIPS Valid-looking To "undisclosed-recipients" header FAKED_UNDISC_RECIPS To =~ /Undisclosed.*Recipient\S*@/i describe FAKED_UNDISC_RECIPS Faked To "Undisclosed-Recipients" header TO_INVESTORS To =~ /\bInvestors\@/ describe TO_INVESTORS To: non-existent 'Investors' address header SUBJ_ALL_CAPS eval:subject_is_all_caps() describe SUBJ_ALL_CAPS Subject is all capitals header SUBJ_MISSING eval:subject_missing() describe SUBJ_MISSING Subject: is empty or missing # (allow this test to pass if there's no Message-Id header) header MSGID_HAS_NO_AT Message-Id !~ /\@/ [if-unset: NO@MSGID] describe MSGID_HAS_NO_AT Message-Id has no @ sign header MSGID_SPAMSIGN_1 Message-Id =~ /^<[0-9a-f]{12,12}\$[0-9a-f]{8,8}\$[0-9a-f]{8,8}\@>$/ describe MSGID_SPAMSIGN_1 Message-Id generated by a spam tool header INVALID_MSGID Message-Id !~ /^<(?:\".+\"|[^\s]+)\@(?:\[.+\]|[^\s]+)>$/ [if-unset: ] describe INVALID_MSGID Message-Id is not valid, according to RFC-2822 header INVALID_DATE Date =~ / AM| PM/i describe INVALID_DATE Invalid Date: header (has AM/PM) header INVALID_DATE_NO_TZ Date =~ /^..., \d+ ... .... ..:..:..$/ describe INVALID_DATE_NO_TZ Invalid Date: header (no timezone) # allow +1300, NZ timezone header INVALID_DATE_TZ_ABSURD Date =~ /[-+](?:1[4-9]\d\d|[2-9]\d\d\d)$/ describe INVALID_DATE_TZ_ABSURD Invalid Date: header (timezone does not exist) header INVALID_DATE_ODD_MONTH Date =~ /\d+ [^A-Z]{3,} \d\d\d\d/i describe INVALID_DATE_ODD_MONTH Invalid Date: header (wierd month) header DATE_IN_FUTURE eval:check_for_forward_date() describe DATE_IN_FUTURE Date: Differs by more than 4 days from current date header SUBJ_HAS_Q_MARK Subject =~ /\?.{2,}$/ describe SUBJ_HAS_Q_MARK Subject: contains a question mark header SUBJ_ENDS_IN_Q_MARK Subject =~ /\?+\s*$/ describe SUBJ_ENDS_IN_Q_MARK Subject: ends in a question mark header ADVERT_CODE Subject =~ /(^\s*|\s+)ADV:/i describe ADVERT_CODE Subject: contains advertising tag header FRIEND_AT_PUBLIC To =~ /(yourdomain|you|your|public).(com|org|net)/i describe FRIEND_AT_PUBLIC sent to you@you.com or similar header DOMAIN_SUBJECT Subject =~ /(\s(\.|dot\s+)(info|biz|name)|domain)\b.*(extension|info|regist(ry|ration|er)|submission)/i describe DOMAIN_SUBJECT Subject: domain registration spam subject header TO_EMPTY To =~ /^(?:\@|\s*$)/ [if-unset: UNSET] describe TO_EMPTY To: is empty header REPLY_TO_EMPTY Reply-To =~ /^(?:\@|\s*$)/ [if-unset: UNSET] describe REPLY_TO_EMPTY Reply-To: is empty header ALL_CAPS_SUBJECT ALL =~ /\nSUBJECT: /s describe ALL_CAPS_SUBJECT SUBJECT: header found header X_EM_VER_PRESENT X-Em-Version =~ /\S/ describe X_EM_VER_PRESENT Found an X-Em-Version: header header X_PMFLAGS_PRESENT X-PMFLAGS =~ /\S/ describe X_PMFLAGS_PRESENT Found an X-PMFLAGS: (all caps) header header X_UIDL_SPAMSIGN X-UIDL =~ /[^\s\x21-\x7E]/ describe X_UIDL_SPAMSIGN X-UIDL: header contains invalid chars header NO_MX_FOR_FROM eval:check_for_from_mx() describe NO_MX_FOR_FROM No MX records for the From: domain header KNOWN_BAD_DIALUPS eval:check_for_bad_dialup_ips() describe KNOWN_BAD_DIALUPS Received via known spam-harbouring dialups header FROM_AND_TO_SAME eval:check_for_from_to_equivalence() describe FROM_AND_TO_SAME From and To the same address header BAD_HELO_WARNING eval:check_for_bad_helo() describe BAD_HELO_WARNING Fake name used in SMTP HELO command header SUBJ_FULL_OF_8BITS eval:check_subject_for_lotsa_8bit_chars() describe SUBJ_FULL_OF_8BITS Subject is full of 8-bit characters header MDAEMON_2_7_4 Received =~ /with SMTP .MDaemon.v2.7.SP4.R./ describe MDAEMON_2_7_4 Received via buggy SMTP server (MDaemon 2.7.4SP4R) header FAKED_IP_IN_RCVD Received =~ /from [-0-9a-z\._]+_\[\d+\.\d+\.\d+\.\d+\] /i describe FAKED_IP_IN_RCVD Received: contains a name with a faked IP-address header SMTPD_IN_RCVD Received =~ /\(SMTPD32-\d+\..+\)/ describe SMTPD_IN_RCVD Received via SMTPD32 server (SMTPD32-n.n) header POST_IN_RCVD Received =~ / Post\.(?:sk|cz)/ describe POST_IN_RCVD Received contains fake 'Post.cz' hostname # the new first arg for check_rbl() indicates what type of check it is; # each type of check is stored in a separate set, and if an IP has already # been hit in that set, it will not be checked with any other zone in # that set. header RCVD_IN_RELAYS_ORDB_ORG eval:check_rbl('relay', 'relays.ordb.org.') describe RCVD_IN_RELAYS_ORDB_ORG Received via a relay in relays.ordb.org header RCVD_IN_OSIRUSOFT_COM eval:check_rbl('relay', 'relays.osirusoft.com.') describe RCVD_IN_OSIRUSOFT_COM Received via a relay in relays.osirusoft.com # ORBZ is indifinitely suspended #header RCVD_IN_ORBZ eval:check_rbl('relay', 'inputs.orbz.org.') #describe RCVD_IN_ORBZ Received via a relay in inputs.orbz.org header RCVD_IN_VISI eval:check_rbl('relay', 'relays.visi.com.') describe RCVD_IN_VISI Received via a relay in relays.visi.com header RCVD_IN_RFCI eval:check_rbl('rfci', 'ipwhois.rfc-ignorant.org.') describe RCVD_IN_RFCI Received via a relay in ipwhois.rfc-ignorant.org # Overzealous, blocking sparklist.com and yahoogroups with Confirmed Spam # Source records. not recommended. #header RCVD_IN_5_10 eval:check_rbl('relay', 'blackholes.five-ten-sg.com.') #describe RCVD_IN_5_10 Received via a relay in blackholes.five-ten-sg.com header RCVD_IN_ORBS eval:check_rbl('relay', 'orbs.dorkslayers.com.') describe RCVD_IN_ORBS Received via a relay in orbs.dorkslayers.com # X prefix is so that these are run after RCVD_IN_*. tests are run in # alphanumerically-sorted order. (These used to be Osirusoft.com-specific, but # now, other DNSBLs are using the same convention.) header X_OSIRU_SPAM_SRC eval:check_rbl_results_for('relay', '127.0.0.4') describe X_OSIRU_SPAM_SRC DNSBL: sender is Confirmed Spam Source header X_OSIRU_SPAMWARE_SITE eval:check_rbl_results_for('relay', '127.0.0.6') describe X_OSIRU_SPAMWARE_SITE DNSBL: sender is a Spamware site or vendor # NOTE: commercial tests, see README file for details header RCVD_IN_RBL eval:check_rbl('rbl', 'blackholes.mail-abuse.org.') describe RCVD_IN_RBL Received via RBLed relay, see http://www.mail-abuse.org/rbl/ header RCVD_IN_RSS eval:check_rbl('relay', 'relays.mail-abuse.org.') describe RCVD_IN_RSS Received via RSSed relay, see http://www.mail-abuse.org/rss/ header RCVD_IN_DUL eval:check_rbl('dialup', 'dialups.mail-abuse.org.') describe RCVD_IN_DUL Received from dialup, see http://www.mail-abuse.org/dul/ # NOTE: commercial test, see README file for details header RCVD_IN_BL_SPAMCOP_NET eval:check_rbl('spamcop', 'bl.spamcop.net.') describe RCVD_IN_BL_SPAMCOP_NET Received via a relay in bl.spamcop.net # don't include From:! Many UNIX MTA's get false positives otherwise # ditto for Reply-To:, some list software inserts Received and Reply-To hdrs header FORGED_RCVD_FOUND ALL =~ /\nSubject:.*\nReceived: /s describe FORGED_RCVD_FOUND Possibly-forged 'Received:' header found header YR_MEMBERSHIP_EXCH Subject =~ /Your Membership Exchange/ describe YR_MEMBERSHIP_EXCH Subject contains 'Your Membership Exchange' # obsolete; hotmail have changed their header format. #header FROM_FORGED_HOTMAIL From =~ /^[^"]+\S+\@hotmail\.com/i #describe FROM_FORGED_HOTMAIL From: claims to be hotmail but not in their format header DIFFERENT_REPLY_TO eval:check_for_spam_reply_to() describe DIFFERENT_REPLY_TO Reply-To: massively different from From: or To: header LOTS_OF_CC_LINES eval:check_lots_of_cc_lines() describe LOTS_OF_CC_LINES Lots and lots of Cc: headers header FROM_NAME_EQ_FROM_ADDR eval:check_from_name_eq_from_address() describe FROM_NAME_EQ_FROM_ADDR 'From:' address also used as sender's real name header FORGED_HOTMAIL_RCVD eval:check_for_forged_hotmail_received_headers() describe FORGED_HOTMAIL_RCVD Forged hotmail.com 'Received:' header found header FORGED_EUDORAMAIL_RCVD eval:check_for_forged_eudoramail_received_headers() describe FORGED_EUDORAMAIL_RCVD Forged eudoramail.com 'Received:' header found header FORGED_YAHOO_RCVD eval:check_for_forged_yahoo_received_headers() describe FORGED_YAHOO_RCVD Forged yahoo.com 'Received:' header found header FORGED_JUNO_RCVD eval:check_for_forged_juno_received_headers() describe FORGED_JUNO_RCVD Forged juno.com 'Received:' header found header FORGED_GW05_RCVD eval:check_for_forged_gw05_received_headers() describe FORGED_GW05_RCVD Forged 'by gw05' 'Received:' header found header CHARSET_FARAWAY eval:check_for_faraway_charset() describe CHARSET_FARAWAY Character set indicates a foreign language header NONEXISTENT_CHARSET Content-Type =~ /charset=.?DEFAULT/ describe NONEXISTENT_CHARSET Character set doesn't exist header CHARSET_FARAWAY_HEADERS eval:check_for_faraway_charset_in_headers() describe CHARSET_FARAWAY_HEADERS A foreign language charset used in headers header X_MAILER_GIBBERISH X-Mailer =~ /^[A-Fa-f0-9\.]{48,}$/ describe X_MAILER_GIBBERISH 'X-Mailer' line contains gibberish header X_PRIORITY_HIGH X-Priority =~ /^1/ describe X_PRIORITY_HIGH Sent with 'X-Priority' set to high header X_MSMAIL_PRIORITY_HIGH X-Msmail-Priority =~ /^High/ describe X_MSMAIL_PRIORITY_HIGH Sent with 'X-Msmail-Priority' set to high header MAY_BE_FORGED Received =~ /\(may be forged\)/i describe MAY_BE_FORGED 'Received:' has 'may be forged' warning header SHORT_RECEIVED_LINE Received =~ /\S{120,}/s describe SHORT_RECEIVED_LINE 'Received:' contains huge hostname header CORRUPT_MSGID Message-Id =~ /\@Received: / describe CORRUPT_MSGID 'Message-Id' contains bits of Received header header MSG_ID_ADDED_BY_MTA Message-Id =~ / \(added by / describe MSG_ID_ADDED_BY_MTA 'Message-Id' was added by a relay header MSG_ID_ADDED_BY_MTA_2 ALL =~ /\nMessage-Id: .*(?!yahoo).*\nReceived: /s describe MSG_ID_ADDED_BY_MTA_2 'Message-Id' was added by a relay (2) # compensate for common false pos on above rule: Yahoo! webmail header YAHOO_MSGID_ADDED ALL =~ /Message-Id: <\S+\.mail.yahoo.com>\nReceived: .*by \S+mail.yahoo.com via HTTP;/s describe YAHOO_MSGID_ADDED 'Message-Id' was added by yahoo.com, that's OK header MANY_FROMS From =~ /^[^\"\<\(]+, [^\"\<\(]+$/ describe MANY_FROMS 'From' contains more than one address # *so* many spams come from here. header FROM_BTAMAIL From =~ /\@btamail.net.cn/i describe FROM_BTAMAIL From an address @btamail.net.cn # ditto header FROM_UGETMORE From =~ /\@ugetmore4less.net/i describe FROM_UGETMORE From an address @ugetmore4less.net header USER_IN_BLACKLIST eval:check_from_in_blacklist() describe USER_IN_BLACKLIST From: address is in the user's black-list header FROM_MISSING From =~ /^UNSET$/ [if-unset: UNSET] describe FROM_MISSING Missing From: header header DATE_MISSING Date =~ /^UNSET$/ [if-unset: UNSET] describe DATE_MISSING Missing Date: header # Steve Linford via Charlie Watts: good test! header CTYPE_JUST_HTML eval:check_for_content_type_just_html() describe CTYPE_JUST_HTML HTML-only mail, with no text version header ROUND_THE_WORLD eval:check_for_round_the_world_received() describe ROUND_THE_WORLD Received: says mail bounced all around the world # this is a quite common false positive, as it's legal to remove a To but leave # a CC. so don't score it high. header MISSING_HEADERS eval:check_for_missing_to_header() describe MISSING_HEADERS Missing To: header # (contrib: skod) # modified by jm to remove bulk_mailer, matches on a mailing list I'm on header RATWARE ALL =~ /(?:4\.\.72\.1712\.3|ACE Contact Manager|Aristotle Mail|Avalanche|Calypso|clansoft|Cognigen|Cyber-Bomber|Crescent|DiffondiCool|Dynamic Mail Server|CTMailer|E-Broadcaster|E-mail Magnet|Ellipse Bulk Emailer|EmailBlaster|Emailer.Platinum|eMerge|Extractor|Floodgate|FlashSend|Goldrush|Group Mail|Internet Marketing|Mailcast|MailKing|MassE-Mail|massmail\.pl|Matchmaker|NetMailer|News Breaker|pop3.report|RamoMail|Ready Aim|Shopping.Planet|Stalker.s|TBBS\/TIGER|TOO BAD|TotalMailTURBO Mail|V3,1,6,1|V3,1,2,0|V3,2,2,0|V.null.\.1712\.3|WindoZ|WinNT.s.Blat|WorldMerge|YMR)/ describe RATWARE Bulk email software fingerprints found in headers # contrib: Craig (total regexp wizardry here ;) header SUSPICIOUS_RECIPS To =~ /(@[-a-z0-9_.]{2,}).*(?:\1.*){9,}/is describe SUSPICIOUS_RECIPS To: contains similar domains at least 10 times header SUSPICIOUS_CC_RECIPS Cc =~ /(@[-a-z0-9_.]{2,}).*(?:\1.*){9,}/is describe SUSPICIOUS_CC_RECIPS Cc: contains similar domains at least 10 times header VERY_SUSP_RECIPS To =~ /\b([a-z][a-z])[^@]{0,20}(@[-a-z0-9_\.]{0,30}).{0,30}?(?:\1[^@]*\2.{0,20}?){9,}/is describe VERY_SUSP_RECIPS To: contains similar usernames at least 10 times header VERY_SUSP_CC_RECIPS Cc =~ /\b([a-z][a-z])[^@]{0,20}(@[-a-z0-9_\.]{0,30}).{0,30}?(?:\1[^@]*\2.{0,20}?){9,}/is describe VERY_SUSP_CC_RECIPS Cc: contains similar usernames at least 10 times header Q_FOR_SELLER Subject =~ /Question.*(for|to|from eBay).*(seller|Member)/ describe Q_FOR_SELLER Subject is an eBay question header USER_IN_WHITELIST_TO eval:check_to_in_whitelist() describe USER_IN_WHITELIST_TO User is listed in 'whitelist_to' header USER_IN_MORE_SPAM_TO eval:check_to_in_more_spam() describe USER_IN_MORE_SPAM_TO User is listed in 'more_spam_to' header USER_IN_ALL_SPAM_TO eval:check_to_in_all_spam() describe USER_IN_ALL_SPAM_TO User is listed in 'all_spam_to' header ORDER_STATUS Subject =~ / order\b/i describe ORDER_STATUS Subject looks like order info header IN_REP_TO In-Reply-To =~ /\S/ describe IN_REP_TO 'In-Reply-To' line found header GAPPY_SUBJECT Subject =~ /(?:[a-z][-_\.\,\:\;\'\~]{1,3}){5,}/i describe GAPPY_SUBJECT 'Subject' contains G.a.p.p.y-T.e.x.t # This is a Bugzilla bug status report e-mail and probably OK header BUGZILLA_BUG Subject =~ /\[Bug \d+\]/ describe BUGZILLA_BUG Looks like a Bugzilla bug # give a negative score to Majordomo results. header MAJORDOMO Subject =~ /Majordomo (?:request )?results/ describe MAJORDOMO From Majordomo header PLEASE_READ Subject =~ /please read/i describe PLEASE_READ Please read this! Please oh please oh please!