Go to TogaWare.com Home Page. GNU/Linux Desktop Survival Guide
by Graham Williams
Duck Duck Go

Procmail: Filter and Split Incoming Email


The procmail package provides a powerful mechanism for filtering incoming email, to split email that meet certain criteria into separate folders, to forward different emails on to other users, and to add extra headers to your email (e.g., X-Label headers to classify your email into categories you might define).

The procmail application will be invoked on any email that arrives for you by adding the following to your .forward file:


At the heart of procmail is the .procmailrc file. This contains all the rules that are applied to an email to determine what should happen to that email.

There is potential for procmail to be invoked in rapid succession, and thus if two procmails try to write to the one file there could be a problem. Thus procmail uses lock files to ensure this does not happen. A lock file will slow procmail down ever so slightly, so it is kept as an option specified in the configuration file (.procmailrc) rather than a default.

We can use formail to process an mbox format mail file (containing a collection of email messages) to pipe each message through our procmail processing:

$ formail -s procmail < /var/mail/kayon
This is only needed if you already have quite a few emails in there, and want to put them through the filter processing.

Procmail Variables

A .procmailrc might start with some variables being defined:

LOGFILE=$MAILDIR/procmail.`date +%Y.%m`.log
Here, PATH and SHELL are pretty standard for such a file. MAILDIR defines the default location for procmail paths (other procmail paths are then relative to this PROCMAIL). The DEFAULT mailbox is then specified, identifying where email will be stored (using the Maildir format here rather than the common GNU/Linux mbox format). Finally, we identify where the log file containing a log of each email messages and procmail's handling of it should be located.

Procmail Commands

:0	New recipe
:0:	Create a local lockfile while running
:0c	Continue processing this email even if this recipe matches
:0fhw	Filter using a pipe processing just the headers and wait

Procmail Recipes

We now start specifying recipes to handle email. A recipe generally contains a pattern to identify the email messages to which the actions of the recipe are to be applied. Generally, the first recipe that matches an email will process that email and then terminate the procmail processing of that message.

Carbon Copy all Email

For the especially cautious, or for when setting up procmail and testing it, you may want to keep a copy of every email that comes through. The first recipe might then be:

:0 c:
.incoming.`date +%Y.%m`/

All recipes are introduced with the :0. This can be followed by flags to control how the recipe works. The c flag above indicates that the email message is to be processed further by this specific recipe, but also a copy is to be pushed through to the remainder of the recipes within the .procmailrc file. The final : indicates that while procmail is processing the email message with this recipe, the recipe should be locked (so that no other procmail can write to the specified file at the same time).

After introducing the recipe with the :0 line, the next line in the above example is the action to be performed. In this case a file name is specified, beginning with a full stop and calling on the operating system to provide a current year and month string (e.g. 2006.01).

Forwarding Email

We can specify exactly which emails we wish a recipe to apply to. We do this for a recipe which will forward email on to another user, as well as keeping a copy for ourselves:

:0 c
* ^From.*abc.com
! abcmail@togaware.com
Lines beginning with * allow us to identify email messages to which the recipe should apply. This example forwards any email from particular users (any email from anyone with an email address that has the string abc.com in it), onto another user (abcuser@togaware.com). You can have a comma separated list of email addresses on to which the email should be forwarded.

With this recipe the recipe introduction uses the c flag to pass the email message on to following recipes as a carbon copy. Also, there is no trailing colon, so we are not requesting a lockfile for this recipe—in this case we don't need to use a lockfile because two instances of procmail will not interfere with each other when the action is to send the email on to someone else.

Other Examples

A sample .procmailrc:

  * ^Resent-Sender.*debian-devel-request@lists.debian.org

  * ^Resent-Sender.*debian-user-request@lists.debian.org

The :0 begins a recipe. The following : ensures the mail file is locked. A line beginning with * begins a condition. You can have multiple conditions within a recipe. The condition ^Resent-Sender.*debian-devel-request@lists.debian.org captures email sent to the debian-devel mailing list. This matches messages that include Resent-Sender: debian-devel-request@lists.debian.org in their header. The final line of a recipe is the mailbox into which procmail will send the mail.

Copyright © 1995-2020 Togaware Pty Ltd
Support further development through the purchase of the PDF version of the book.
Brought to you by Togaware and the author of open source software including Rattle and wajig.
Also the author of Data Mining with Rattle and Essentials of Data Science.