Posted on Thu 30 October 2014

two stage mail filtering

Sure, you have a system which automatically filters incoming mail into appropriate folders – most of these are for mailing lists, a few from specific companies or people – but you still have mail that comes in to your inbox specifically because you want to see it and deal with it.

After you’ve read it and done something about it, you want to archive it, because storage is cheap and more reliable than your memory. Do you throw it all in a pile?

Some people do throw it all in a pile, and trust to their full-text indexer (mairix, mu, notmuch…) to find it for them later. If you don’t have a full-text search system, any of the three I just mentioned are a good idea.

Even if you do have that set up, sometimes you just want to browse. It sure would be nice if you could do that without sucking in 120,000 messages to find the ones about credit cards, right? And the obvious answer is that you save messages to folders rather than dumping them in one pile.

Let’s do that automatically, with a second stage mail filter. Since I use maildrop as my incoming filter, I’ll use it for my archive filter as well. If you like procmail, use that. Any filter that can use a non-default rules file will work.

In an incoming mail filter, you often filter on List-Id, Mailing-List, Sender and other specialized headers. So far I’ve found that those aren’t very useful for an archive filter. Mail that you want in your inbox doesn’t come from a mailing list. Most matches will be on From: or To:.

Start with a new file. Maildrop defaults to $home/.mailfilter, so we’ll write $home/.mailfilter-archive:

   if (/^From:.*root@.*localdomain/:h)
   to "| /usr/local/bin/deliver-to-maildir seen $HOME/Maildir/.system/"

   if (/^From:.*@retailer.com/:h)
   to "| /usr/local/bin/deliver-to-maildir seen  $HOME/Maildir/.commerce/"

   if (/^To:.*school@domain.edu/:h)
   to "| /usr/local/bin/deliver-to-maildir seen $HOME/Maildir/.school/"

   if (/^To:.*family@localdomain/:h)
   to "| /usr/local/bin/deliver-to-maildir seen $HOME/Maildir/.family/"

   #default
   to "| /usr/local/bin/deliver-to-maildir seen $HOME/Maildir/.archive/"

deliver-to-maildir is courtesy of Edward Speyer – I’m using it specifically because of the ability to specify that the mail goes in the Maildir/cur directory, rather than new which is what a naive use of to or cc would do.

Next, we need to be able to summon this filter from mutt. In your .muttrc:

macro index Z "<enter-command>unset wait_key\n<pipe-message>maildrop $HOME/.mailfilter-archive<return><delete-message><enter-command>set wait_key\n"

I specify the scope of the macro as index because it’s most useful when you have finished dealing with a message – I suppose that the pager might be a useful additional scope. Z becomes the key to automatically file a message after you’re done with it; if the filter doesn’t know where to put it, the default at the end kicks in and drops in a big archive pile, which is not worse than before.

  • 2019 edit: deliver-to-maildir is defunct, but fear not: there’s an even better way to do this. See the updated article

© -dsr-. Send feedback or comments via email — by continuing to use this site you agree to certain terms and conditions.

Built using Pelican. Derived from the svbhack theme by Giulio Fidente on github.