E-mail redirection and sorting
Mail Delivery Agent - MDA - Procmail is used to deliver e-mail on Unix mail servers at FIT and FEEC. Procmail can filter incomming messages using other programs, store to arbitrary mailboxes, resend to other recepients etc. Procmail follows the rules stored in file $HOME/.procmailrc (variable $HOME is users' directory on Unix server - Eva for FIT students, Fest for FEEC students). File .procmailrc may contain variable defintions as well. If there is no .procmailrc in user's home directory all incomming mail messages are stored into file /var/mail/login where login is user's login name.
Note: Mail redirection via .forward file should be avoided since it may cause mail loops.
Email comprises of headers and a body. The contents of mail message is stored in the body. Headers section is group of lines in the beginning of message which contain legible email information. The format of headers is strictly defined. Many header lines are just informative and some are meaningfull for user (e.g. Subject or From headers). Email clinets usually display headers intended for user only. Each header begins with keyword followed by colon, e.g. From:. Simple email message may lok like this:
Delivery rule for procmail
The rules consist of flags, conditions and a line of action. The rule is generaly of form:
The beginning of the rule
Each rule begins with :0. Digit zero may be followed by flags. If digit zero or flags is followed by another colon procmail should use local lock file. Lock file name should be specified. If there is none the name of mailbox from action line is used followed by $LOCKEXT (default .lock). Name of implicit lock file is not possible to determine when forwarding or processing using pipe.
Locking is required for delivering to mailbox (i.e. writing file) and for processing action by external program which writes to file. Locking is not necessary and should not be used for forwarding mail to another address.
Why should we lock? Procmail may be invoked for delivering several messages for one recepient. In such situation several processes may try to write to the same file (e.g. mailbnox). Without locking this would result in mixed messages and corrupted mailbox structure. With locking the first process following given rule creates locking file. When another process trie to follow the same rule an attempt to create lock file fails. The second process then waits while the first one finishes it's task and deletes locking file.
Conditions are optional. If there is none specified action is executed on all delivered emails. If there are more than one conditions (i.e. more lines) logical operator AND is applied. An action is executed if all conditions are fulfilled (true). Conditions are extended regular expressions compatible with egrep(1). Besides egrep regural expressions there are some other special conditions which have to begin with one of the following characters:
Note 2: By default procmail does not distinguish lower and upper case letters. This may be changed with flag D.
Action line specifies what to do with message when all conditions are met. To store a message to mailbox action line contains mailbox name. To forward mail action line begins with exclamation point ! followed by destination email address. To pass a message to external program action line begins with pipe character |.
There are two types of rules - delivering and non-delivering. If delivering rule is executed procmail stops proccessing of following rules and email is considered delivered. This behaviour may be changed using c flag. c. Delivering rules either save messag (or just it's headers or body) or pass the message to external program or resend message to another address. If non-delivering rule is executed procmail continues with next rule. Non-delivering rules pass the message through program or filter and the result is returned back to procmail for further processing.
If the conditions are not met action is not executed (mail is not delivered) and procmail continues with next rule. If all rules in .procmailrc are processed (i.e. action in no delivering rule was executed) email is delivered to mailbox defined by $DEFAULT variable. The variable $DEFAULT is set to /var/mail/login on servers at FIT and FEEC.
Example: mail sorting rule:
Example: forward mail to another server:
The other option is to use a bit more complex rule which returns an error message to original sender. The drawback of this rule is the original sender may in - case of delivery problem - receive an error message concerning address which he/she has not used. Even worse if the mail was sent to several recepients it may not be clear which one the error is related to. But by adding the Resend-From header when sending mail, the advanced email user will find address in the headers.
Example: resend mail to another server and store it locally:
Use of flag c instructs procmail to execute delivery rule and then continue with processing .procmailrc file. If no other delivery rule is met mail is stored to default incomming mailbox.
Example: resend email to mobile phone:(Note: quite unreliable, depends on quailty and restrictions on mail-to-sms gateway of your mobile operator, think twice before using it, no damages compensations may be claimed)
Similar to previous rule except second condition < 1000, which prevents resending messages larger than 1000 characters.
Regular expressions (RE)
Elementary regular expression is one character or string of characters. More complex regural expressions contain metacharacters with this meaning:
Some regular expressions examples:
Internal procmail variables H and B
Teh environment variable H contains headers of a mail while variable B contains a body.
Exaples of usage:
Special meaning of strings ^TO_, ^FROM_DAEMON, ^FROM_MAILER
The strings mentioned above are a sort of makro definitions which are replaced by quite complex regural expressions. String ^TO_ (both letters uppercase) checks headers containing destination of a message. Most common headers are To, Cc, Resent-To. The string ^FROM_DEAMON selects messages from most deamons and theč string ^FROM_MAILER selects messages from most of the mailservers.
^TO_ is replaced with:
(^((Original-)?(Resent-)?(To |Cc |Bcc) |(X-Envelope |Apparently(-Resent)?)-To) :(.*[^-a-zA-Z0-9_.])?)
This expression searches headers beginning with To, Cc, Resent-To, or some other recepient specification, character : follows and then any number of characters and email address starting with character -a-zA-Z0-9_..
^FROM_DEAMON is replaced with:
(^(Mailing-List : |Precedence :.*(junk |bulk |list) | To : Multiple recipients of |(((Resent-)?(From |Sender) |X-Envelope-From) : | >?From )([^>]*[^(.%@a-z0-9])?(Post(ma?(st(e?r)? |n) |office) |(send)?Mail(er)? | daemon |m(mdf |ajordomo) |n?uucp |LIST(SERV |proc) |NETSERV |o(wner |ps) | r(e(quest |sponse) |oot) |b(ounce |bs\.smtp) |echo |mirror |s(erv(ices? |er) | mtp(error)? |ystem) |A(dmin(istrator)? |MMGR |utoanswer)) (([^).! :a-z0-9][-_a-z0-9]*)?[%@>\t ][^<)]*(\(.*\).*)?)?$([^>] |$)))
^FROM_MAILER is replaced with:
(^(((Resent-)?(From |Sender) |X-Envelope-From) : | >?From )([^>]*[^(.%@a-z0-9])?(Post(ma(st(er)? |n) |office) |(send)?Mail(er)? | daemon |mmdf |n?uucp |ops |r(esponse |oot) |(bbs\.)?smtp(error)? | s(erv(ices? |er) |ystem) |A(dmin(istrator)? |MMGR)) (([^).! :a-z0-9][-_a-z0-9]*)?[%@>\t ][^<)]*(\(.*\).*)?)?$([^>] |$))
Links to further procmail information
More detailed description of .procmailrc file may be found in manual page "man procmailrc". Many examples of procmail rules are described in manual page "man procmailex". Further reading concerning procmai program and rules construction can be found at Proctut: Procmail Tutorials or Nancy McGough's "Procmail Quick Start".