Procmail Tips & Tricks

Debugging | Duplicates | Logging | Read Own Mail | Redeliver E-mail | Stripping Subject Tags | Vacation Setup

Some collected tips and tricks for the procmail local e-mail delivery program. For more documentation, see procmailrc(5) and procmailex(5). Be sure to debug new procmail recipes, as typos can easily ruin mail flow.

Debugging

Waiting for a message that may or may not fail on a new rule is a Bad Idea. Best to use a testing system; failing that, send a custom mail that triggers a match on the new rule somehow. For example, a rule that does a loose check for a mailing list can be triggered by adding a custom X-Match header with the address of the list in question, such as members@example.net.

Duplicates

Procmail can keep track of recent messages by the Message-ID header, and delete duplicates. This works well for mailing list crossposts or resent messages.

:0 Wh: msgid.lock
| formail -D 8192 ~/.procmail/msgid.cache

If you want duplicates stored elsewhere for review, use the following instead.

:0 Whc: msgid.lock
| formail -D 8192 ~/.procmail/msgid.cache
:0 a:
duplicates

Logging

Logging is good when debugging new ~/.procmailrc configuration files.

SHELL=/bin/sh
LOGFILE=$HOME/.pm_logfile
VERBOSE=on

For other sanity checks, use a recipe that does nothing, but writes log data somewhere else, like to syslogd(8). The following logs the current working directory, which may be needed if debugging a global /etc/procmailrc recipe set.

:0c
| logger `pwd`

Read Own Mail

To mark e-mail from myself but not to myself as non-new, I use the following rule. This works with mutt, and is good for mailing lists where one does not want to waste time marking mail you have sent and presumably already read as seen. The trick is to set the Status header to RO.

:0Wf
* ^From: .*user@example\.org
* !^TO_user@example\.org
|formail -I"Status: RO"

Redeliver E-mail

While not a procmail tip, the related formail script can be used to redeliver e-mail from a mailbox to a different e-mail address. The following assumes /var/mail/user is in a format formail understands, and that the messages should be sent to newuser@example.org via sendmail.

$ formail -n 3 -s /usr/sbin/sendmail newuser@example.org < /var/mail/user

Disadvantages of this method include the addition of new Received headers; if possible, copy delivered e-mail via some other means, such as rsync or via the Internet Message Access Protocol (IMAP).

Stripping Subject Tags

Mailing lists often set subject-line space consuming tags, which have no value where one is already filtering each list into a unique destination. In the following example, the list members@example.net sends e-mail with a subject tag of [Example-Members], which is removed by the formail recipe. I filter all mailing list traffic into a lists subdirectory under my mail folder to simplify management of mailing lists.

:0
* members@example\.net
{
:0Wf
* ^Subject:[ ]+(Re:[ ]+)?\[Example-Members\] \/.+
|formail -I"Subject: $MATCH"

:0
lists/example-members
}

Vacation Setup

Procmail vacation service setup in an example ~/.procmailrc. An autoresponse will be delivered to unseen senders. The example also includes a tip on forwarding the e-mail to another address.