HMC Homepage      CS Home

Sorting and Forwarding Mail with Procmail

Procmail is a program to sort, filter, forward, and otherwise organize incoming e-mail messages. This qref explains how to use procmail for some common sorting purposes. The examples given here will definitely work if you use pine to read e-mail on turing. They have not been tested under other circumstances but will most likely work anyway.

  1. To make procmail filter your mail you need to create a .procmailrc file in your home directory. If you already have a .forward file you should remove (or rename) it. (See the notes section for more information.)

  2. The .procmailrc file contains rules (commonly called "recipes") for handling incoming messages. A procmail recipe consists of a condition and an action, much like your normal everyday if statement. Each recipe is executed in turn; the first one that matches will be the one that is executed (but there is a way to have mail keep falling through recipes, keep reading).

  3. At the top of the .procmailrc you should set some environment variables. These control the way procmail behaves.
    Here is an example, the meaning of each variable is explained below.

    MAILDIR=$HOME/Mail
    DEFAULT=$HOME/mailbox
    LOGFILE=$MAILDIR/log

    MAILDIR - "Current directory while procmail is executing (that means that all paths are relative to $MAILDIR)." (rogue(5)) It is important to make sure that whatever directory you specify actually exists.

    DEFAULT - If an e-mail message does not match any rules it will be delivered to this mailbox.

    LOGFILE - This specifies a log file that will will store the time and subject of all messages received and which folder they were delivered to. It also logs some error messages. The file, named log in this example, can be read using less or your favorite text editor. It is recommended that you use a log file.

    HOME - A variable that is already defined by the shell. It stores the location of your home directory, usually /home/userName.

    $ - The value of a variable is gotten by putting a $ sign in front it.

    Read procmailrc(5) for more information on environment variables.

  4. Anything after a '#' (pound sign) is a comment. Condition lines start with an '*' (asterisk). You cannot have a comment on the same line as a condition. This will make more sense after we look at an example.

  5. The following is a procmail recipe.

    # Deliver mail addressed to thee linux-l mailing list # to the linux-l folder (in the MAILDIR directory).
    :0:
    * ^TO_linux-l@hmc\.edu.*$
    linux-l

  6. Anatomy of a procmail recipe:

    :0 [flags] [: [locallockfile]]

    All procmail recipes start with colon zero. Square brackets indicate optional things. If you want a lock file you should include the second colon. A lock file prevents messages from being overwritten if one arrives while a previous one is being processes. For most simple recipes the default lock file (no name given) is sufficient. If you want to name your own lock file you can do so after the second colon. There are several flags you can include after the zero but before the second colon to make procmail behave in various ways. A c after the zero will make a copy of the e-mail to keep falling through the filters. One can think of it as the "copy" flag, so it will get delivered to more than one mailbox. Perhaps I can have my .procmailrc setup so that important mail goes to my inbox and a filtered folder for eternal storage, and other mail goes straight to the filtered folder. Then when reading my inbox I need only delete the message, knowing that I have an archived copy already. Another REALLY USEFUL use of the 'c' flag is to have a backup folder that EVERYTHING gets copied to - it'll save your butt while setting up procmail such that a mistyped recipe doesn't make you lose your mail (see an example of this below). Read procmailrc(5) for more information on other available flags.

    * ^TO_linux-l@hmc\.edu.*$

    This line is a condition. Condition lines start with an asterisk. The only other thing on the line is a regular expression. condition lines. If the header of the incoming mail message matches the given regular expression then the action for that recipe is taken. This regular expression says that the message must be addressed to the address linux-l@hmc.edu. ^TO_ will be expanded by procmail as follows (as described in procmailrc(5) ): If the regular expression contains `^TO_' it will be substituted by `(^((Original-)?(Resent-)?(To|Cc|Bcc)| (X-Envelope|Apparently(-Resent)?)-To):(.*[^-a-zA-Z0-9_.])?)', which should catch all destination specifications containing a specific address. The '.' (period aka dot) character will match any character. The '*' (asterisk aka star) matches zero or more of the proceeding character. So the regular expression '.*' (dot star) matches zero or more of any character. In order to turn off a special character, you can proceed it with a '\' (slash) character. Regular expressions are the heart of procmail. To learn about all the possible regular expressions read procmailrc(5). Each recipe may have zero or more condition lines. If there are zero condition lines, the corresponding action will be taken for every message. Multiple condition lines are anded together.

    linux-l The line after the condition(s) tells procmail where to deliver the message. In this case it will be delivered to the linux-l folder. Read the note on pine folders before creating any for yourself. If you place an ! exclamation mark at the beginning of the action line procmail will forward the message to the address(es) that follow.

  7. The following are working procmail recipes. Feel free to use them.

    # If this is the first recipe in your .procmailrc file it will back up all your
    # before sorting it mail.
    # A copy of the message will be put into the backup folder.
    # Notice the c flag. That means a copy of the mail message will fall through
    # to the rest of your recipes.
    # Notice that there is no condition, therefor all messages are handled.
    :0 c:
    backup
    
    
    
    # Deliver any message generated by the request system into the request folder.
    # This regular expression matches if the subject line contains one of
    # NewReq, CloseReq, UpdtReq, AsgnReq, ReopnReq, or ChgPrty.
    :0:
    * ^Subject:.*(NewReq|CloseReq|UpdtReq|AsgnReq|ReopnReq|ChgPrty).*$
    request
    
    # Unlocked term messages delivered to the unlockedterm folder.
    :0:
    * ^Subject:.*(Unlocked Terminal - Security Risk)$
    unlockedterm
    
    
    # Any message sent to consult or consultant @turing.cs.hmc.edu or @cs.hmc.edu
    :0:
    * ^.*consult(ant)?@(turing.)?cs\.hmc\.edu.*$
    consult
    
    # Submissions. These are sent by the submit script.
    # Matches mail whose subject line contains the word "submission"
    :0:
    * ^(Subject):.*submission.*$
    submissions
    
    
    # Forward any e-mail to or from the cs-125-l list to the address 
    # anotherAccount@hmc.edu
    :0:
    * (^TO_|^From:.*)cs-125-l@hmc\.edu
    ! anotherAccount@hmc.edu
    
    # You can simulate a .forward file with the following recipe:
    # Notice there is no condition for this recipe. All messages match an empty
    # condition, therefor all messages will be forwarded to the given address.
    # When using a rule that forwards e-mail, be careful not to cause mail loops
    # by forwarding from one account to another and back again.
    :0
    ! anotherAccount@hmc.edu
    
    
    # If you get duplicate copies of the same e-mail message
    # procmail at all, you might be interested in the following procmailrc
    # recipe, which will ensure that you see only one copy of any message no
    # matter how many are delivered:
    :0 Wh: msgid.lock
    | /usr/local/bin/formail -D 8192 msgid.cache
    # This recipe uses the | in the action line to feed the header of the 
    # e-mail (only the header because the 'h' flag is used) to another
    # program, in this case formail.
    # The W flag means: 
    #    Wait for the filter or program to finish and check its
    #    exitcode  (normally  ignored);  if the filter is unsuccessful,
    #    then the text will not have been filtered.
    #    And suppress any `Program failure' message.
    # If you wish, you can replace
    # "msgid.cache" with the pathname of a file somewhere else in your home 
    # directory so that it is hidden from your daily activities.
    	

  8. Tips:

    Use a recipe with no condition as the first recipe in your .procmailrc file to have a rule that affects every message. Be sure to use the c flag or no other recipe will ever be executed.

    Use a recipe with no condition as the last recipe in your .procmailrc file as a default rule. Any message that does not get caught by a preceding rule will get caught by it.

Notes:

  • .forward files: If you are currently using a .forward file to forward e-mail from turing, and you want to use procmail, you should remove your .forward file. The .forward file gets executed before the .procmailrc file and prevents procmail from ever seeing an incoming message. The example section of this qref explains how to make procmail forward mail.

  • Procmail does not support the expansion of '~' tilde. If you want to refer to your home directory use $HOME instead.

  • Pine folders: Lets say you all your linux-l mail delivered to the linux-l folder. Do NOT create a directory called linux-l. I did that at first, its not a good thing. What you need to do is create a new folder within pine. To do this, open pine. Choose the L option to view the folder list. Then type a to add a folder. Pine will prompt you for the name of the new folder.

  • For more information:

    procmailrc(5) - Contains all the available environment variables, recipe flags, and extended regular expression. Very useful.

    procmailex(5) - Examples of recipes for a variety of situations. Very useful.

    procmail(1) - About the procmail program itself. Very tedious and not so useful for learning procmail.

    procmailsc(5) - Procmail weighted scoring technique. I don't know what that means.

    lockfile(1) - More on lock files. Unnecessary for most people.

    Regular expression are vital to procmail so you should become familiar with them. Procmail uses egrep regular expressions. The available special characters and phrases are listed in procmailrc(5) For more information about regular expressions, check out regexp(5) or the O'Reilly book "Programming Perl".

    Other tutorials on procmail can be found on the world wide web. Simply search google for them.


HMC Computer Science Department
Contact Information
Last Modified Tuesday, 14-Oct-2003 15:26:04 PDT