Managing Mail – procmail 

I like the way I manage my email, so I thought I should put it up on my blog, so that it might be of some use to others as well.

Here’s a list of what I use for what:

  • exim4 – To send outgoing e-mail
  • getmail – To fetch my mail from an IMAP server
  • procmail – To process my mail and deliver it into appropriate mailboxes
  • mutt – To read my mail
  • emacs – To compose mail 😀

Much of my configuration was ‘stolen’ from KMap (a.k.a Kumar Appaiah) including the getmailrc, exim4 configs, procmailrc, muttrc and .emacs :-D. I’ve put up full instructions on configuring this combination inside IIT Madras over here.

Most of the modifications I felt the need to make were done in the .procmailrc, which is the (default) configuration file for procmail. This post is going to focus on how I handle my mail in my procmailrc.

I love procmail. Using procmail is like doing ‘programmable’ mail filtering, or even better programmable mail processing! Here are some tidbits from my procmailrc:

Header

# kstar’s .procmailrc

SHELL=/bin/sh
MAILDIR=$HOME/Mail
LOGNAME=kstar
LOGFILE=$HOME/pmlog
LOG=”

VERBOSE=yes

This is what the beginning of my procmailrc looks like. It tells procmail various things, like that it should maintain a log, and deliver mail into ~/Mail and use /bin/sh as the shell. The debugging logs are sometimes helpful. procmail is so flexible that you can run into bugs in your procmail script which will cause mail to be delivered incorrectly.

Anything that starts with ‘#’ is a comment, as usual 😀

NOTE: procmail does not recognize ‘~’ as your home directory. You should use $HOME instead.

Deleting Unwanted Mail

I no longer am on these social networking sites, and I keep getting invites to various social networking sites – minglebox, hi5, blah blah blah. This is what happens to all those “invites”:

The Example:

# Trash all mail with the subject line “invites you”
:0

  • ^Subject.*invites you

trash/

The funda:

As the comment explains, what this block does is to put all mails which have “invites you” in the subject line into a mailbox called trash (which is a directory, as indicated by the ‘/’ at the end).

Every rule (procmail calls it a ‘recipe’ :-D) in your .procmailrc should begin with a ‘:0 <something>’. The last rule begins with a ‘:0:’.

That is followed by a list of conditions (optional). In this case, the line ‘* ^Subject.*invites you’ is a condition. The ‘*’ at the beginning tells procmail that this rule applies to all mails that match the regular expression that follows it. So only mail that matches the regular expression ‘^Subject.*invites you’ will pass. (^ matches the beginning of a line, .* matches 1 or more arbitrary characters)

The set of conditions is followed by exactly one action. In this case the action is ‘trash/’ which tells procmail to put the mail into a directory called trash under MAILDIR, i.e. into $HOME/Mail/trash in my case.

Another Example:

# Delete all birthday calendar requests
:0

  • ^Subject.*when’s your birthday

/dev/null

Another example, just to get the hang of it. In this case, the action is to put it into /dev/null which is the infinite sink for all unwanted information. Anything that is redirected into /dev/null vanishes from the realms of virtual existance for ever, ever and ever. (Don’t you wish you could ‘cat’ your institute’s dean into /dev/null as well?)

Processing mail to remove nonsense

The Example:

# Remove Yahoo! Groups links
:0 fHB

  • ^To.*yahoogroups\.com

| sed ‘/__\._,_\.___/,$d’

CAUTION: Do not use this code – this is only an example. It fails when attachments are sent with e-mail, and simply deletes them!

The Funda:

This rule looks a bit different from the earlier ones. It begins with a ‘:0 fHB’. The ‘f’ stands for ‘filter’. This tells procmail to treat this rule as a filter, i.e. to pass this through a command and deliver the output as if it were email. ‘HB’ tells procmail to look for the regular expression patterns (specified using ‘*’) in both the header (‘H’, which is default) and the body. I do this so that the links added by Yahoo! Groups at the end of emails are removed not only in direct messages from Yahoo! Groups, but also forwarded posts from Yahoo! Groups.

The second (functional) line is straightforward – it looks for the pattern ^To.*yahoogroups\.com in the Header and the Body (because we specified so) and applies the filter to only those mail which match this pattern. Notice that the ‘.’ is escaped, as in ‘\.’ – that’s part of the regexp syntax: In regexp ‘\.’ matches a ‘.’, and ‘.’ matches any character (it has “special meaning”).

The third line tells procmail to pipe the mail’s contents into sed, which cuts out all that is in the mail after the pattern “__._,_.___” (which Yahoo! Groups use at the end of the message). It also cuts out attachments, so be careful! (I’m still trying to find time to fix this 🙂 Any solutions for this problem are welcome.)

Copying mail to the inbox

I like my inbox clean, with no e-mail in it. I delete email as and when I read them – so that my inbox looks empty. Now, I want a backup of every e-mail I receive to be archived into an appropriate mailbox and a copy to be delivered to my inbox. So this is what I do:

The Example:

# Now copy all stuff to inbox
:0 c
inbox/

The Funda:

The ‘c’ in ‘:0 c’ stands for copy and tells procmail to apply this to a copy of the mail. So a copy of all mail that passes the tests described earlier, irrespective of content (no ‘*’ regexp conditions) gets into my inbox.

procmail stops looking for rules when it finds a destination for mail. So when it finds some mail which is a social networking invite, it writes it to trash/ (or /dev/null) and since it has found a target destination, it stops there. Thus, the above example copies only mails which have passed those tests into my inbox. But this is not a final target, because of the ‘c’ in the recipe header, so procmail will continue to look through other recipes as well.

Archiving Mail

I prefer to archive mail from different mailing lists or frequently-mailed people into different directories. So this is what I do.

The Example:

# All linuxusers_iitm mail goes into the linuxusers_iitm folder
:0

  • ^TOlinuxusers_iitm

linuxusers_iitm/

The Funda:

The above recipe puts all mail that was sent to an address containing linuxusers_iitm into a box called linuxusers_iitm/

Any mail that matches the condition here will find its final destination in linuxusers_iitm/ mailbox and procmail stops looking for additional rules.

The “TO” is a procmail standard macro that looks for whatever that goes after it (in this case ‘linuxusers_iitm’) in many email headers – To, Cc, BCc… Read the man page for more.

Another Example:

# All Facebook mail doesn’t get archived
:0

  • ^From.*Facebook

/dev/null

(I no longer am on Facebook, so this is useless for me now :-P)

The Final Target

The Example:

# Finally, that which matches nothing is archived into ‘archive’
:0:
archive/

The Funda:

This is the last rule in my .procmailrc

It puts any mail that hasn’t found a destination mailbox for archival into the ‘archive’ mailbox.

Resources:

I hope this was useful. Here are many other resources that I found with Google, to save you some trouble Googling 😛

Also, there are always the man pages on procmailrc – and they are a very useful source, indeed.

Advertisements