The first step is to get the
latest version of procmail. When this article was started the last version was
After getting the source code for the program, in order to install it
it will be necessary to uncompress and unpack it using the following command:
tar -xzvf procmail.tar.gz
The next step is to edit the files Makefile and
config.h. Since this article is only an introduction and to keep
things simple in this first introduction, we will not explain the various
configuration options of these files. The interested reader can consult the
manual pages and the documentation provided with the sources.
Nevertheless, it is convenient to mention the existence of the option
BASENAME in the Makefile. With this option we indicate
the directory base where procmail will be installed. From the basename directory
we indicate will hang other directories as bin and man.
Finally, to compile the package we must execute the command
Procmail can be installed for the whole system and then be called through some
rule of sendmail(8) or it can be by some user for his personal use.
In the later case, the user will indicate the use of procmail in his
.forward, where a line like the following should be present:
|IFS=' ' && exec /home/juan/procmail/bin/procmail -f- || exit 75 #juan
In this line I assumed that the user juan has installed procmail in
his HOME. For this particular line the
BASENAME that should have been specified during compilation
Procmail reads from its standard input. It checks the file
.procmailrc which is a configuration file that the user should
have in his HOME. This file defines certain rules that will tell procmail
what to do after reading a message. It can be directed to
check for certain strings in the header of the message, in order to
decide whether to save the message, ignore it, reply automatically, etc..
Procmail also let us deal automatically with the arriving mail or the mail stored
in a file.
The configuration file used is .procmailrc and it
must be placed in HOME.
Every line started with # is considered a comment.
Lines started with :0 or :0: indicate the
beginning of a new rule which tells procmail what to do with a message.
The lines started with * indicate a condition to be satisfied for
a rule to apply. This is the mechanism procmail uses to select which messages
require processing with the rule and which do not.
The remaining lines, that is, those not starting with a
:, or * are considered commands, in other words
the action to be applied by procmail to the message satisfying the
condition. Some possible actions or commands are deleting a message,
forwarding a message, saving a message, saving a message...
The first thing to be indicated in a
.procmailrc are some of the environment variables, here are some of
the variables I would recommend to define in your .procmailrc
Indicates the directory where procmail saves the files with mail messages.
This variable usually point to $HOME/mail or $HOME/Mail. Whether is one or
the other is a matter of the kind of mail reader being used.
Indicates the name of a log file where procmail leaves record of all the transactions
Indicates where to find sendmail, which will be used to automatically
Indicates where to find formail. This program is distributed together with
procmail and its purpose is to modify the mail headers or to reformat a
message before sending or storing a message.
File where a message is saved if procmail was not able to apply any of the
Anywhere in .procmailrc one can define an environment variable.
If the variable is written without the symbol = follow by a value,
such variable is removed.
Regarding rules, they come in two groups:
Rules that consider the message delivered after applying their
action and rules that do not.
The first rules are simple, after applying their action then
assume no further rules should apply to this message and therefore
The second type of rules, those that do not consider the message delivered,
upon applying their action are very useful when one wishes the possibility
of applying multiple rules and actions to the same message before delivery.
The general syntax for a rule is the following:
:0 [options] [ : [exclusion file] ]
* condition 1
* condition 2
* condition N
Lets go by parts analyzing this construction.
First every rule starts with a :0, after it may follow
any of these options:
H The condition is applied to the mail header.
B The condition is searched in the body of the message.
D When the condition is investigated, upper and lower cases are
A This rule is applied only if the previous one was.
a Like A, except that the execution of the previous rule
must have been carried out without errors.
E This rule is executed if the previous one was not.
e This rule will be executed if the previous one was executed but
exit with some error.
h The message header is passed to the command.
b The message body is passed to the command.
f The command is interpreted as a filter.
c Generate a carbon copy cc of the message. When executing a rule that
considers the message delivered with this flag, then one accomplishes a work
around its delivery, and further rules can be applied to the carbon copy
of the message.
w Wait until the command finish executing to receive its exit code.
W As the previous option but in case of error does not emit any messages.
i Ignore the possible typing errors.
r Writes the message such as it is. It does not test whether it ends
with a blank line.
By default, if no options are specified, the condition is tested on the
mail header (option H). The command receives in its standard input
both header as boy of the message (options h and b). There is no distinction
between upper and lower case.
After :0 and the possible options, a second
: may follow, if it does it indicates that the destination file
where the message is going to be written should be blocked to avoid two
processes writing simultaneously over the file. Optionally one can indicate the
exclusion file which is used as a lock.
Next follow the conditions, one per line and preceded by a
* character. Conditions are usually written as regular expressions
in order to find character string within the header or body of a message.
Regular expressions use the following symbols among others:
^ Beginning of a line.
$ End of a line
. Any character except a carriage return
* Zero or more times.
+ One or more times.
? Zero or more times.
[a-z] Range of characters, in this example from a to z.
[^a-z]Any character outside the range a to z.
a|b Either 'a' or 'b'
After the conditions come a single command. If the first character
of the command is any of the following then a special behavior onsets:
! The message is redirected to all the mail addresses indicated.
| If this symbol is continued by an executable then it is run
whenever the condition is satisfied. If nothing follows the symbol
the full text of the message goes to the standard output. If instead
the name of a variable follows |, then the result of the indicated command
is saved into that variable.
A situation where procmail can be very useful is in the management
of our mail. Let us suppose that we are subscribed to three Linux mailing lists.
each list is identified by the address of origin, for instance we could have
the following addresses
Under normal circumstances the messages from these mailing lists will
arrive together, at the same mail box, and if nothing is done they will
remain mixed up. It would be much easier if as the mail were arriving
if was sorted and stored in appropriate files.
Procmail can solve this problem easily. We could use a file
.procmailrc with the following simple rules to sort our mail
from the Linux mailing lists:
Let us examine carefully one of the rules. If you understand the
inner workings of a rule, then is easy to understand the rest because
the basic mechanism is always the same.
First one finds a :0 string that indicates the beginning of
a new rule. There are no further options so procmail will take the default
options for this rule: upper and lower case are indistinguishable, the condition
applies only to the mail header, the command receives both header and body of
In the next line one finds the condition, that as it was previously mentioned
is always identifiable because its first character is a *. The condition
is the following regular expression:
The substring ^From tells procmail to search for those lines
beginning by the substring From.
The following .* character, means any number of characters. We saw
before that in regular expressions a "." character is equivalent to
any character and that * refers to zero or more. Then
.* means that after the initial From there may be zero or more
Next should come email@example.com, which is the address
from where the messages originate.
Thinking a bit about the regular expressions, you will see that the following
lines would be recognize by this rule:
With this rule one can already distinguish messages coming from this
address and the others. So now that one has the message what shall be done with
The next line is the command (or action), and it indicates what to do with
the message. In this case it is supposed to be deliver to the file
linux-mx where it should be stored. In case of not indicating the
absolute path to the file, by default it will be considered relative to the
environment variable $MAILDIR.
Clearly messages arriving from different lists can now be distributed to
various files according to their origin (From field).
Other situation where procmail will be useful is for automatic replies.
It comes often handy, for example, if you wish to send your public PGP key
automatically to anyone that requests it by E-Mail
To do this, write a rule that will consider as a petition for
our PGP public key any message with the string PGP in its subject.
This rule can be written as:
| (formail -r ; cat $HOME/key.asc) | sendmail -t
This same idea can be applied to write the typical program that
lets people known we are off on vacation and that we will reply to
their E-Mail after coming back:
| (formail -r; cat $HOME/vacations.txt) | sendmail -t
In the last case there is no condition since all messages should
be sent the same notice.
Avoiding Infinite Loops in Automated Replies
In the previous examples no attempt was made to handle possible infinite
loops that sometimes occur when mail is answered automatically.
If a message whose origin is our own E-Mail address, the program would reply
to that address, then the reply would come back to us. This message would be
replied once more and so on in an infinity loop. In order to avoid it,
when answering the message one should add an extra line in the header to indicate
that message was already answered. Using the option -A of formail:
formail -r -A"X-Loop: firstname.lastname@example.org"
Where email@example.com would be your own E-Mail address. This way when
generating the header for the reply the line
X-Loop is added so that later on one can check for it with a new rule:
* !^X-Loop: firstname.lastname@example.org
| (formail -r -A"X-Loop: email@example.com" ;
cat $HOME/vacation.txt) | sendmail -t
This rule prevents an infinite loop because any message containing
in the header a line X-Loop will not satisfy the condition and
as a result will not be answered by procmail.
Another interesting rule for our .procmailrc is that which
decodifies the incoming mail encoded with uuencode(1) automatically.
The rule could be given as:
* ^begin 644 .*
Here it is explicitly indicated with the option
B that the rule's condition should only be tested on the
body of the message.
If the rule finds a line beginning with the string
"begin 644" it means that it has found the beginning of a file encoded with
uuencode(1) so it establishes the environment variable
MAILDIR, which is equivalent to changing the directory pointed by
that variable. From that moment on, all the print or display actions will be
perform taking the base directory indicated. In our case we are interested
on saving the received messages in $HOME/files.
Next there is a rule, without condition, that only pipes the message
to uudecode(1) for decodification. The original file will go to
Hopefully after this brief introduction to procmail, it is clear that
procmail is extremely versatile and it can help to manage your mail
easy and conveniently. I recommend to experiment with the regular expressions
and the rules, adapt them to your needs because procmail possibilities
go well beyond what I have been able to discuss in this short introduction.