April 13, 2006

Process your email with procmail

Author: Shashank Sharma

Mutt is a fine command-line email client, but it lags Evolution and Thunderbird in its ability to do email filtering. The procmail mail processing utility can help. It is highly configurable, allows for far better email filtering than Thunderbird, and as is customary with command-line applications, it is fast. While procmail is most commonly employed on the server side, its ability to handle POP and IMAP protocols makes it useful for desktop users as well.

Procmail is a Mail Delivery Agent (MDA), meaning it can be used along with a Mail Transfer Agent (MTA) such as mutt or sendmail to filter messages. Procmail processes all messages before they are delivered to your mailbox. You can have your incoming messages distributed into various folders based on preset criteria such as the subject of a message or the recipient. The use of regular expressions for creating rules and the ability to run multiple rules on messages make procmail a very precise mail filtering program.

To begin using procmail on the desktop, you need to create a .forward and a .procmailrc file in your home directory. The .forward file makes all incoming messages run through procmail, and the .procmailrc file specifies settings such as the location of mailboxes and the mail filtering rules.

Your .forward file must include the line |/usr/bin/procmail. This 'pipes' all incoming mails to procmail. If you use fetchmail to connect to your mail server and downloading messages, you can run fetchmail -m "/usr/bin/procmail -d %T" to pass all messages to procmail for processing.

A basic .procmailrc file might look like this:

# .procmailrc file

PATH=/usr/sbin:/usr/bin
MAILDIR=$HOME/mail  #location of your mailboxes

PATH which tells procmail where to look for other programs, such as sendmail, and MAILDIR is the location of your mailboxes. I have a directory named mail in my home directory within which I have other directories where procmail delivers messages.

Now we need to write the rules for filtering messages, which procmail calls recipes. There are three parts to every procmail recipe. First, :0 indicates the start of a recipe. Next, the * refers to the start of the condition for filtering messages. Lastly, the action line specifies the name of the folder where messages should be delivered if the condition is true.

Here is my .procamilrc file, which I use to filter messages from my friends and a couple of mailing lists.

# .procmailrc file

PATH=/usr/sbin:/usr/bin
MAILDIR=$HOME/mail  #location of your mailboxes
DEFAULT=$HOME/mail/priority  #any mail that is not filtered into some other folder gets here

#The recipes begin

#these are my friends
:0
* ^From:.*(linuxlala\@yahoo\.co\.in|shashankjee@gmail\.com)
$MAILDIR/buddies

#separate directories for my mailing lists
:0
* ^TOcc-licenses@lists\.ibiblio\.org
$MAILDIR/cc-license

:0
* ^TOindlinux-group@lists\.sourceforge\.net
$MAILDIR/indlinux

# default rule, drops messages into the default box
:0
* .*
priority

You can add comments anywhere in your .procmailrc file except in the condition lines. The first condition, ^From:. ensures that all messages from linuxlala@yahoo.co.in and shashankjee@gmail.com are dropped into the $MAILDIR/buddies directory. Though we did so here, we don't need to specify the entire path to folders when writing recipes. Simply writing the folder name is enough, since we have specified the MAILDIR path. Writing buddies instead of $MAILDIR/buddies would still drop all messages that satisfy the condition to the buddies folder.

Multiple checks can be applied to a condition, as I do for my buddies filter. I separate multiple email addresses with a pipe (|). ^TO is a special procmail expression that's useful when you wish to create filters for mailing lists. Note that there are no spaces between ^TO and the email address. Also note that you have to escape the dot in the email address by using the \ character, because the dot is a restricted keyword.

Now that we understand how they are created, let's work on some smart recipes.

Smart recipes

I use the following handy recipe to forward puzzles that any friend sends to me, while I keep a copy of it myself. That is, I have to perform two tasks at the same time. Here's how you can go about it:

# forward puzzles to a friend
#and also keep a copy
:0
* ^Subject:.*(puzzle)
{
  :0 c
  ! myfriend@buddy.com

  :0
  puzzle
}

Here we use a nested block (enclosed in braces) instead of an action line. This block allows us to put multiple recipes within it, which are used only if the parent recipe is true.

In both the recipes in the block, we don't have any condition statements. In the first action, the c flag is used to copy the message. Typically, a message will only run through the first recipe that is true. That is, if we don't use the c flag, we can't run the mail through the second recipe. The bang (!) before the email address indicates we want to forward the mail. The second recipe in the block delivers the mail to the puzzle directory.

Using procmail you can even filter spam. Here is how I do it:

#sort spam
:0
* ^Subject:.*(mortgage|debt|free|training|mentor)
garbage

If you are certain that messages that have any of these words in their subject are spam and you wish to delete them permanently, replace garbage from the action line with /dev/null. Use this with caution though, as mail deleted like this cannot be retrieved. A better approach might be to configure procmail with SpamAssasin.

You can even use procmail to convert HTML messages to text using this recipe.

Getting acquinted with regular expressions may seem like a tall order, but it allows you to create recipes such as this that change the subject of a message so that it stands out in your inbox. So get cooking!

Shashank Sharma is studying for a degree in computer science. He specializes in writing about free and open source software for new users.

Click Here!