cats2procmailrc - generate a procmail recipe from my mail categories file


cats2procmailrc [-a alert] [-A addresses] [-C] [-d dirpath] [-D subst=val] [-L] [-m maildomains] [-S] [-t type] [-T] [LOG=value] [category-files...] >procmailrc


cats2procmailrc reads human friendly mail category description files and emits a matching procmail(1) recipe to implement it. The intent is to have an extremely succinct file of easily editable one line rules, generally of the form:

      folder  tag     pattern

Raw procmailrc(5) clauses are also supported for less trivial rules and also an inclusion syntax.

I build my .procmailrc like this:

      cats2procmailrc \
              -a 'announce-email "+%"' \
              -A "$HOME/rc/mail/aliases" \
              -t maildir -L \
              -m \
              <categories >$HOME/.procmailrc


-a alert

Specify a shell command to run as the alert function (see FILE FORMAT below), such as mailblink(1). The character percent ('%') is replaced by the folder name.

-A addresses

Read the file addresses expecting lines of the form:

 cat[,cat...] rfc2822-address

and define macros named re_cat for each category that contain regexps to match all the addresses in each category cat.


Continue mode. Alters the semantics of the generated rules. Default mode is to stop filing when a matching rule is found unless it commences with a ``+''. In continue mode, file continues after a rule match unless the rule commences with an ``=''.

-d dirpath

If a relative filename is used in a '<' include line, look for it in the directories specified by dirpath in addition to the current input directory. dirpath is a colon (':') separated directory list.

-D subst=val

Add a macro definition.


Put the tag into the X-Label header field instead of as a prefix to the subject line.

-m maildomains

A comma separated list of default mail domain for rule addresses lacking an @domain. The default comes from the environment variable $MAILDOMAIN.


Synchronous. All continue rules will use a lock file. This constrains procmail(1) from becoming a fork bomb if there are many continue rules, such as may occur in a cross-referencing rule list.

-t type

Specify the default mailbox type. If the mailbox exists the type is deduced automatically, but otherwise uses this default, which may be one of unix, maildir or mh. The default is unix.


Don't track rule matches. Normally a X-Cats2Procmailrc-Matching-Rule header is inserted describing the match rule. This is done with formail and so can incur a noticable penalty on slow machines with lots of messages. If you're using the -L option the labels will mostly track stuff for you anyway.

The optional argument LOG=value will be prepended to the start of recipe actions. This can be a useful adjunct to the LOGABSTRACT facility in procmail.

If no category-files are supplied, standard input is used.



Lines ending in a slosh ('\\') are continued to the next line, keeping the newline and discarding the slosh.

Blank lines and lines beginning with an octothorpe ('#') are passed through unchanged.

Lines of the form:


are passed through unchanged.

Lines beginning with a colon (':') introduce a raw procmail recipe, and this line through to the first line commencing with a closing curly bracket ('}') are passed through unchanged.

Lines of the form:

      < filename

include the specified file. Relative filenames are sought in the directory containing the current input file (taken to be the current working directory if the current input is stdin) and then in the list of directories specified by the -d option.

Other lines are of the form:

      [+][!]target[,target...] tag pattern [newline pattern...]

where each target has the form:


Multiple targets may be specified to file the message to multiple places for this rule.

A target may be enclosed in double quotes ('``').

A leading plus sign ('+') means that this rule should be a continue rule, and not abort processing.

A leading exclaimation mark ('!') means that mail items matching this rule should generate an alert. The alert can be any action you desire, such as the mailblink(1) command; see the -a option. For me, this means a single line summary of the mail item appears in yellow in a small log window I have at the top of my screen for mail items I should read now.

A target commencing with a pipe symbol ('|') is considered a shell command to which to feed the message. The tag is appended to the shell command unless the tag is ``.'' in which case it is omitted.

Otherwise, if the target contains an ``at'' (@) character it is considered an email address and the mail item is forwarded to that address.

Otherwise the target names a mail folder in which to place the mail item. Normal UNIX mail files, MH style directories and Maildir style directories are autodetetected. If the folder does not yet exist, the folder type specified by the -m option is used. Relative folder names are considered to be in the directory specified by the $MAILDIR environment variable.

The tag is placed at the start of the message's Subject line for ready recognition in mixed folders unless the -L option is used, in which case it is placed in the X-Label: header line. The special tag dot (``.'') suppresses this action.

The patterns select the mail items. All the patterns in a rule must match the mail item for the rule to apply. The special pattern ``.'' always matches.

The folder or who@where or |shell-command may be enclosed in double quotes if desired, for example if the folder name or program invocation contains whitespace. Note that the quotes must not enclose the leading ``+'' or ``!''.

Substrings of the form ``{{WORD}}'' are replaced with macro values of the same name if defined. Any environment variable of the form $CATS2PROCMAILRC_WORD prepopulates the macros a macro called WORD containing the value of the environment variable. WORD must match the regexp ^[A-Z][A-Z_0-9]*$. Further or overriding macros may be specified with the -D option.

Example Patterns

The usual form is simply an address (see RFC822 and RFC2822) to be present in the To, CC or BCC header lines. If the address string lacks an at (``@'') then an at (``@'') and the value of the environment variable $MAILDOMAIN is appended. If the address string lacks the local part, any localpart is accepted.

I have rules like this:

      !attn   Personal        cs
      !attn   Personal
      attn    EFF-Cafe-News
      crypto  AUCrypto

matching,, and respectively. The ``Personal'' items generate an alert.

It is also possible to select on a different header line by prefixing the pattern string with a header name, viz:

      applix  ApplixWare

which selects for an address in the Sender header line.

The pattern may also be an arbitrary regular expression in egrep(1) syntax. In this case the pattern starts with a slash (``/'') and optionally ends in a slash, viz:

      !adzap  AdZap           subject:/(noads|add?[-  s]*zap|squid_?redir|zapp(er|ing)|wrapzap)/

which matches mail items with subjects probably regarding my adzap program. A leading ``^.*'' is added to the regexp unless it already starts with a ``^''.

A typical use of the ``at'' sign is in conjunction with the plus sign above to copy particular mail items to another account while still delivering locally. For example: .
      fredmail Fred

to accept mail aimed at and also copy it to This could also be written:,fredmail .

Patterns with more than one condition:

      logs    cron    root \
                      subject:/Cron <root


        !me     interesting     {{ME}} \

This rule matches email to me from people I know, filing it with an alert action. The variables $CATS2PROCMAILRC_ME and $CATS2PROCMAILRC_KNOWN are constructed in advance to match these addresses; the former from my mutt alternates line and the latter from my mail alias file.

A pattern that always fires:

      +all-mail       .       .

to copy everything into the ``all-mail'' folder, and continue processing.


MAILDIR, the directory containing mail folders.

MAILDOMAIN, the local mail domain (eg for my home domain).

CATS2PROCMAILRC_[A-Z]*, macro definitions


procmail(1), procmailrc(1), procmailex(1), egrep(1)


Cameron Simpson <>