From ArchWiki
Revision as of 16:21, 29 August 2012 by Chrisl (talk | contribs) (Tips and tricks)
Jump to navigation Jump to search

Procmail is a program for filtering, sorting and storing email. It can be used both on mail clients and mail servers. It can be used to filter out spam, checking for viruses, to send automatic replies, etc.

The goal of this article is to teach the configuration of procmail. This article asumes you already have either a email client (mutt, nmh, etc) or a mail server (sendmail, postfix, etc) working, that can use (or requires) procmail. It also assumes you have at least basic knowleadge on regular expressions. This article will give only a minimal explanation, for a complete manual, check the man procmailrc


Install the package procmail from the official repositories.

Configuration format

The configuration is going to be saved on ~/.procmailrc if this is the configuration for an email client, or on /etc/procmailrc if is going to be used by an email server.

The configuration is composed of two sections; assignments and recipes.


The assignments section provides variables for procmail



Recipes have the following format:

:0 [flags] [ : [locallockfile] ]
<zero or more conditions (one per line)>
<exactly one action line>

The conditions are extended regular expressions, with some few extra options. Conditions always start with an asterisk.

The action can be only a mailbox name, or an external program.

Flags and lockfile

For basic recipes, you don't need any flags. But they can be necessary if your script calls an external command. Here is a list of some of the most used flags:

  • f Consider the pipe as a filter.
  • w Wait for the filter or program to finish and check its exitcode (normally ignored); if the filter is unsuccessful, then the text will not have been filtered.


A condition is an extended regexp, starting with an asterisk, like this one:

* ^From.* someperson@\


An action can be something as simple as


in that case, the mail that complies with the condition will be saved on the work inbox.

It could also start with a pipe, which means the message is going to be passed to the standard input of the command following the pipe. A line like that could be something like this:

| /usr/bin/vendor_perl/spamc

By default, once a recipe's action is used, the processing is over.

If the f flag was used, the command can alter the message and keep reading recipes. In this example, the spamassassin command will add headers to the mail, with its spam status level, which later can be used by another recipe to block it, or store it on a different mailbox.

Tips and tricks


Here is an example using spamassassin to block spam. You should already have spamassassin installed and working.

# By using the f and w flags and no condition, spamassassin is going add the X-Spam headers to every single mail, and then process other recipes.
# No lockfile is used.
| /usr/bin/vendor_perl/spamc

# Messages with a 5 stars or higher spam level are going to be deleted right away
# And since we never touch any inbox, no lockfile is needed.
* ^X-Spam-Level: \*\*\*\*\*

# If a mail with spam-status:yes wasn't deleted by previous line, it could be a false positive. So its going to be sent to an spam mailbox instead.
# Since we don't want the possibility of one procmail instance messing with another procmail instance, we use a lockfile
* ^X-Spam-Status: Yes


An example using the clamav antivirus.

# We make sure its going to use the sh shell. Mostly needed for mail-only account that have /sbin/nologin as shell

# We'll scan the mail with clam using the standard input, and saving the result on the AV_REPORT variable
AV_REPORT=`clamdscan --stdout --no-summary - |sed 's/^stream: //'`

# We check if the word FOUND was in the result and save "Yes" or "No" according to that
VIRUS=`echo $AV_REPORT|sed '/FOUND/ { s/.*/Yes/; q  };  /FOUND/  !s/.*/No/'`

# formail is a filter that can alter a mail message, while keeping the correct format. We use it here to add/alter a header called 
# X-Virus with either value Yes or No
| formail -i "X-Virus: $VIRUS"

# And if we just added "X-Virus: Yes", we will also add another header with the scan result, and alter the subject, again, with the scan result.
# Since we are using the f flag, the mail is going to be delivered anyway.
* ^X-Virus: Yes
| formail -i "X-Virus-Report: $AV_REPORT" -i "Subject: [Virus] $AV_REPORT"