The italian version is here.
Summary
- Create the sendmail configuration to use mailertable and the procmail mailer.
- /etc/mail/sendmail.mc
dnl Enable support for the mailertable FEATURE(`mailertable') dnl Add procmail to the list of available mailers MAILER(procmail)
- Ath the bottom, insert local rules to fend off loops (watch out for the TAB between '>' e '$')
- /etc/mail/sendmail.mc
LOCAL_CONFIG # Add .PROCMAIL to the pseudo-domain list CP.PROCMAIL LOCAL_RULE_0 # Strip .PROCMAIL and send via esmtp R$+ < @ $+ .PROCMAIL . > $#esmtp $@ $2 $: $1<@$2>
- Set up mailertable to route mail sent to specific domains (or even all mail, as in the last line) through the procmail mailer:
- /etc/mail/mailertable
example.com procmail:/etc/mail/procmailrcs/spam-filter wrotethebook.net procmail:/etc/mail/procmailrcs/spam-filter fake.ora.com procmail:/etc/mail/procmailrcs/uce-filter . procmail:/etc/mail/procmailrcs/any.rc
- Create procmail recipe files (owned by root.root, perms 644) in /etc/mail/procmailrcs (root.root, perms 755). Forwarded mail should extend with the .PROCMAIL pseudo-domain all addresses liable to be rerouted through the procmail mailer.
Discussion and example
The procmail mailer and mailertable
The MAILER(procmail) macro adds the procmail mailer defintion. This mailer is independent and separate form the local_procmail feature (used to filter incoming local mail).
Using the mailer requires routing mail to it through mailertable:
sendmail invokes procmail as follows:
The -Y flag selects Berkely Unix mailbox format, -m tells procmail that it's being invokde as a general mail filter, $h is set to the full path of the rule file, $f is set to the envelope sender address, $u to the envelope recipient address: these last two can ber referenced in tha rc file as $1 and $2.
Using the mailer requires routing mail to it through mailertable:
- /etc/mail/mailertable
example.com procmail:/etc/mail/procmailrcs/spam-filter . procmail:/etc/mail/procmailrcs/any.rc
# sendmail -bv crooks@example.com crooks@example.com... deliverable: mailer procmail, host /etc/mail/procmailrcs/spam-filter, user crooks@example.com # sendmail -bv spammers@spammers.net spammers@spammers.net... deliverable: mailer procmail, host /etc/mail/procmailrcs/any.rc, user spammers@wrotethebook.net
sendmail invokes procmail as follows:
procmail -Y -m $h $f $u
The -Y flag selects Berkely Unix mailbox format, -m tells procmail that it's being invokde as a general mail filter, $h is set to the full path of the rule file, $f is set to the envelope sender address, $u to the envelope recipient address: these last two can ber referenced in tha rc file as $1 and $2.
Local rules
If, after processing, the message is going to be forwarded again, care must be taken as to avoid mail loop when (if) the message gets back to mailertable processing. The standard technique is to add the pseudo domain .PROCMAIL to the recipient address within the procmail recipe files, and intercept this domain within sendmai.cf adding rules to the bottom of sendmail.mc like this (there must be a literal TAB between '<' and '$'):
- /etc/mail/sendmail.mc
LOCAL_CONFIG # Add .PROCMAIL to the pseudo-domain list CP.PROCMAIL LOCAL_RULE_0 # Strip .PROCMAIL and send via esmtp R$+ < @ $+ .PROCMAIL . > $#esmtp $@ $2 $: $1<@$2>
- LOCAL_CONFIG starts the section that will be copied to sendmail.cf verbatim;
- CP.PROMAIL inserts .PROCMAIL in class P: pseudo-domains that sendmail does not look up in the DNS;
- LOCAL_RULE_0 starts a section whose content is added to ruleset 0—also called the parse ruleset. The code is entered in the ParseLocal ruleset (ruleset 98). The parse ruleset risolvs an addresse in a delivery triplet.
- The R rule matches addresses of the form user@domain.PROCMAIL, and rewrites them as a triplet with with “esmtp”, as mailer, “domain” as hast and “user@domain” as recipient.
# sendmail -bv crooks@example.com.PROCMAIL crooks@example.com.PROCMAIL... deliverable: mailer esmtp, host example.com, user crooks@example.com
Procmail rule files, and an example
The (objectionable) purpose of this example is creating a sendmail instance who does a stealth forward of a copy of all transient mail to a set of configured addresses, while also delivering it to the intended address.
After setup, the second rule checks if the message ID is already in a cache file, and add it there if it isn't. This will avoid sending multiple copies of the message to the “espiones” when we have several recipients (in from:, cc: or bcc:). Lastly the message gets added a watermark header, for debugging.
- /etc/mail/sendmail.mc is as above.
- Mailertable:
- /etc/mail/mailertable
. procmail:/etc/mail/procmailrcs/any.rc
- We use two auxiliary rule files to set-up and tear down tha stage.
- /etc/mail/promailrcs/000_setup
# Debugging (use =no and =no to turn off) VERBOSE=on LOGABSTRACT=all # PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin LOGFILE=/var/log/proc_log #recommended #this is clearer OSENDER=$1 ORECIPIENT=$2 #Echoed to logfile at the end TRAP="echo '---------- End of procmailer ------' " # # Antiloop belt+suspender. This should never be triggered. :0 w * 1^0 ^X-Our-Anti-Loop: SET ! -f $OSENDER $ORECIPIENT.PROCMAIL
- /etc/mail/promailrcs/999_end
# # Insert Anti-loop header, add .PROCMAIL to recipient :0 w | (formail \ -A"X-Our-Loop: SET" \ ) | $SENDMAIL -oi -f $OSENDER $ORECIPIENT.PROCMAIL
- In any.rc is where the meat and potatoes are:
- /etc/mail/promailrcs/any.rc
# Setup INCLUDERC=/etc/mail/procmailrcs/000_setup # #flag 'c' creates a carbon copy for processing # Avoid sending duplicates :0 Whc | formail -D 16384 /tmp/idcache # #flag 'c' creates a carbon copy for processing #flag 'e' executes only if previous command failed. #espiones must contain addresses that are either local or .PROCMAIL terminated :0 ec | (formail -A"X-Our-Processed: SET" ) | $SENDMAIL -oi -f $OSENDER espiones #clean up and forward INCLUDERC=/etc/mail/procmailrcs/999_end
After setup, the second rule checks if the message ID is already in a cache file, and add it there if it isn't. This will avoid sending multiple copies of the message to the “espiones” when we have several recipients (in from:, cc: or bcc:). Lastly the message gets added a watermark header, for debugging.
- Since espiones is an aliased adress, non-local addresses in the alias need protection, too (as would literal addresses specified in the rule)
- /etc/aliases
espiones: foo@bar.com.PROCMAIL, baz@sna.fu.PROCMAIL, snafu
Additional Considerations
No doubt a task like this could be performed with a milter. Usage of the procmail mailer, as everything, has pros and cons.
Pros
- You do not need to select, write, or buy a suitable milter
- Yu do not have to learn the ins and outs of yet another piece of MTA related software
- You do not have to set up/debug the relevant communication between milter and sendmail
- You have one less demon (the milter) to take care of
Cons
- The mail flow becomes more involved and it is now controlled by yet another layer of configuration files (the rule files), and the same message will go through sendmail more than once.
- God help you if you come to rely on multiple loops of this machinery (it is tempting, I know).
- Procmail syntax sucks.