#!/usr/bin/procmail # # NAME # spamfilter - Spamassassin based spam filter. # # SYNOPSIS # spamfilter [email=address] [spambox=mailboxspec] # # DESCRIPTION # Spamfilter is a procmail script, which first filters mail through # spamassassin. It then uses the headers added by spamassassin to # further process the mail. # # Mail with the special keyword NOSPAM: at the beginning of the # subject line is never connsidered being spam. # # Mail tagged by spamassassin as being spam is considered to # be spam. # # Mail not considered being spam is moved to the default mailbox. # # Mail considered being spam is moved to the spam mailbox specified # at the command line, or if no spam mailbox has been specified, to # the default ~/mail/Spam. The spammer will receive a notification # message that his mail has been deleted. This notification message # also informs that the spam filter can be bypassed by placing the # special keyword NOSPAM: at the beginning of the subject line. That # way, a legitimate sender whose mail is erroneously considered being # spam, will be able to resent the mail and bypass the spam filter. # # If a file .spamfilter.msg exists, the message in this file is # used as relply message to the spammer. A subject field can be # specified on the 1st line. The subject shall be precieded with # "Subject: ". # # No notification message is sent if the mail was marked to have # been auto generated. This prevents mail loops with auto # responders. # # Some spammers use your own e-mail address as from address. This # means the notification message is sent to yourself. Spamfilter # deletes notification messages which are received back. It looks # for your own e-mail address appearing in a header field # X-Spamfilter-From. # # Since spamfilter attaches part of the original message to it's # notification messages, there would be a risk that these notification # messages are seen as spam as well when the other user is also # using spamfilter. To prevent spamfilter from treating notification # messages from other users using spamfilter as spam, it adds a # header field X-Spamfilter-Bypass with the bypass keyword to the # notification messages. Mail containing the X-Spamfilter-Bypass # header field with the right bypass keyword is never treated as # spam. # # If a parameter email=address is present on the command line, # address is used in the notification message as an identification # of the mailbox. If this parameter is not present, the mailbox # is identified as username@hostname. # # Spamfilter will typically be called from a the file ~/.forward. # Such a ~/.forword file shall contain a line like: # # "|/usr/local/bin/spamfilter email=user@domain \ # spambox=/home/user/file" # # Note that if no parameters are added to spamfilter, it is desirable # to add #userid as a parameter. If two users have identical # destinations in their .forward files, mail sent to both users, # is delivered only to one. Adding a unique comment makes the # destinations different. # # Alternatively spamfilter can be called by including the following # lines in ~/.procmailrc file (or /etc/procmailrc): # # email=user@domain # spambox=/home/user/file # INCLUDERC=/usr/local/bin/spamfilter # # In this case the ~/.forward file shall contain a line like: # # "|/usr/bin/procmail #userid" # # To get rid of delivery failure notifications of spamfilter # notification messages, it is desirable to create the following # entry in the mail system wide mail alias file: # # spamfilter: /dev/null # # FILES # ~/.forward Contains e-mail adresses or programs # to which mail must be forwarded. # # ~/.spamfilter.msg Contains a the reply message, including the # subject field. # # ~/mail/Spam The user's default spam mailbox. # # ~/.procmailrc The users procmail configuration file. # # /etc/procmailrc The system wide procmail configuration file. # # /etc/mail/aliases The the system wide mail alias file. # # VERSION # 2.0 (12 April 2006) # # AUTHOR # Frits Wiarda, e-mail fwiarda(at)fwiarda.com # # SEE ALSO # spamassassin, spamfiltertest, procmail # # NOTES # This script has been tested with Red Hat Linux 8.0 with # spamassassin updated to revision 3.0.1. Note that for other # systems it can be necessary to modify line 1, containing # a reference to procmail. The set variables section below should # be checked as well. # # Debugging can be done by adding LOGFILE=filename and VERBOSE=on # to the command line. # ###################################################################### # # Set variables. # ###################################################################### BYPASS_KEYWORD="NOSPAM" MESSAGE_FILE=".spamfilter.msg" REPLY_FROM="MAILER-DAEMON@${HOST}" REPLY_FROM_NAME="Mail Delivery Subsystem" SPAMBOX="${HOME}/mail/Spam" CAT="/bin/cat" FORMAIL="/usr/bin/formail" HEAD="/usr/bin/head" LINEBUF=4096 RM="/bin/rm" SED="/bin/sed" SENDMAIL="/usr/sbin/sendmail" SPAMASSASSIN="/usr/bin/spamassassin" # Add -P when using spammassassin 2.x. SPAM_HEADER="^X-Spam-Flag: YES" ###################################################################### # # Delete mail generated by spamfilter for this e-mail address. # ###################################################################### :0 * $ ^X-Spamfilter-From: ${email:-${LOGNAME}@${HOST}} /dev/null ###################################################################### # # Mail is filtered through spamassassin. # ###################################################################### :0fW | ${SPAMASSASSIN} ###################################################################### # # We start asuming the mail isn't spam. # ###################################################################### SPAM="false" ###################################################################### # # If a special header generated by spamassassin is present, the mail # is marked to be spam. # ###################################################################### :0 * $ ${SPAM_HEADER} { SPAM="true" } ###################################################################### # # If the X-Spamfilter-Bypass header starts with the bypass keyword, # the mail is not treated as spam, even if it was marked before as # spam. It is a delivery failure notification generated by somebody # else using spamfilter. # ###################################################################### :0 * $ ^X-Spamfilter-Bypass: ${BYPASS_KEYWORD} { SPAM="false" } ###################################################################### # # If the subject field starts with the bypass keyword, the mail is # not treated as spam, even if it was marked before as spam. # ###################################################################### :0 * $ ^Subject: ${BYPASS_KEYWORD} { SPAM="false" } ###################################################################### # # If the mail has been marked as spam we will send an error message to # the sender. # # The flag indicates this recipe creates a copy of the mail. That means # the next recipe (which actualy delivers the mail) is executed as well. # ###################################################################### :0c * SPAM ?? true { # If the original mail was marked to be auto generated, with an # "Auto-Submitted:" header, no notification is sent. :0 * ^Auto-Submitted: * ! ^Auto-Submitted: no /dev/null # If the original mail was marked to be auto generated, with an # "Precedence: junk" header, no notification is sent. :0 * ^Precedence: junk /dev/null # If the original mail was marked to be auto generated, with an # "Precedence: bulk" header, no notification is sent. :0 * ^Precedence: bulk /dev/null # The original message, stipped of all except the most relevant headers, # and truncated to 20 lines is stored in a variable. # # The flag to this recipeindicates we have to wait until the pipe # finishes, while ignoring the pipes exit code. :0W ORIGINAL_MESSAGE=| ${FORMAIL} -zk -X "Date" -X "From" -X \ "To" -X "Cc" -X "Subject" | ${SED} -e "1d" | ${HEAD} -n 20 # A reply message is send, to inform the sender his mail has been # deleted. # # The flag to this recipe indicates the pipes exit code must be ignored. :0i | (if test -r ${MESSAGE_FILE} ; then ${FORMAIL} -rt \ -I "From: \"${REPLY_FROM_NAME}\" <${REPLY_FROM}>" \ -I "X-Spamfilter-Bypass: ${BYPASS_KEYWORD}" \ -I "X-Spamfilter-From: ${email:-${LOGNAME}@${HOST}}" \ -I "Auto-Submitted: auto-generated (failure)" \ -I "Precedence: junk" \ -I "Subject: Delivery failure notification" \ -U "`${HEAD} -n1 ${MESSAGE_FILE} | grep Subject:`"; \ ${SED} -e "/^Subject/d" ${MESSAGE_FILE}; \ echo ""; \ echo ""; \ echo ""; \ echo "----- Original message (which was deleted) -----"; \ echo "${ORIGINAL_MESSAGE}"; \ else ${FORMAIL} -rt \ -I "From: \"${REPLY_FROM_NAME}\" <${REPLY_FROM}>" \ -I "X-Spamfilter-Bypass: ${BYPASS_KEYWORD}" \ -I "X-Spamfilter-From: ${email:-${LOGNAME}@${HOST}}" \ -I "Auto-Submitted: auto-generated (failure)" \ -I "Precedence: junk" \ -I "Subject: Delivery failure notification"; \ echo "Your mail, which is included below, was not delivered to"; \ echo "the following address:"; \ echo ""; \ echo " ${email:-${LOGNAME}@${HOST}}"; \ echo ""; \ echo "It was deleted by the spam filter for one or more of the"; \ echo "following reasons:"; \ echo "- Your mail contained phrases that are commonly used by"; \ echo " advertisers;"; \ echo "- Your mail was suspected to contain a virus (e.g."; \ echo " because it contained an unsafe attachment);"; \ echo "- Your mail was sent from a site listed on a public"; \ echo " blacklist of sites that allow users to advertise;"; \ echo "- You are listed on the local blacklist of senders who"; \ echo " have sent advertisements before."; \ echo ""; \ echo "You can resend your mail and bypass the spam filter by"; \ echo "starting the subject field of your mail with:"; \ echo ""; \ echo " ${BYPASS_KEYWORD}:"; \ echo ""; \ echo "If you are an advertiser (commercial, political or"; \ echo "otherwise) please do not mail again."; \ echo ""; \ echo "Do not reply to this message. All replies to this message"; \ echo "are deleted without notice."; \ echo ""; \ echo ""; \ echo ""; \ echo "----- Original message (which was deleted) -----"; \ echo "${ORIGINAL_MESSAGE}"; fi ) \ | ${SENDMAIL} -oi -t -f ${REPLY_FROM} } ###################################################################### # # If the mail has been marked as spam before, it is delivered to the # spam mailbox (either the one specified at the command line or the # default). # # A lock file is created while writing to the mailbox (because of # the second colon). # ###################################################################### :0: * SPAM ?? true ${spambox:-${SPAMBOX}} ###################################################################### # # If no parameter mailbox=mailboxspec has been specified at the # command line, remaining mail is delivered to the user's default # mailbox. (Or if spamfilter was included in a .procmailrc file, # recipes after the include, will proces the remaining mail.) # ######################################################################