# @(#) pm-jaube.rc -- Jari's Unsolicited Bulk Email (UBE) filter.
# @(#) $Id: pm-jaube.rc,v 2.0 2001/07/27 22:45:50 jaalto Exp $
#
# {{{ Documentation
#
#   File id
#
#	.Copyright (C)  1997-2001 Jari Aalto
#       .$Created:	1997-09 $
#	.$Maintainer:	Jari Aalto <jari.aalto@poboxes.com> $
#	.$Keywords:	procmail, subroutine, UBE, spam, UCE filter $
#
#       This code is free software in terms of GNU Gen. pub. Lic. v2 or later
#	Refer to http://www.gnu.org/copyleft/gpl.html
#
#   Warning
#
#	Put all your UBE (aka spam) filters towards the end of your
#	.procmailrc. The idea is that valid messages are filed
#	first (mailing lists, your work and private mail, bounces) and only
#	the uncategorized messages are checked.
#
#   Overview of features
#
#	o   Requires procmail 3.11pre7+
#	o   Header based filtering: Minimum headers, Pegasus bulk mail,
#	    X-uidl validity check
#	o   Address based filtering: Numeric address, Invalid address (eg.
#	    me@myMarketing.global), UBE-like(friend,remove request.)
#	o   Text filtering: no html accepted, common advertising slogans.
#	o   You don't need external files: site block lists, the
#	    heuristics nail most of the UBE messages. Just plug in this
#	    module and you have UBE shield active.
#
#	Remember: this is not 100%, there is always some mishits, so
#	don't just junk messages to `/dev/null'. Instead set `JA_UBE_MBOX'
#	to the appropriate mailbox where you want to store the messages.
#
#   Description
#
#	My life changed when Daniel smith posted his spam.rc, where he had
#	gathered many tips and heuristics to filter UBE email. The filter
#	expressed work of many Procmail usears including [phil] and [dan].
#	You can get the original file by sending email with subject
#	`pm-dsspam.rc' to maintainer.
#
#	I modified the filtering rules a bit, took out some rules that
#	catched false email messages and made the package look a bit more
#	general so that it could be included via `INCLUDERC' in the standard
#	way. Not all ideas here are mine; many of them are directly from
#       Dan's original filter with slight modifications.
#
#	Thanks to Daniel and others, the UBE bomb days are gone, when this
#	filter is active. Couple of UBE email may still lurk into my
#	mailbox, but that's life; no shield is 100% proof.
#
#   Logging the events
#
#       The default subroutine `pm-jaube1.rc' does nothing fancy, but
#       writes a short log to `JA_UBE_LOG' and stores the message into
#       `JA_UBE_MBOX', which is sort of a brief biff log, where information
#       about incoming mail and what happened to it is stored. When message
#       arrives; date, from and subject should be written to the log and when
#       message gets filed; you should write the folder and reason.
#       Eg. my biff log looks like this:
#
#           1997-12-08 Foo <bar@x.com>  send pm-tips.txt
#               [ja-srv1; sent ema-keys.txt; Foo <bar@x.com> ;]
#           1997-12-08 work@home.com  Extra Holiday $$$$$
#               [jaube; Marketing-Big-ExitCode; LEGAL, MONEY-MAKING PHENOMENON]
#           1997-12-09 Denizen <logger@california.com>  [RePol] hiding
#           1997-12-09 david X <dx@a.com>  Re: Send list to incoming folder
#           1997-12-09 david X <dx@a.com>  Re: Send list to incoming folder
#           1997-12-09 OMC manager <omcman@foo.fi> "Environments updated"
#               [my; work-localenv]
#           1997-12-09 doodle@gruppe.org  Re: Gnus (Emacs Newsreader) FAQ
#               [my; emacs;   Re: Gnus (Emacs Newsreader) FAQ ]
#
#       First, I got a message to my fileserver and it responded. Then came
#       a UBE message that was identified and saved to UBE folder. Next 3
#       messages vere ones, that were filed to mailing-list folders and
#       there was no [] action displayed for them (left out due to high
#       volume of these messages). Second Last; that was internal work
#       message, Lastly someone mailed me about Emacs and that message was
#       filed to emacs folder.
#
#       The basic timestamp recipe in my .procmailrc is as follows.
#       Variable `TODAY' is `$YYYY-$MM-$DD' which you get from `pm-jadate.rc'.
#       The `LISTS' exclude mailing lists. I don' want to see their activity.
#       Variables `FROM' `SUBJECT' are read header fields from the message
#
#           BIFF    = $HOME/tmp/pm.biff
#
#           :0 hwic:
#           *$ ! $LISTS
#           |echo "$TODAY $FROM $FSUBJECT" >> $BIFF
#
#	Here is small perl script to print summary of trapped UBE
#	messages. It gives nice overview which recipes trap most of
#	the UBE messages.
#
#	    perl5 -ne '/jaube; (\S+)/; $s{$1}++;			\
#		 END {	$s = (map{$x += $_; $_= $x} values %s)[-1];	\
#			$i = int $s{$_}/$s *100;			\
#			for (keys %s) { printf "$s{$_} $i $_\n" } 	\
#		     }'							\
#		 pm-hdr.log						\
#		 sort -nr
#
#	Here is sample results of mine during 1998-08-16 - 1998-10-04.
#	There are total of 3248 UBE messages trapped.
#
#	  count  %  type
#	  ------------------------------------------
#           554 17  Marketing-CountBigLetterWords;
#           457 14  Marketing;
#           422 12  Marketing-SelectedBigLetterWords;
#           349 10  AddrBogus-ToFrom;
#           263  8  ReceivedFrom-Mismatch;
#           223  6  NoDirectAddress-ToCc;
#           216  6  HdrForgedPegasus;
#           164  5  AddrBogus-To;
#           151  4  MessageId;
#           121  3  FromReceived-Mismatch;
#           102  3  BodyHtml;
#           73   2  Received-IPError;
#           63   1  Identical-FromTo;
#           53   1  AddrInvalid;
#           15   0  From-nslookup;
#           9    0  HdrReceivedTime;
#           7    0  HdrX-UIDL;
#           4    0  Marketing-headers;
#
#   About bouncing message back with exitcode 67 or 77
#
#       The gneral concensus is, that you should not send bounches, the UBE
#       sender is not there, because the address is usually forged. Do not
#       increase the network traffic. Instead save the messages to folders
#       and periodically send complaints to postmasters that you find in
#       `Received' headers. If you decide to bounce anyway, be sure to do
#       `FROM_DAEMON' and mailing list tests before sending anything back.
#       It's not nice to be forced to apologize about boounces to a wrong
#       destination.
#
#   Required settings
#
#       PMSRC must point to source direcry of procmail code. This recipe file
#       will include
#
#       o   pm-javar.rc
#       o   pm-jaube1.rc        (includes pm-jastore.rc)
#       o   pm-janslookup.rc
#	o   pm-jaaddr.rc
#
#   Call arguments (variables to set before calling)
#
#	o   JA_UBE_VALID_ADDR, your email addresses or valid from addresses.
#       o   JA_UBE_RC, inclurerc called when ube was trapped. The default
#           action is to save the message to folder and write a brief log.
#       o   JA_UBE_LOG, if not empty, then a brief message is written to
#           this log file when ube was triggered.
#       o   JA_UBE_HDR, If JA_UBE_LOG  is _empty_, no log is written to
#           separate file, but a new header is added which tells which
#           recipe was triggered.
#       o   JA_UBE_MBOX, where to store the UBE. Add ".gz" extension to file
#           name if you want to save messages in gzip format. If this variable
#           is _empty_, the message is not stored anywhere, but falls
#           through pm-jaube.rc.
#       o   Various flags: Some of the ube detecting recipes give more
#	    false hits than nail real ube. Experiment with yourself and turn
#	    on or off the recipes that work for the kind of ube messages
#	    you receive.
#       o   JA_UBE_MAX_BIG_WORDS, the maximum count of big letter words in the
#	    meswsage that is tolerated. The current count 5 is rather
#	    conservative and I suggest you to increase it to prevent
#	    trapping too many false hits. Alternatively update JA_UBE_CAPS_OK
#	    to include accepted words.
#	o   JA_UBE_APPRENTLY_TO_MAX, how many Apparently-To headers are
#	    tolerated. Default is 3.
#	o   JA_UBE_MAX_HTML_TAGS, maximum count of html tags allowed in the
#	    body
#
#   Return values
#
#	If you use your own `JA_UBE_RC' then you can read these values,
#       when your script is called. They are also set after recipe
#       if `JA_UBE_MBOX' is empty "".
#
#	o   ERROR, is set to short ube trigger recipe reason
#	o   ERROR_MATCH, is set to some MATCH that happened while triggering
#	    UBE message.
#
#	The UBE reason ERROR is also seen in the separate header.
#
#	o   JA_UBE_HDR, header not added if this is empty ""
#
#   Usage example
#
#       It is best, that the UBE filterings are put last to your .procmailrc.
#       Handle all legimate messages at the beginning and save them to
#       folders. Only messages that didn't fit to previous categories shgould
#       be feed to to this recipe.
#
#           # - All legimite messages already handled and saved before this
#           # - Activate the filter only for messages that are not from
#           #   daemon and not from valid senders: like from "my" domain
#           #   and mailing lists and from soemwhere else. Define your
#           #   favourite VALID_FROM regexp.
#
#           RC_UBE     = $PMSRC/pm-jaube.rc
#	    VALID_FROM = "(my_domain|my_mailinglist)"
#
#           :0
#           *$ ! ^From:.*$VALID_FROM
#           *$ ! $from_daemon
#           {
#               JA_UBE_MBOX = "junk.ube"
#               INCLUDERC   = $RC_UBE
#           }
#
#	I have also received UBE messages that fool `FROM_DAEMON' test, so
#	you could also consider using this condition. The standard daemon
#	error message almost always has sentence "Transcript of session
#	follows" in the body.
#
#	    *   -1^0       ^FROM_DAEMON
#	    * !  2^1  B ?? Transcript of session follows
#
#	Intead of simple daemon test:
#
#	    *$ ! $from_daemon
#
#   File layout
#
#	The layout of this file is managed by Emacs packages folding.el/{{{}}}
#	tinybm.el/&tags and tinytab.el for the 4 tab text placement. See
#	also unix what(1) and GNU RCS ident(1).
#
#   Bug reports or updates
#
#       1998-08-24 Gregory Sutter sent update to his recipe.
#
#	1998-02-27 <bochmann@TUDURZ.urz.tu-dresden.de> (Henryk Bochmann)
#	reported that the ReceivedFrom test triggered all htmail messages.
#	Now Fiexed.
#
#   Change Log (none)
#
# }}}
# {{{ Variables

# ............................................................ &init ...

id    = "pm-jaube.rc"
dummy = "
========================================================================
$id: init:
"

:0
* !  WSPC ?? ( )
{
    INCLUDERC = $PMSRC/pm-javar.rc

    :0                  # This is extremely critical, so flag error if needed
    * !  WSPC ?? ( )
    {
        LOG = "(pm-jaube.rc) *** FATAL ERROR: couldn't include pm-javar.rc"
    }
}

# ....................................................... &variables ...

JA_UBE_RC   = ${JA_UBE_RC:-$PMSRC/pm-jaube1.rc}
JA_UBE_LOG  = ${JA_UBE_LOG:-"$HOME/pm-ube.log"}
JA_UBE_HDR  = ${JA_UBE_HDR:-"X-Ube-trigger"}
JA_UBE_MBOX = ${JA_UBE_MBOX:-""}

#   Define this variable to match _all_ valid From and To addresses that
#   are yours. Put your regexp inside prenthesis.
#
#   This defualts to "(logname|email@foo.com)" or "(logname|xxxx)" if EMAIL is
#   not defined.

JA_UBE_VALID_ADDR = ${JA_UBE_VALID_ADDR:-($LOGNAME|${EMAIL:-xxxx})}

#  A Macro

JA_UBE_FROM	= ${JA_UBE_FROM:-\
"(^(Apparently-|Resent-)*(From|Reply-To|Sender):|^From$NSPC+)"}

#   If message comes from these address, check that From address's domain
#   is found from Received header. If not, then it's forged.
#
#   This regexps must not include @ character because the matched string
#   is used later "as is" and included @ will confuse the algorithm.
#
#   1998-10-05 Jacques Gauthier <jacques_g@yahoo.com> informaed that
#   rocketmail was merged with lycosmail, but that rocketmail still exists.


JA_UBE_FROM_QUESTIONABLE = ${JA_UBE_FROM_QUESTIONABLE:-"\
(compuserve\
|aol\.\
|juno\.\
|netcom\
|earthlink\
|prodigy\
|freeyellow\
|hotmail\
|rocketmail\
|lycosmail\
|wowmail\
)"}

#   Allowed words that are all caps.
#   If message contains too many capitalized words, it's certainly UBE.
#
#   If you want _NO_ caps word checking, set:
#
#       JA_UBE_CAPS_OK = ""

JA_UBE_CAPS_OK  = ${JA_UBE_CAPS_OK:-\
"(AM|SMTP|IP|\
BEGIN|END|PGP|SIGNED|ENCRYPTED|MESSAGE|PUBLIC|KEY|BLOCK|PART|\
USA|FIN|FINLAND|GSM|EXIT|MIME|PCX|GIF|JPG|EMACS|XEMACS|POSIX|\
KB|HTTP|ASAP|FAQ\
)\>"}

# ...................................................... &thresholds ...

JA_UBE_MAX_APPRENTLY_TO	    = ${JA_UBE_MAX_APPRENTLY_TO:-3}
JA_UBE_MAX_BIG_WORDS	    = ${JA_UBE_MAX_BIG_WORDS:-5}
JA_UBE_MAX_HTML_TAGS	    = ${JA_UBE_MAX_HTML_TAGS:-20}

# ........................................................... &flags ...

#   Recipe enable flags. Turn off if you think they
#   give too many false hits. Set to 'yes' or 'no'

JA_UBE_FLAG_IP		      = ${JA_UBE_FLAG_IP:-"yes"}
JA_UBE_FLAG_MID		      = ${JA_UBE_FLAG_MID:-"yes"}
JA_UBE_FLAG_NUM_ADDR	      = ${JA_UBE_FLAG_NUM_ADDR:-"yes"}
JA_UBE_FLAG_TEXT_MARKET	      = ${JA_UBE_FLAG_TEXT_MARKET:-"yes"}
JA_UBE_FLAG_IDENTICAL_FROM_TO = ${JA_UBE_FLAG_IDENTICAL_FROM_TO:-"yes"}
JA_UBE_FLAG_TO_CC	      = ${JA_UBE_FLAG_TO_CC:-"yes"}

#	Should the From: addresses domain be validated with nslookup too?
#	Turning this option on may slow down UBE filter for firts 200
#	mails. After that the nslookup cache starts playing well.

JA_UBE_FLAG_FROM_NSLOOKUP   = ${JA_UBE_FLAG_FROM_NSLOOKUP:-"yes"}

# ........................................................... &other ...
#   Define DEGUG = "yes"  to get the headers into the LOGFILE

:0
* DEBUG ?? on
{
    LOG  = "$NL$NL ######## head-begin $NL"
    HEADER = `sed /^$/q`
    LOG  = "$NL ######## head-end $NL"
}

# ................................................... &private-flags ...

UUmessage  = "no"               # set initial value for flag
PGPmessage = "no"               # set initial value for flag

:0 B
*$ ^begin $d$d$d( )
*$ ^end
{
   UUmessage = "yes"
}

:0 B
* BEGIN PGP (SIGNED )?MESSAGE
{
   PGPmessage = "yes"
}

# .......................................................... &output ...

#   The UBE catch reason is stored into this variable

ERROR       = ""

#   If something was matched while detecting UBE, this will hold the match.

ERROR_MATCH = ""

# }}}

# ............................................................ &misc ...

# {{{ Invalid IP and domains, or From_

:0
*    JA_UBE_FLAG_IP ?? yes
*$  ^Received.*()\/\[[0-9\.]*([03-9]$d$d|2[6-9]$d|25[6-9])
{
    ERROR	= "Received-IPError"
    ERROR_MATCH = $MATCH
    INCLUDERC	= $JA_UBE_RC
}

#	1998-05-26 By <dattier@wwa.com> (David W. Tamkin) in
#	procmail mailing list. Message-ID: <m0ye6in-001HOsC@tekka.wwa.com>
#
#	Valid envelope From_ address looks like and anything different from
#	that is propably spam.
#
#		From foo@bar.com  Tue May 26 02:46:33 1998

:0 E
*$ ! ^From$s+$NSPC+$s+.*$weekdays
*$    From+s+\/.*
{
    ERROR	= "EnvelopeFrom-Invalid"
    ERROR_MATCH = $MATCH
    INCLUDERC	= $JA_UBE_RC
}


# }}}
# {{{ Invalid message id

#   By era eriksson <era@iki.fi>
#
#   Invalid Message-Id:s are likely UBE
#   Carefull, this seems to give false hits sometimes(and one is enough!)
#   You may want to disable this permanently.
#
#   There is software out there that breaks
#   RFC822 in that they don't include an "@" in the Message-Id. I don't
#   care too much since I see them in my spam tank but if you send stuff
#   to /dev/null, you'll probably want to take out the @ part.
#
#   rfc822 says message-id = word *("." word) "@" sub-domain *("." sub-domain)
#   Example: valid mail with <winATT-3.01-userid-999> as the message-id.
#   Example: <v03130307b0b2fc185d0b@[206.109.113.133]>

:0 E
*     JA_UBE_FLAG_MID ?? yes
*    ^Message-Id:
*$ ! ^Message-Id:\/$s*<[^$WSPC<>@]+@[^$WSPC<>@]+>$s*$
{
    ERROR	= "MessageId"
    ERROR_MATCH	= $MATCH
    INCLUDERC	= $JA_UBE_RC
}

# Empty Message-ID should never be generated by a real mail program

:0 E
*$ ^Message-Id:.*<$s*>
{
    ERROR	= "MessageIdEmpty"
    # ERROR_MATCH	= $MATCH
    INCLUDERC	= $JA_UBE_RC
}


# }}}

# .......................................................... &header ...

# {{{ Header: Required minimum

:0
* ^From:
* ^(Apparently-)?To:
* ^Date:
{ }
:0 E
{
    ERROR	= "NotEnoughHeaders"
    # ERROR_MATCH	= $MATCH
    INCLUDERC	= $JA_UBE_RC
}

# }}}
# {{{ Header: X-distribution

#   - Thanks to Pegasus mail, we have this.
#   - Interestingly, this nails 50% of the UBE messages alone.

:0
*$  ^X-Distribution:$s*\/(moderate|bulk|mass)
{
    ERROR	= "HdrX-Distribution"
    ERROR_MATCH	= $MATCH
    INCLUDERC	= $JA_UBE_RC
}

# }}}
# {{{ Header: Apparently-To

#   One typical UBE is where there is multiple apparently-to headers
#
#   Apparently-To:
#   Apparently-To:
#   Apparently-To:
#   Apparently-To:
#   Apparently-To:

:0 E
*$ -$JA_UBE_MAX_APPRENTLY_TO^0
*  1^1 ^Apparently-To
{
    ERROR	= "Excess Apparently-To $="
    # ERROR_MATCH	= $MATCH
    INCLUDERC	= $JA_UBE_RC
}

# }}}
# {{{ Header: X-uidl

# Headers that shouldn't exist in "real" mail
#
# Might need to be a little more particular here;
# Philip Guenther <guenther@gac.edu>: If a message comes into your
# mailbox that has the X-UIDL: header, and doesn't have your address in
# the header, then I would have strong doubts about it's legitamacy.
#
# Edward J. Sabol <sabol@alderaan.gsfc.nasa.gov>: E-mails with
# X-UIDL: headers are almost definitely spam unless they've been
# Resent-To: me by someone. Also, valid X-UIDL: headers have 32 hexadecimal
# digits exactly.

hex8 = "$h$h$h$h$h$h$h$h"

:0 E
*    ^X-UIDL:
*$ ! ^X-UIDL:$s*\/$hex8$hex8$hex8$hex8$s*$
*  ! ^Resent-To:
{
    ERROR	= "HdrX-UIDL"
    ERROR_MATCH	= $MATCH
    INCLUDERC	= $JA_UBE_RC
}

# }}}
# {{{ Header: bogus Pegasus

#   1998-08-24 Gregory kindly sent update to this filter. Thank you.
#
#	Pegasus mailer is the only mailer which legitimately generates
#	"Comments: Authenticated sender is ..." so kill anything else.
#	--Gregory S. Sutter <gsutter@pobox.com>
#
# Pegasus mailer is the only mailer which legitimately generates
# "Comments: Authenticated sender is ..." so kill anything else.
# This works for Pegasus versions 2.54 and below only, 2.55 and
# above don't generate the Authenticated Sender header.
:0 E
* ^Comments:.*Authenticated sender
* !^X-Mailer:.*Pegasus Mail
* !^Resent-To:
* !^Return-Path:.*owner-
{
    ERROR	= "HdrForgedPegasus"
    # ERROR_MATCH	= $MATCH            # what should be saved here?
    INCLUDERC	= $JA_UBE_RC
}

# }}}
# {{{ Header: Received

# ........................................................ &received ...

# Spamford's "Cyber-Bomber" generates "CLOAKED!" headers.
# Also catched bogus IP addresses

:0 E
* ^Received: \/.*(CLOAKED|\[(0)+\.(0)+\.(0)+\.(0)+\]).*
{
    ERROR	= "HdrReceived $MATCH"
    ERROR_MATCH	= $MATCH
    INCLUDERC	= $JA_UBE_RC
}

# Stealth Mailer bogus timestamp

:0 E
* ^Received: \/.*-0[67]00 \(E[SD]T\)
{
    ERROR	= "HdrReceivedTime"
    ERROR_MATCH	= $MATCH
    INCLUDERC	= $JA_UBE_RC
}

#   by wwgrol@sparc01.fw.hac.com (W. Wesley Groleau x4923)
#   Check that suspicious From site is mentioned in the Received headers

:0 E
*   ^Received:
*$   ^From:.*\/$JA_UBE_FROM_QUESTIONABLE
*$ ! ^Received:.*\/$MATCH
{
    ERROR	= "FromReceived-Mismatch"
    ERROR_MATCH	= $MATCH
    INCLUDERC	= $JA_UBE_RC
}


#   by wwgrol@sparc01.fw.hac.com (W. Wesley Groleau x4923)
#   Check also that suspicious Received site is mentioned in the From

:0 E
*$   ^Received:.*\/$JA_UBE_FROM_QUESTIONABLE
*$ ! ^From.*$MATCH
{
    ERROR	= "ReceivedFrom-Mismatch"
    ERROR_MATCH	= $MATCH
    INCLUDERC	= $JA_UBE_RC
}


# }}}

# ......................................................... &Address ...

# {{{ Address: Numeric

:0 E
*   JA_UBE_FLAG_NUM_ADDR ?? yes
*$ ^From:\/$s*$d+@.*
{
    ERROR	= "AddrNumeric"
    ERROR_MATCH	= $MATCH
    INCLUDERC	= $JA_UBE_RC
}


# And some spam uses bogus, all-numeric domain names:

:0 E
*   ^(From|To|Reply-To): \/.*@[0-9]+\.
{
    ERROR	= "AddrNumericDomain"
    ERROR_MATCH	= $MATCH
    INCLUDERC	= $JA_UBE_RC
}




# }}}
# {{{ Address: Invalid AOL

#   By John Gianni <jjg@cadence.com>
#
#   From Postmaster@aol.com: Valid AOL address can not:
#
#   - be shorter than 3 or longer than 10 characters
#   - begin with numerals
#   - contain periods, underscores, dashes or other punctuation
#
#   Valid AOL mail will have a short, verifiable Received path directly
#   from a resolvable host within AOL.COM to your mail host. Valid AOL
#   address are 10 characters or less and also has to begin with a
#   letter and not a number also.
#
#   If AOL address starts with anything else but A-Z; then it must be bogus.

:0 E
*   ^From: \/.*@aol\.com
* ! ^From: *([^a-z]|.+[^0-9a-z]|............).*@
{
    ERROR	= "AddrAOLinvalid"
    ERROR_MATCH	= $MATCH
    INCLUDERC	= $JA_UBE_RC
}

# }}}
# {{{ Address: Bogus

# Originally by Daniel Smith

word	= "[a-z0-9][-a-z0-9_.+]*"
word2	= "[-a-z0-9]"
tld	= "(com|gov|org|edu|net|int|[a-z][a-z])"

:0 E
*$ ! ^From:\/.*$word@($word2+\.)+$tld
{
    ERROR	  = "AddrBogus-From"
    ERROR_MATCH   = $MATCH
    INCLUDERC	  = $JA_UBE_RC
}


:0 E
*$ ! $SUPREME^0 ^To:\/.*$word@($word2+\.)+$tld
*$ ! $SUPREME^0 ^To:\/.*$JA_UBE_VALID_ADDR
{
    ERROR	  = "AddrInvalid-To"
    ERROR_MATCH   = $MATCH
    INCLUDERC	  = $JA_UBE_RC
}

#	If the From: line contains a @ but no . after it, it's suspect
#	By Era eriksson

:0 E
*    ^From:\/.*@[^ >]+>?
*$ ! ^From:.*@[^.]+\.
{
    ERROR	= "AddrInvalid-From"
    ERROR_MATCH	= $MATCH
    INCLUDERC	= $JA_UBE_RC
}

# }}}
# {{{ Address: UBE-like

#	let friends@site.com fall through

:0 E
*$ \/(${JA_UBE_FROM}|^TO)(remove|delete|free|friend@)
{
    ERROR	= "AddrUbeLike"
    ERROR_MATCH	= $MATCH
    INCLUDERC	= $JA_UBE_RC
}

# }}}

# ............................................................ &text ...

# {{{ text: html

#	Raw HTML; gives me creeps
#	Or you could match B ?? ()<(body[^<>]*|html)>

:0 E
*$   B ?? ^^$SPCL*<html>
*  ! H ?? ^(Mime-Version\\|Content-Type):
{
    ERROR	= "BodyHtml"
    ERROR_MATCH	= $MATCH
    INCLUDERC	= $JA_UBE_RC
}


:0 E
*$ -$JA_UBE_MAX_HTML_TAGS^0
* B ?? 1^1 ()</?(html|ul|ol|dl|dd|dt|li|br|p|pre|font|h[123456]|table|tr|td)>
{
    ERROR	= "BodyHtmlTags"
    # ERROR_MATCH	= $MATCH
    INCLUDERC	= $JA_UBE_RC
}

#   Known MEGA Spammers
#
#   They send 20Million spams a day! Try this (and we'll count
#   lines, not strings, just in case "cyberpromo.com" occurs twice in
#   the subject: for example, a legitimate letter from a friend has a
#   subject of "I'm sick of cyberpromo.com! Damn cyberpromo.com to
#   hell!").
#
#       1^1 ^.*\<cyberpromo\.com\>
#       * -1^1 ^Subject:(.*\<)?cyberpromo.com\>
#
#   While less "perfect", I can never remember the scoring rules, and I'd
#   likely use something like the following; plus, it's probably faster:
#   This catches "cyberpromo.com" in any header not starting with "S", and
#   it happens that none of the ones we need to catch it in start with "S",
#   so it probably works the same on "real-life" mail headers. The
#   condition can be modified to check for headers not starting with "Su"
#   by changing it to:
#
#     * ^([^S]|S[^u]).*\<cyberpromo\.com\>
#
#   if needed; further extensions should be obvious.)

:0 E
* ^[^S].*\/\<cyberpromo\.com\>
{
    ERROR	= "MegaSpammer"
    ERROR_MATCH	= $MATCH
    INCLUDERC	= $JA_UBE_RC
}

# }}}
# {{{ Text: Marketing slogans
# ....................................................... &marketing ...
# Notice that the MATCH is set to text line that triggered the UBE
#


dummy = "$NL$NL$id: Marketing-CaseSensitive $NL"

#       Case sensitive tests

:0 E HB D
*   JA_UBE_FLAG_TEXT_MARKET ?? yes
*   ()\/\<(GUARANTEED|FREE|OFFER|BONUS|QUOTE|CREDIT|LOWEST\
    |LEGAL(LY)?|SECRET|BULK|CLICK|BEST\
    |ORDER|FORM |NO RISK|(MAKE|MAKING).*MONEY|MLM\
    |MILLION|THOUSEND|NOW \
    ).*
{
    ERROR       = "Marketing-SelectedBigLetterWords"
    ERROR_MATCH	= $MATCH
    INCLUDERC   = $JA_UBE_RC
}


dummy = "$NL$NL$id: Marketing-Headers $NL"

#       If there is a dollar in header(subject), this is ube.

:0 E
*     JA_UBE_FLAG_TEXT_MARKET ?? yes
*    ^Subject:.*()\/(\$[0-9]|\<Free\>|!!!)
*  !  SUBJECT ?? Returned mail
{
    ERROR	= "Marketing-headers"
    ERROR_MATCH	= $MATCH
    INCLUDERC	= $JA_UBE_RC
}



dummy = "$NL$NL$id: Marketing $NL"

#	"Earn" must not match "learn"
#	Some marketing people try to be clever, they send
#
#	    for just $19.95, for incredible $19.95, for the sum 19.195
#	    for 19.95
#
#	So we match anything that has "for" and NN+.N+. There must not be
#	dollar in from, because the marketing could also use English pounds
#	or some other currency.
#
#	    \<for\>.*\<[0-9][0-9.]*\>

:0 E B
*     JA_UBE_FLAG_TEXT_MARKET ?? yes
*     UUmessage ?? no
*  !  SUBJECT ?? Returned mail
*   ()\/(naked\>|women|girls|nude\>|babe\>|cash\>|\<sex\>|adult\>\
    |\<earn\>|promote\>|income\>\
    |make.*money\
    |Money Making\
    |Make.*\$[0-9]\
    |(Low|fair|these) +price|price.*range\
    |want to buy\
    |Million E-mail Addresse\
    |bulk email\
    |No Credit Check\
    |this is your chance\
    |The most incredible stuff\
    |You have nothing to lo*se\
    |weight control\
    |lifetime membership\
    |Internet Business\
    |order(ing)? (now|form)\
    |Are you currently looking for affordable\
    |professional networking system\
    |global.*Advertising\
    |marketing resource\
    |Don't waste.*(dollars|money)\
    |bring to your attention\
    |limited.*(trial|time).*(offer)?\
    |examine our.*offerings\
    |We.*(guarantee|seek)\
    |You will not want to miss out on this\
    |\<for\>.*$[0-9][0-9.]\
    |For more information.*FREE\
    |This offer\
    |FREE.*\$[0-9]\
    |FREE.*(offer|bonus|sample)\
    |as low as.*$[0-9]\
    |$[0-9].*\<(minute|day|week|month|year)\
    |send \$.* to\
    |save up.*to.*%|save as much as.*[$%]\
    |sav(e|ing).*money\
    |Delete if not interested\
    |iemmc.org|cyberpromo|answerme\.com\|savetrees\.com\
    |wish to be (excluded|removed)\
    |to our remove list\
    |Remov(al|e) instruction\
    |remove.*email\
    |reply.*Remove\
    |(removed|deleted) +from +our +list\
    |our.*(mailing list|database)\
    |to be removed from.*list\
    |to reply to remov\
    |you were.*selected\
    |life style\
    |phone card|long distance\
    |Life Insurance\
    |forgive the intrusion\
    |Your.*(bonus|marker)\
    |(visit|Welcome|our) .*Web ?site\
    |(CALL|visit).*\<(us|today)\>\
    |!!!\
    ).*
{
    ERROR	= "Marketing"
    ERROR_MATCH	= $MATCH
    INCLUDERC	= $JA_UBE_RC
}

# }}}

# {{{ score: big letters

#   Count full words whose all letters have been capitalized
#   - If must not be uuencoded message,
#   - Ignore some commond words like: IP AM SMTP
#   - Word must have at least 3 big letters

:0 E BD
*     UUmessage  ?? no
*     PGPmessage ?? no
*$ !  JA_UBE_CAPS_OK ?? ^^^^
*$   -$JA_UBE_MAX_BIG_WORDS^0
*$   -1^1 ()$JA_UBE_CAPS_OK
*     1^1 ()\<[A-Z][A-Z][A-Z]+\>
{
    ERROR	= "Marketing-CountBigLetterWords"
    ERROR_MATCH	= "$= excess capitalized words"
    INCLUDERC	= $JA_UBE_RC
}

# }}}
# {{{ Header: From-To, To-Cc

#   By Era Eriksson, Sun, 08 Feb 1998 in procmail mailing list
#   The second To just purely for logging purposes to set MATCH

:0 E
*    JA_UBE_FLAG_IDENTICAL_FROM_TO ?? yes
*$ ! ^(From|To):.*$JA_UBE_VALID_ADDR
*    ^To: \/.*
* $  ^\/(From|Reply-To): $\MATCH
{
    ERROR	= "Identical-FromTo"
    ERROR_MATCH	= $MATCH
    INCLUDERC	= $JA_UBE_RC
}


#   If the message is not directly addressed to ME, then It's suspectible

:0 E
*    JA_UBE_FLAG_TO_CC ?? yes
*    ^(To|Cc):\/.*
*$ ! ^(To|Cc):.*$JA_UBE_VALID_ADDR
{
    ERROR	= "NoDirectAddress-ToCc"
    ERROR_MATCH	= $MATCH
    INCLUDERC	= $JA_UBE_RC
}

# }}}
# {{{ nslookup

dummy = "$NL$NL$id: __nslookup__ $NL"

#   Check if From address has valid domain. We can't check address, but this
#   is closest we get. This check must be at the end so that faster "text"
#   test are applied first.

:0 E
* UUmessage			?? no
* JA_UBE_FLAG_FROM_NSLOOKUP	?? yes
* ^From:\/.*
{
    INPUT	= $MATCH
    INCLUDERC	= $PMSRC/pm-jaaddr.rc	# explode address string

    :0
    *$ SITE ?? $a
    {
	INPUT	    = $SITE
	INCLUDERC   = $PMSRC/pm-janslookup.rc

	:0
	* ERROR ?? yes
	{
	    ERROR_MATCH	= "From $SITE nslookup fail/$ERROR_MATCH"
	    ERROR	= "From-nslookup"
	    INCLUDERC	= $JA_UBE_RC
	}
    }
}

# }}}


dummy = "$id: end:"

# pm-jaube.rc ends here
