# Procmail QuickStart # http://www.ii.com/internet/robots/procmail/qs ################################################################### # # Configuration - Variables # # Next may be needed if you invoke programs from your procmailrc, but # it should not be needed for the simple sorting recipes on this page. # Details in Check Your $SHELL and $PATH in Troubleshooting below. ## SHELL=/bin/sh # Directory for storing configuration and log files # You can name this environment variable anything you like # (for example PROCMAILDIR) or, if you prefer, don't set it # (but then don't refer to it!) PMDIR=$HOME/Mail # Put ## before LOGFILE if you want no logging (not recommended) LOGFILE=$PMDIR/Procmail.log # Set to yes when debugging; default is no VERBOSE=yes # Messages that fall through all your procmail recipes are delivered # to your default INBOX PATH=/bin:/usr/bin:/usr/local/bin:/usr/lib:/local/bin: #DEFAULT=/var/mail/vlb # defaulted :-) # Personalized variables. Use your own name! MYNAME='Vicki' FULLNAME='Vicki Brown' EMAIL="${LOGNAME}@cfcl.com" ALIASES='heatercats@cfcl.com' # Stick some frequent comments into variables EGREP="egrep -iqs" # ignore case, quiet, suppress errors, GREPV="egrep -iqsv" # ignore case, quiet, suppress errors, FGREP="fgrep -iqwf" # ignore case, quiet, whole words # Blacklists # mail from these is summarily deleted BLACKLIST=$PMDIR/blacklist # people BLACKDOMAINS=$PMDIR/blackdomains # domains BLACKSUBJECTS=$PMDIR/blacksubjects # subject lines # Whitelists # mail from the following bypasses all other filtering WHITELIST=$PMDIR/whitelist # people WHITEMLISTS=$PMDIR/whitemlists # mailing lists OURDOMAINS=/local/docs/domains # cfcl "internal" domains # We ony partially trust sender domains but define them anyway # Note: it is best to add full addresses to the WHITELIST and WHITEMLISTS # if you can, rather than to only add the domain to the WHITEDOMAINS WHITEDOMAINS=$PMDIR/whitedomains # domains (only partially "trusted") # Extract parts of the header information SUBJECT="`formail -zxSubject:`" SENTFROM="`formail -zxFrom: -zxReply-To:`" SENTTO="`formail -zxTo: -zxCc:`" # We can no longer trust the domain on the From: header # but we can use it to check against blacklists FROMDOMAIN="`formail -zxFrom: | sed 's/^.*@// ; s/>//'`" # for the moment, we continue to trust a Reply-To address just a little REPLYDOMAIN="`formail -zxReply-To: | sed 's/^.*@// ; s/>//'`" # otherwise, look at the Received headers RCVDOMAIN="`formail -xReceived: | awk '/^ +from ([^ ]+)/ { print $2}'`" # domain matches below use fgrep. Recall that with fgrep the _patterns_ # are in the file; so, we match the acceptable patterns against # the domains and addresses found in the mail # i.e. a whitedomain of apple.com will match snowy.corp.apple.com in a # Received: from header # ################################################################### # From the procmaail man pages: ################################################################### # # Recipes # # Flags can be any of the following: # # H Egrep the header (default). # # B Egrep the body. # # D Tell the internal egrep to distinguish between upper # and lower case (contrary to the default which is to # ignore case). # # h Feed the header to the pipe, file or mail destination # (default). # # b Feed the body to the pipe, file or mail destination # (default). # # f Consider the pipe as a filter. # # c Generate a carbon copy of this mail. This only makes # sense on delivering recipes. The only non-delivering # recipe this flag has an effect on is on a nesting # block, in order to generate a carbon copy this will # clone the running procmail process (lockfiles will # not be inherited), whereby the clone will proceed as # usual and the parent will jump across the block. # # There are some special conditions you can use that are not # straight regular expressions. To select them, the condi- # tion must start with: # # ! Invert the condition. # # $ Evaluate the remainder of this condition according to # sh(1) substitution rules inside double quotes, skip # leading whitespace, then reparse it. # # ? Use the exitcode of the specified program. # # < Check if the total length of the mail is shorter than # the specified (in decimal) number of bytes. # # > Analogous to '<'. # # # Recipe action line # The action line can start with the following characters: # # ! Forwards to all the specified mail addresses. # # | Starts the specified program, possibly in $SHELL if # any of the characters $SHELLMETAS are spotted. You # # { Followed by at least one space, tab or newline will # mark the start of a nesting block. Everything up # till the next closing brace will depend on the con- # ditions specified for this recipe. Unlimited nest- # # Environment variable defaults # LOGNAME, HOME and SHELL # Your (the recipient's) defaults # # PATH # $HOME/bin # SHELLMETAS &|<>~;?*[ # # SHELLFLAGS -c # # ORGMAIL /var/mail/$LOGNAME # (Unless -m has been specified, in # which case it is unset) # # MAILDIR $HOME/ # (Unless the name of the first suc- # cessfully opened rcfile starts with # `./' or if -m has been specified, in # which case it defaults to `.') # # DEFAULT $ORGMAIL # # SENDMAIL /usr/sbin/sendmail # # SENDMAILFLAGS -oi # # HOST The current hostname # # # Use :0 Hc if you want fallthrough to another recipe # Use :0 H if a trigger will not pass through to another recipe ################ Blacklisting and summary deletion # # get these out of the way # :0 * ? (echo ${SENTFROM} | $FGREP ${BLACKLIST}) { :0 /dev/null } # Check domain in From: header against blacklists :0 * ? (echo ${FROMDOMAIN} | $FGREP ${BLACKDOMAINS}) { :0 /dev/null } # # real mail should have certain fields! # :0 H * !^Message-Id /dev/null :0 H * !^To /dev/null # Idiotic ploys :0 H * ^Subject.*Virus * ! ^To:.*${FULLNAME} /dev/null :0 B * .*(I send you this file in order to have your advice|See the attached file for details) /dev/null :0 H * ^From:.*(Microsoft|Security) /dev/null # Klez :0 B * ^(TVqQAAMAAAAEAAAA|TVpQAAIAAAAEAA8A) /dev/null # ################ ################ # # Redirect subscriptions to share # :0 H * ^From.*(TwoCents@sfchronicle.com) { :0 c ! rdm@cfcl.com :0 ${DEFAULT} } :0 H * ^From.*(comicmembers|mycomicspage|dailyink) { :0f * ^Subject: | formail -A 'X-Bypass: [COMICS-OK]' :0 c ! rdm@cfcl.com :0 ${DEFAULT} } :0 H * ^From:.*(applejobs|svc-jobs|jobmail.dice.com|jimsjobs|KITlist-Tech|jobfan|jobs-admin@perl) { :0f * ^Subject: | formail -A 'X-Bypass: [JOBS-OK]' :0 c ! rdm@cfcl.com :0 /dev/null } # # ############################################################### ################################################################ # White Listing # # Messages that match most of the recipes below will bypass SpamAssassin # to make that obvious on delivery, most of these recipes add an X-header # e.g. X-Bypass: [WLIST-OK] # # # Weblog mail # :0H * ^Subject:.*(notification - subscribe|New Comment Posted to|Weblog Update) { :0f * ^Subject: | formail -A 'X-Bypass: [BLOG-OK]' :0 ${DEFAULT} } # # Magic words # :0 B * ^.*(Mezzaluna|Sourceror|Taligent|Amador|Canta Forda|Maine Coon) { :0f * ^Subject: | formail -A 'X-Bypass: [MAGIC-OK]' :0 ${DEFAULT} } :0 H * ^Subject: *TTD: { :0f * ^Subject: | formail -A 'X-Bypass: [MAGIC-OK]' :0 ${DEFAULT} } :0 H * ^X-Mailer: Eudora for Macintosh { :0f * ^Subject: | formail -A 'X-Bypass: [EUDORA-OK]' :0 ${DEFAULT} } :0 * $^.*${MYNAME}.*wrote { :0f * ^Subject: | formail -A 'X-Bypass: [ATTRIB-OK]' :0 ${DEFAULT} } # # White Domains # # Check domain in Reply-To: header against whitelist :0 H * ? (echo ${REPLYDOMAIN} | $FGREP ${WHITEDOMAINS}) { :0f * ^Subject: | formail -A 'X-Bypass: [REPLYDOMAIN-OK]' :0 ${DEFAULT} } # Check domain in Received: header against whitelist :0 H * ? (echo ${RCVDOMAIN} | $FGREP ${WHITEDOMAINS}) { :0f * ^Subject: | formail -A 'X-Bypass: [RCVDOMAIN-OK]' :0 ${DEFAULT} } # # Mailing lists, Commercial notices # :0 H * ^From.*muttscomics { :0f * ^Subject: | formail -A 'X-Bypass: [COMICS-OK]' :0 ${DEFAULT} } :0 * ^.*forums.cocoaforge.com { :0fc * ^Subject: | formail -A 'X-Bypass: [LIST-OK]' :0 ${DEFAULT} } # Modify some subjects that don't have tags :0 f * ^TO.*procmail@lists.RWTH-Aachen.DE | sed -e '/^Subject:/s/ct:/ct: [Procmail]:/' :0 f * ^TO.*users.spamassassin.apache.org | sed -e '/^Subject:/s/ct:/ct: [SpamAssassin]:/' # # mailing lists (To) # :0 H * ? (echo ${SENTTO} | $FGREP ${WHITEMLISTS}) { :0f * ^Subject: | formail -A 'X-Bypass: [MLIST-OK]' :0 ${DEFAULT} } # # mailing lists (From) # :0 H * ? (echo ${SENTFROM} | $FGREP ${WHITEMLISTS}) { :0f * ^Subject: | formail -A 'X-Bypass: [MLIST-OK]' :0 ${DEFAULT} } # # Whitelist: Known Senders # :0 H * ? (echo ${SENTFROM} | $FGREP ${WHITELIST}) { :0f * ^Subject: | formail -A 'X-Bypass: [WLIST-OK]' :0 ${DEFAULT} } :0 H * ^From:.*(Yahoo Member Services|login_vlb) { :0f * ^Subject: | formail -A 'X-Bypass: [YAHOO-OK]' :0 ${DEFAULT} } # # ############################################################# ############################################################ # # SPAM SPAM SPAM SPAM # (http://www.detritus.org/spam/skit.html) # Now it's time to throw more things away! # # # I don't want mail with these subjects # :0 * ? (echo "${SUBJECT}" | $FGREP ${BLACKSUBJECTS}) { :0 /dev/null } # # Trash Windoze style Attachments # :0 * ^.*content.*name=.*\.(dat|cmd|com|cpl|exe|scr|pif|bat|vbs|vb|zip)" { :0 * ^.*content.*name=.*\.(dat|cmd|com|cpl|exe|scr|pif|bat|vbs|vb) !vsample@ironport.com :0 /dev/null } # # Tag Standard Ploys # SpamAssassin watches for these X-Procmail headers # # not To or Cc my address :0 Hf * ? (echo ${SENTTO} | ${GREPV} "${EMAIL}|${ALIASES}") | formail -A 'X-Procmail: [DEAR-OCCUPANT]' # Has my name in the subject :0 Hf * $^Subject: .*${MYNAME} | formail -A 'X-Procmail: [NAME-IN-SUBJECT]' # claims to be from my address but not my name :0 Hf * $^From: .*${EMAIL} * ! $^From: .*${FULLNAME} | formail -A 'X-Procmail: [MAYBE-FORGED]' # To my address but no full name field :0 Hf * $^(To|Cc): .*${EMAIL} * ! $^(To|Cc): .*${FULLNAME} | formail -A 'X-Procmail: [NO-REALNAME]' # ########################################################## ########################################################## # # Now send everything that's left to SpamAssassin # # The -s flag ensures that only messages smaller than 250 kB # (250 * 1024 = 256000 bytes) are processed by SpamAssassin. Most spam # isn't bigger than a few k and working with big messages can bring # SpamAssassin to its knees. :0fw | /usr/local/bin/spamc -s 256000 -t 60 # # Foreign character sets # If any of these made it through, throw them away # :0 H * ^(UNDESIRED_LANGUAGE_BODY|SUBJ_FULL_OF_8BITS|CF_I18N) /dev/null # # Check domain in From: header against whitelist # From: Domain is no longer entirely trustworthy # so we get a spam score first # :0 * ? (echo ${FROMDOMAIN} | $FGREP ${WHITEDOMAINS}) { :0f * ^Subject: | formail -A 'X-Bypass: [FROMDOMAIN-OK]' :0 ${DEFAULT} } # Delete high-scoring messages # According to the SA docs, mail with a score of 15 or higher is # almost certainly spam (with 0.05% false positives according to # rules/STATISTICS.txt). # # Personally, I've lowered that threshold to 7 - YMMV # :0 H * ^X-Spam-Level: \*\*\*\*\*\*\* /dev/null # ###################################################################### ###################################################################### # # At this point anything left is either # Spam Score < my threshold # OR # X-Spam-Status: No # OR # Somehow it missed SpamAssassin # Tag any of that last pack # :0 H * ! X-Spam-Checker-Version: { :0f * ^Subject: | formail -A 'X-Spamchk: [NOSCORE!]' :0 ${DEFAULT} } ############################################################# # Recipe Samples - no live code below this point ############################################################# # Everything below is commented out ############################################################# # Nothing to see here folks ############################################################# # # :0 Hc # * ^From.*rdm@cfcl.com # { # :0fc # * ^Subject: # | sed -e '/^Subject:/s/ct:/ct: REDIRECT:/' # :0 # ! vremote@cfcl.com # } # # # :0 c # * ^From.*vlb@apple.com # { # :0fwc # | sed -e '/^>/d' # :0fwc # | sed -e '/^-- /,$d' # :0 # ! vlb@apple.com # } # # #