Back to main page

The Quick-N-Dirty Guide to maildrop

Although procmail seems to be more widely used, the maildrop program is preferred by some people. The documentation can be difficult for newcomers, however, its syntax for simple filtering is straightforward.

I want to thank my friend Tillman Hodgson whose pages can be viewed here for helping me understand how simple maildrop's syntax can be

1.) Do you have maildrop?

At a command prompt type
which maildrop

If you get an answer like /usr/bin/maildrop or /usr/local/bin/maildrop go to step 3, otherwise, go to step 2.

2.) Installing

For help with installing take a look at our QND guide to installing software. If your distribution isn't covered, then you may have to install from source. Fear not, we have a QND guide for installing from source as well. RedHat based systems don't have a package for maildrop. I've built it from source without problem, however Falko Timme has an excellent howto at howtoforge.com on using courier-imap and friends on RH based systems. He includes instructions for building your own maildrop rpm, as well as providing a link to his own maildrop.rpm created for Fedora 8. The article can be found here. One thing that he doesn't mention (but is mentioned in the comments) is that the rpmbuild might fail due to missing fam.h. This can be fixed by installing gamin-devel.

3.) Configuring

In our example, we will deal with two mailling lists, list1 and list2.org. We will then create another mailbox to deal with anything having linux in its subject line and then put personal email in its own box and add a line to catch everything else.

Many mailing lists will, if you hit reply when answering a post, simply send the reply to the mailing list. Other lists, (including many technical *nix lists) only reply to the original poster. Some people when replying, change this, sending it only to the group, but many people hit reply, let the To: line go to the original poster and just cc the group. In our example, list1 will be a list where replies automatically go to the entire group and list2.org will be one of those where reply would only reply to the original poster.

Using your favorite text editor, in your home directory, create a file called .mailfilter. Add the following

if (/^To: .*list1/)
        to Mail/IN-list1

if (/^(From|To|cc|bcc): .*list2\.org/)
        to Mail/IN-list2

if (/^Subject: *.linux/)
        to Mail/IN-linux

if (/^To: john/)
        to Mail/IN-personal

DEFAULT="Mail/IN-misc"

As you can see the syntax is rather simple. The first line begins with if (/^ and then the header word such as From: To: Subject: or whatever then /). The next line begins with to then the destination. If you want to handle more than one header keyword, such as To and cc then you put them in their own, second set of parentheses, separated by pipes. Periods (and other special characters) such as the one in .org are escaped with backslashes. One ends the list of rules with the DEFAULT keyword, and in this case puts the path to the default mailbox in double quotes.

Using multiples can also be used with conditions. For example, if my friend John Paul Jones has three email accounts, I could do the following

if (/^From: (.*john|.*jpjones|.*jjones24)/)
        to Mail/IN-jpjones

We take the condition, From: in this case and put the different possibilities in parentheses, again, separated by pipes then end with the usual /).

Although it's sometimes simpler (and less prone to error) to make a few entries, one can make various combinations. Taking our earlier example, let's say list2 can also be addressed as 2list. (For example, the FreeBSD-questions list will work as freebsd-questions or questions@freebsd.org)

if (/^(From|To|cc|bcc): (.*list2\.org|.*2list\.org)/)
        to Mail/IN-list2

As you see, the pattern is actually rather simple.

if (/^(thing1|thing2): (otherthing1|otherthing2)/)

(Note that the ^ before the group thing1 means the expression begins with thing1 or thing2--that's why we use a .* in case From or whatever doesn't actually begin with the letters thing. Also note the colon after test2 is for header lines like From, To, cc and the like). You could make separate entries for list2 and 2list or do it as shown above, combining it into one expression.

Now that we've created our .mailfilter, we only want the owner to have permissions on the file. So do a chmod

chmod 600 .mailfilter 
There are a few other basic, but useful things. The above samples are giving a case of if the mail meets this condition OR that condition. Sometimes, you want it to meet two conditions.

The maildropex(7) page gives various examples. Simplifying one of these, suppose you want to put all email from the boss about the project you're working on in its own mailbox.
if (/^From: .*boss/ && /^Subject: .*project/)
	to Mail/Project

This will take mail from the boss with Project in the subject line and put it in your project mailbox. It will only do this if both conditions are met, that is, only if it is both from the boss and has project in the subject line. Other mail from the boss, or mail that is not from the boss but has project in the subject line will not be caught by this rule. In this case, note that you need the / / around both the from condition and subject condition, however, there is only one set of parentheses.

Spaces, like other examples given above, can be escaped with backslashes. For example, if you want to catch the words project status in the subject line you would use
if (/^Subject: .*project\ status/)
	to Mail/project

One can also make a search case sensitive by, after the other conditions, typing :D. For example, if we only want to put PROJECT in the project mailbox but ignore anything that isn't in upper case
if (/^Subject: .*PROJECT/:D)
	to Mail/project

This will ignore Project, project, etc and only match something that has PROJECT, in upper case, in the subject line.

4.) Testing maildrop

Run your MTA (Mail Transfer Agent). If you use something like getmail run it once with the verbose flag
getmail -v

This will catch some, though not all, syntax errors, as well as other problems (such as allowing group or world permissions on your .mailfilter file). You can start by sending an email to yourself, then run your MTA. If you've followed these instructions, then the email should go into your IN-personal mailbox. (Gentoo and some others use .maildir rather than Mail--in that case, of course you would change your .mailfilter accordingly.) With the Maildir format, you may have to add a trailing slash to your rules, such as


if (/^To: john/)
        to .maildir/IN-personal/

If you use SpamAssassin, you can add this rule at the top of your .mailfilter file. (Assuming you wished to move everything that had a score of 4 and above to a spam folder to be checked later)

xfilter "/usr/local/bin/spamassassin"
if (/^X-Spam-Level: \*\*\*\*/)
        to Mail/IN-Spam

We use xfilter to run a command in .mailfilter. For example, I sometimes use a despammed.com address. If I do, it puts [despammed] in the subject line. I use xfilter to send a command to sed

xfilter "sed -e '/^Subject:.*\[despammed\]/s/\[despammed\]//g'"
One nice rule sent me by author Richard Dooling will catch most of those spams with the spam itself in embedded gifs.

if (/image\/gif/:b)
	to Mail/SPAM 
(or whatever you call your mail folder. The tricky part is the :b for body, as the default is to search :h for headers.) Many thanks to Richard.

Congratulations, you're done.

References

This QND guide gives a very simple setup. For more complex filtering rules see
man maildrop
man 5 maildropfilter
man5 maildropex
A page of mine about mutt which covers using maildrop with mutt

Back to main page