# 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 header FROM_STARTS_WITH_NUMS From =~ /^\d\d/ describe FROM_STARTS_WITH_NUMS From: starts with nums 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 FROM_NAME_NO_SPACES From =~ /(^(?!=\?)\S+\s*<\S+\@\S+>|\(\S+\)$)/ describe FROM_NAME_NO_SPACES From: no spaces in name 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[^:]|[^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 Subject !~ /\S/ 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 MSGID_CHARS_SPAM Message-Id =~ /[\#:}{,!\/]/ describe MSGID_CHARS_SPAM Message-Id has characters indicating spam header MSGID_CHARS_WEIRD Message-Id =~ /["=\\~]/ describe MSGID_CHARS_WEIRD Message-Id has characters often found in spam 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 !~ /^((Sun|Mon|Tue|Wed|Thu|Fri|Sat), )?([\d ]?\d) (Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) (\d\d|\d\d\d\d) \d\d:\d\d(:\d\d)? (UT|[A-Z]{3,5}|[+-]\d\d\d\d)(\s+\(.*\))?\s*$/ describe INVALID_DATE Invalid Date: header (not RFC 822) # 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 DATE_YEAR_ZERO_FIRST Date =~ /[a-z]\s+0\d\d\d(\s|$)/ describe DATE_YEAR_ZERO_FIRST Invalid Date: year begins with zero header DATE_IN_PAST_03_06 eval:check_for_shifted_date('-6', '-3') describe DATE_IN_PAST_03_06 Date: is 3 to 6 hours before Received: date header DATE_IN_PAST_06_12 eval:check_for_shifted_date('-12', '-6') describe DATE_IN_PAST_06_12 Date: is 6 to 12 hours before Received: date header DATE_IN_PAST_12_24 eval:check_for_shifted_date('-24', '-12') describe DATE_IN_PAST_12_24 Date: is 12 to 24 hours before Received: date header DATE_IN_PAST_24_48 eval:check_for_shifted_date('-48', '-24') describe DATE_IN_PAST_24_48 Date: is 24 to 48 hours before Received: date header DATE_IN_PAST_48_96 eval:check_for_shifted_date('-96', '-48') describe DATE_IN_PAST_48_96 Date: is 48 to 96 hours before Received: date header DATE_IN_PAST_96_XX eval:check_for_shifted_date('undef', '-96') describe DATE_IN_PAST_96_XX Date: is 96 hours or more before Received: date header DATE_IN_FUTURE_03_06 eval:check_for_shifted_date('3', '6') describe DATE_IN_FUTURE_03_06 Date: is 3 to 6 hours after Received: date header DATE_IN_FUTURE_06_12 eval:check_for_shifted_date('6', '12') describe DATE_IN_FUTURE_06_12 Date: is 6 to 12 hours after Received: date header DATE_IN_FUTURE_12_24 eval:check_for_shifted_date('12', '18') describe DATE_IN_FUTURE_12_24 Date: is 12 to 24 hours after Received: date header DATE_IN_FUTURE_24_48 eval:check_for_shifted_date('24', '48') describe DATE_IN_FUTURE_24_48 Date: is 24 to 48 hours after Received: date header DATE_IN_FUTURE_48_96 eval:check_for_shifted_date('48', '96') describe DATE_IN_FUTURE_48_96 Date: is 48 to 96 hours after Received: date header DATE_IN_FUTURE_96_XX eval:check_for_shifted_date('96', 'undef') describe DATE_IN_FUTURE_96_XX Date: is 96 hours or more after Received: 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([\s:-]|$)/i describe ADVERT_CODE Subject: contains advertising tag # KOREAN_UCE_SUBJECT tests for 8-bit characters, it will not catch a very small # percentage of Subject: headers containing the Korean unsolicited mail tag # that are encoded with quoted-printable or base64. Rather than complicate # this rule, we will assume that MIME is decoded before this rule is evaluated, # even if that's not true yet. header KOREAN_UCE_SUBJECT Subject =~ /[({[<] *(\xbc\xba\xc0\xce)?\xb1\xa4( *|\x2e)\xb0\xed *[)}\]>]/ describe KOREAN_UCE_SUBJECT Subject: contains Korean unsolicited email 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_HEADER ALL =~ /\n(?:TO|FROM|SUBJECT|DATE):/s describe ALL_CAPS_HEADER Header with all capitals found 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 # Multizone / Multi meaning BLs first # Osirusoft, like MAPS RBL+ is a multi-meaning BL, so it is treated separately header RCVD_IN_OSIRUSOFT_COM rbleval:check_rbl('osirusoft', 'relays.osirusoft.com.') describe RCVD_IN_OSIRUSOFT_COM Received via a relay in relays.osirusoft.com # X prefix was used to insure that it was run at the end, but it's not needed # anymore since we run the rule with rblreseval -- Marc header X_OSIRU_SPAM_SRC rbleval:check_rbl_results_for('osirusoft', '127.0.0.4') describe X_OSIRU_SPAM_SRC DNSBL: sender is Confirmed Spam Source header X_OSIRU_SPAMWARE_SITE rbleval:check_rbl_results_for('osirusoft', '127.0.0.6') describe X_OSIRU_SPAMWARE_SITE DNSBL: sender is a Spamware site or vendor header X_OSIRU_DUL_FH rbleval:check_rbl('osirusoft-dul-firsthop', 'dialups.mail-abuse.org.') describe X_OSIRU_DUL_FH Received from first hop dialup listed in relays.osirusoft.com # Now, single zone BLs follow: # 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 rbleval:check_rbl('relay', 'relays.ordb.org.') describe RCVD_IN_RELAYS_ORDB_ORG Received via a relay in relays.ordb.org header RCVD_IN_VISI rbleval:check_rbl('relay', 'relays.visi.com.') describe RCVD_IN_VISI Received via a relay in relays.visi.com # Overzealous, blocking sparklist.com and yahoogroups with Confirmed Spam # Source records. not recommended. #header RCVD_IN_5_10 rbleval: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 rbleval:check_rbl('relay', 'orbs.dorkslayers.com.') describe RCVD_IN_ORBS Received via a relay in orbs.dorkslayers.com # DSBL catches open relays, badly-installed CGI scripts and open SOCKS and # HTTP proxies. list.dsbl.org lists servers tested by "trusted" users, # multihop.dsbl.org lists servers which open SMTP servers relay through, # unconfirmed.dsbl.org lists servers tested by "untrusted" users. # See http://dsbl.org/ for full details. # This is effectively an open relay BL, put in in the relay set too -- Marc header RCVD_IN_DSBL rbleval:check_rbl('relay', 'list.dsbl.org') describe RCVD_IN_DSBL Received via a relay in list.dsbl.org # Warning, several big ISP's mail relays (not open to outside people) are # listed on multihop. Do not set a high score on this. # Note too that those IPs often are listed in unconfirmed.dsbl.org at the same # time, so make sure that the score FUDGE_MULTIHOP_RELAY cancels one of the # two scores -- Marc header RCVD_IN_MULTIHOP_DSBL rbleval:check_rbl('multihop', 'multihop.dsbl.org') describe RCVD_IN_MULTIHOP_DSBL Received via a relay in multihop.dsbl.org # We want to count this in the open relay set so that someone doesn't get scored # twice (at least by default) for being listed there and in some other relay BL. # Users can request a double hit and double score by changing 'relay' with # 'unconfirmed_dsbl' or something like that, but I don't think it should be # a default -- Marc header X_RCVD_IN_UNCONFIRMED_DSBL rbleval:check_rbl('relay', 'unconfirmed.dsbl.org') describe X_RCVD_IN_UNCONFIRMED_DSBL Received via a relay in unconfirmed.dsbl.org # Other miscellaneous RBLs are listed here: header RCVD_IN_RFCI rbleval:check_rbl('rfci', 'ipwhois.rfc-ignorant.org.') describe RCVD_IN_RFCI Received via a relay in ipwhois.rfc-ignorant.org # NOTE: commercial test, see README file for details header RCVD_IN_BL_SPAMCOP_NET rbleval:check_rbl('spamcop', 'bl.spamcop.net.') describe RCVD_IN_BL_SPAMCOP_NET Received via a relay in bl.spamcop.net # NOTE: commercial tests, see README file for details header RCVD_IN_RBL rbleval: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 rbleval: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 rbleval:check_rbl('dialup', 'dialups.mail-abuse.org.') describe RCVD_IN_DUL Received from dialup, see http://www.mail-abuse.org/dul/ header X_RCVD_IN_DUL_FH rbleval:check_rbl('dialup-firsthop', 'dialups.mail-abuse.org.') describe X_RCVD_IN_DUL_FH Received from first hop dialup, see http://www.mail-abuse.org/dul/ # Now, you can apply rules to counter for the effect of two similar BLs matching # together -- Marc header FUDGE_DUL_MAPS_OSIRU rblreseval:check_two_rbl_results('osirusoft', "127.0.0.3", 'dialup', "127.0.0.3") describe FUDGE_DUL_MAPS_OSIRU Do not double penalize for MAPS DUL and Osirusoft DUL header FUDGE_RELAY_OSIRU rblreseval:check_two_rbl_results('osirusoft', "127.0.0.2", 'relay', "127.0.0.2") describe FUDGE_RELAY_OSIRU Do not double penalize for being an open relay on Osirusoft and another RBL header FUDGE_DUL_OSIRU_FH rblreseval:check_two_rbl_results('osirusoft-dul-firsthop', "127.0.0.3", 'dialup-firsthop', "127.0.0.3") describe FUDGE_DUL_OSIRU_FH Do not double compensate for MAPS DUL and Osirusoft DUL first hop dialup header FUDGE_MULTIHOP_RELAY rblreseval:check_two_rbl_results('multihop', "127.0.0.2", 'relay', "127.0.0.2") describe FUDGE_MULTIHOP_RELAY Do not double penalize if an IP is a multihop and an open relay # don't add headers without testing for false positives (usually Unix MTAs and # list software) and especially don't add From:, Reply-To:, Date:, Message-ID: header FORGED_RCVD_FOUND ALL =~ /\n(?:To|Importance|Content-Transfer-Encoding|Content-Type|Subject|X-Mailer|X-MSMail-Priority|X-Sender):.*\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 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 'From' yahoo.com does not match 'Received' headers header FORGED_JUNO_RCVD eval:check_for_forged_juno_received_headers() describe FORGED_JUNO_RCVD 'From' juno.com does not match 'Received' headers header FORGED_GW05_RCVD eval:check_for_forged_gw05_received_headers() describe FORGED_GW05_RCVD Forged 'by gw05' 'Received:' header found 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 eval:check_for_mta_message_id_later() describe MSG_ID_ADDED_BY_MTA_2 'Message-Id' was added by a relay (2) header MSG_ID_ADDED_BY_MTA_3 eval:check_for_mta_message_id_first() describe MSG_ID_ADDED_BY_MTA_3 'Message-Id' was added by a relay (3) # 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 # here, too header FROM_TOPICA From =~ /\@(?:\w\.)*email-publisher.com/i describe FROM_TOPICA From an address @email-publisher.com header USER_IN_BLACKLIST eval:check_from_in_blacklist() describe USER_IN_BLACKLIST From: address is in the user's black-list header USER_IN_WHITELIST eval:check_from_in_whitelist() describe USER_IN_WHITELIST From: address is in the user's white-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,3}).{0,40}?(?:\1[^@]*\2.{0,20}?){4,}/is describe VERY_SUSP_RECIPS To: contains similar usernames at least 5 times header VERY_SUSP_CC_RECIPS Cc =~ /\b([a-z][a-z])[^@,]{0,20}(@[-a-z0-9_\.]{0,3}).{0,40}?(?:\1[^@]*\2.{0,20}?){4,}/is describe VERY_SUSP_CC_RECIPS Cc: contains similar usernames at least 5 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 GAPPY_SUBJECT Subject =~ /\b(?:[a-z][-_\.\,\:\;\'\~\s]{1,3}){4,}/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! ### header existence tests (description is added automatically) # X-Fix example: NTMail fixed non RFC822 compliant EMail message # # X-PMFLAGS is all caps # # Headers that seem to only be used by a single spamming software and # are found together in the same message: # 1. X-MailingID and X-ServerHost # 2. X-EM-Registration and X-EM-Version # 3. X-Stormpost-To and X-List-Unsubscribe header CRON_ENV exists:X-Cron-Env header DATE_WARNING exists:Date-warning header IN_REP_TO exists:In-Reply-To header X_ANTIABUSE exists:X-AntiAbuse header X_AUTH_WARNING exists:X-Authentication-Warning header X_EM_REGISTRATION exists:X-EM-Registration header X_EM_VER_PRESENT exists:X-EM-Version header X_ENC_PRESENT exists:X-Encoding header X_ESMTP exists:x-esmtp header X_FIX_PRESENT exists:X-Fix header X_LIST_HOST exists:X-List-Host header X_LIST_UNSUBSCRIBE exists:X-List-Unsubscribe header X_MAIL_ID_PRESENT exists:X-MailingID header X_MESSAGE_ID exists:X-Message-Id header X_PMFLAGS_PRESENT exists:X-PMFLAGS header X_PRECEDENCE_REF exists:X-Precedence-Ref header X_SERV_HOST_PRESENT exists:X-ServerHost header X_SMTPEXP_VERSION exists:X-SMTPExp-Version header X_STORMPOST_TO exists:X-Stormpost-To header X_X_PRESENT exists:X-x header MIME_ODD_CASE ALL =~ /\nMiME-Version: /s describe MIME_ODD_CASE MiME-Version header (oddly capitalized) header OE_PI X-Mailer =~ /OutLook Express 3\.14159/ describe OE_PI X-Mailer contains 'OutLook Express 3.14159' header PGP_SIGNATURE_2 Content-Type =~ /protocol=.?application\/pgp-signature.?;/i describe PGP_SIGNATURE_2 Contains a PGP-signed message (signature attached)