blog >> 
Join the conversation >>

[Infinite Ink logo]

An introduction to email filtering with a focus on procmail

Copyright © Nancy McGough & Infinite Ink
Originally published in 1994 as part of the Filtering Mail FAQ
Last modified 27-Nov-2007


   “... Quick Start at Infinite Ink, one of the best primers to a complex program I've ever seen.   
-- Kai Schätzl, 2004 May 16, Procmail list  



Historical MetaNote   I wrote the first incarnation of this Procmail tutorial more than thirteen years ago as part of the Usenet Filtering Mail FAQ. In 1995 it was published in the book Internet Secrets. In 1999, I HTMLized it and turned it into this Procmail Quick Start. In 2000, a revised version was published in the book Internet Secrets, 2nd Edition. I've been editing and updating this document at all stages, so it is quite mature at this point (and I'm still editing it!). Thanks to all the people who have sent me feedback and suggestions.


Linking MetaNote   I regularly update this page so when you want either the latest version of this Procmail Quick Start or the Procmail Section of the Filtering Mail FAQ, please go to <>. Please do not use or link to an outdated, unauthorized, or plagiarized version of this. For example, do not link to the Procmail Section of the Filtering Mail FAQ, which I haven't updated in years, and do not link to plagiarizations, which I'm collecting at / / _MyWriting / Uncredited. If you know anyone who has stolen my writing or design, please tell and me. If you have a suggestion for a way to name & shame people who are plagiarizing and pirating, please tell me that too!


Searching MetaNote   You can use this form to search the web, the Infinite Ink site, or the site (my blog) for information about Procmail (or about anything!).

Infinite Ink

[New!] Procmail-Related News MetaNote   The Procmail-related news items that used to be posted here are now posted on my blog with the label PROCMAIL.



 On This Page  




What is Procmail and What You Need to Use this Quick Start

Procmail is free/libre open-source software that is both a mail processor and a mail delivery agent (MDA). It can be used by either a system administrator or a user to automatically process and deliver incoming mail messages. It can also be used to re-process and re-deliver messages that are already in a mailbox.

This Procmail tutorial is aimed at regular users, not system administrators. In order to use these instructions, you need:

  1. A basic understanding of Internet mail flow, which you can learn about at:

In addition to understanding Internet mail flow, your mail messages must be delivered to a system that:

  1. has procmail installed
  2. you have shell access to
  3. either
    1. uses procmail as the default local delivery agent (LDA), or
    2. uses a message transfer agent (MTA) that lets you use a .forward file to set procmail as your LDA, or
    3. allows you to set procmail as your LDA some other way. For example, with qmail, use dot-qmail files; with MMDF, use .maildelivery; with getmail, use .getmailrc; and with fetchmail, use .fetchmailrc.

If your system satisfies 4a or 4c, make sure that you skip Steps 8 & 9 below, that is, do not set up a .forward file.


[Note]  If you are looking for a provider that has procmail installed, see my list of Free or Reasonably-Priced IMAP Service Providers — most of the providers who give full Unix shell access also let their users write and manage their own procmail recipes.  



Terms Used in This Article

Note about the ordering of these terms:  The terms listed earlier are used in the definitions of later terms.

PM  or  pm
In this article I use PM as an abbreviation for Procmail. For example, I use pmlog for the Procmail log file, PMRE for Procmail regular expression (defined below), and PMDIR for the variable that points to the directory that holds your Procmail-related files. Note that there are others who use this abbreviation, for example, Paul Chvostek's Procmail Log Watch awk script is called pmlw and Jari Aalto's Procmail Documentation and Procmail Library are located at and

mail client  or  mail user agent  or  MUA
A program — such as Mulberry, pine, alpine, mutt, Opera Mail (M2), Thunderbird, SeaMonkey Suite, Outlook Express, Outlook,, or Eudora — that a user uses to process mail messages. "Processing" includes reading, extracting or launching attachments, moving, printing, deleting, and composing & initiating the sending of messages. For more information, see the definition of MUA at FOLDOC and Email client at [Wikipedia Icon]. For discussion about offline-, online-, and disconnected-mode IMAP clients, see this 2002-June-01 comp.mail.imap message. For a comparison of Pine, Mutt, Mulberry, SeaMonkey Suite and Thunderbird, see Comparison of Pine and Its Main Competitors on the All About Pine page.

news client  or  NNTP client
A program — such as pine, alpine, nn, slrn, Opera Mail (M2), SeaMonkey Suite, or Microsoft Outlook Express — that a user uses to process Usenet and other NNTP messages. "Processing" includes reading, extracting or launching attachments, moving, printing, canceling, and composing & initiating the sending of messages. Note that many NNTP clients can save to, read from, and process the mailboxes that Procmail delivers messages to. For more information, see the definition of news reader at FOLDOC.

A computer or a computer program that responds to requests from — or serves — other computers or computer programs. Whether the word “server” means “server software” or “server computer” is usually clear from the context and sometimes people explicitly say which is meant. For example, the following questions are equivalent and both are in standard parlance.

  • “What IMAP server software are you running?”
  • “What IMAP server are you running?”

For more information, see the definition of server and client-server at FOLDOC.

MTA  or  message transfer agent  or  mail transport agent  or  mailer
The underlying program that a mail server uses to send and receive mail messages. There are many MTAs in use today, for example CommuniGate Pro, Courier, Exchange, exim, MMDF, postfix,, qmail, sendmail, smail, and Zmailer. Note that on some systems the sending MTA is different from the receiving MTA. For more information, see the definition of MTA at FOLDOC, Cameron Laird's personal notes on message transfer agents, Unix Mail Transport Systems reviewed by JdeBP, and the definition of Message Transfer Agent at [Wikipedia Icon].

MSA  or  mail submission agent
To “send” a message, a mail user agent traditionally submitted the message to a message transfer agent. Nowadays most systems have a layer that sits between the MUA and MTA called the mail submission agent or MSA, and the MUA submits the message to the MSA rather than to the MTA. For details, see RFC2476, Message Submission and Gregory Neil Shapiro's Message Submission Agent (MSA). An MSA is used to authenticate the sender and, optionally, to rewrite headers, catch outgoing spam, viruses, & other vermin, and to provide an alternate outgoing port number (because, e.g., port 25 is often blocked or hijacked by Internet Access Providers).

LDA  or  local delivery agent  or  MDA  or  mail delivery agent  or  DA  or  delivery agent  or  local mailer
The program your server uses to deliver mail messages to the mailboxes of users on the system. Sometimes delivery is built into the message transfer agent (for example, sendmail's mail.local and Postfix's local) and sometimes another program, such as tmail, dmail, Dovecot deliver, maildrop, or procmail, is used as the delivery agent.

mailbox  or  mail folder  or  folder
A collection of messages stored on either a local or a remote computer. A mailbox might be a single flat file (this is the structure used by spool (mbox) and c-client MBX mailboxes); it might be a directory with each message a file in the directory (this is the structure of MH, maildir, and Netnews mailboxes); or it might use some other data structure, for example the structure used by c-client mix mailboxes. For more information, see "Appendix A: Folder Formats" in the Procmail FAQ and Before You Begin: Note About MH, maildir, and Traditional Unix Spool (mbox) Mailbox Formats below.

default inbox  or  system mailbox
Whatever you or your system administrator has specified as your primary incoming mailbox. Messages that fall through all your procmail recipes are delivered to this mailbox. To find out your system mailbox, type  procmail -v  at your Unix prompt. To tell procmail to override your default inbox, set the DEFAULT environment variable in your procmailrc. Warning: Overriding $DEFAULT may have undesired consequences with some MTAs.

MAILDIR variable  and  maildir format  (which are two completely different beasts!)
Unfortunately, the word “maildir” is used in (at least) two different ways in the Procmail world. MAILDIR (in all caps) is a Procmail variable that changes Procmail's current working directory and is used to point to the directory where your personal (non-system-spool) mailboxes are stored. For more information about Procmail's MAILDIR variable, see the blinking IMPORTANT note in Step 4 below. Maildir (not in all caps) is the name of a mailbox format. For more information about the maildir mailbox format, see Using maildir format, the maildir man page, and the section below about delivering to a mailbox that is in maildir format.
list  or  subscription  or  solicited bulk email  or  SBE or  solicited bulk mail  or  SBM
A mailing list that is used either for group discussion or for newsletters & announcements. For more information, see the definition of mailing list at FOLDOC and Webopedia; also see the definition of UBE (Unsolicited Bulk Email), which is an antonym of these terms.

A set of conditions and an action to be performed if the conditions are satisfied. Note that some programs that filter messages use a different term for this concept. For example, Pine uses the term filtering rule, Visual Office use the term rule, SeaMonkey Suite and Thunderbird use the term message filter, SmartSieve uses the term Mail Filter Rule, and Mulberry uses the terms script, trigger, & rule to encompass this concept.

A sequence of characters. Letters, digits, punctuation, symbols, tabs, and spaces are all considered characters. A substring is a string that is contained in another string. For more information, see the definition of string at FOLDOC.

regular expression  or  RE  or  RegEx  or  RegExp
A string in which some characters are interpreted as “wild cards” or metacharacters. Here are some metacharacters and metaphrases that can be used in a Procmail regular expression (PMRE).

or Metaphrase
Meaning in a Procmail Regular Expression
. any character other than newline (i.e., other than Line Feed or LF or ASCII character 10)
(string) treat string as a single item
* zero or more of preceding item
? zero or one of preceding item
+ one or more of preceding item
^ newline; usually used to match beginning of line; Note: As discussed in Re: procmail help! $MATCH grabs newline too, the meaning of the ^ metacharacter is different in Procmail than in most other RE tools.
$ newline; usually used to match end of line; Note: As discussed in Re: procmail help! $MATCH grabs newline too, the meaning of the $ metacharacter is different in Procmail than in most other RE tools.
[characterList] any single character in characterList
[^characterList any single character NOT in characterList
each of \< and \> is a metaphrase for a "non-word character"; details are in the definition of word & Matching a Word below, and in Jari Aalto's Procmail and egrep differences
| OR; ORing in Procmail is discussed below
() () is the null item and is always a match; it is used to make a recipe condition more readable, to escape a leading backslash (\), or to escape the special meaning of other metacharacters or metaphrases. For examples, see this discussion of ()< and this discussion of ()\/. Note that it is more common to escape a metacharacter with a backslash, which is discussed in the next item.
\metacharacter Escape the special meaning of metacharacter and treat it as the literal character that it is;  for example  \.  means the dot character rather than “backslash followed by any character” and  \*  means the asterisk character rather than “zero or more backslashes.”  Note: The less-than character (<) needs to be escaped differently. Also see David W. Tamkin's 2004-April-24 message about leading backslash problem (was persistent lock files).  Tip: Another way to escape a metacharacter is to put it in a [characterList], e.g., you can use either \. or [.] to mean a literal dot (.) in a PMRE.  Example: In Setting Keywords or Labels below, there is a recipe condition that contains a literal $ character.
\/ extraction operator (discussed below)
\newline If the last two characters on a line are a backslash (\) followed by newline, this is a “continuation backslash” and it tells Procmail to continue the current line with the text on the next line and ignore these characters: backslash (\), newline, white space (spaces, tabs, and/or newlines).

In Procmail, regular expressions are used in the conditions of a recipe to, e.g., look for a pattern in the Subject header of a message. For more information, see the definition of regular expression at FOLDOC,, Regular Expressions HowTo at OmniWeb, Columbia University's page on regular expressions for procmail, the Regular Expression section of era eriksson's Procmail Quick Reference, Scott Wiersdorf's Regular Expressions - Procmail Mail Filtering Syntax, manual page for regexp, the Extended regular expressions section of the procmailrc manual page, and [Wikipedia Icon].




A substring that contains only word characters - letters, digits, and underscores - and is bounded on the left by the beginning of a line or non-word character and on the right by the end of a line or non-word character. For example, in the line
           Subject: testing procmail
the substrings Subject, testing, and procmail are each words and the substrings Subject:, mail, and test are not words. The diagram below shows the relationship between words and substrings, namely: Every word is a substring but not every substring is a word.

           |  +---------+   |
           |  |  words  |   |
           |  +---------+   |
           |     substrings |

Since you need to look at the boundaries of a string to determine whether it is a word, the term word only makes sense when you are talking about a substring in the context of a larger string. For more information, see the discussion about matching the word “test” in Understanding and Refining Your Procmail Recipes below.
A friendly text editor that is the default pine composer. Throughout this article you can replace pico with a different text editor if you like. To learn more about Pico, see the pico man page and What is Pico at the University of Washington Pine Information Center.
or  $HOME  or  ${HOME} 
Your home directory. You can get home by typing any of the following:
cd ~
cd $HOME
cd ${HOME}
Note: Do not use ~ in a procmailrc file; use $HOME or ${HOME} instead.
Remember:  There's no place like ~ 


See Also




With procmail you can organize your environment variables, recipes, mailboxes, and directories however you like. Only the .procmailrc file, which I discuss below in Step by Step Through Setting Up and Testing Procmail, is required to have this name and to reside in your home directory. This freedom is part of what gives procmail its power but it can lead to chaos if you do not have a strategy for organizing and naming your procmail-related environment variables, files, and directories.



  Everything should be as simple as possible but no simpler.   

-- Albert Einstein as quoted and discussed in the
Mentors section of Peter G. Neumann’s page


The first strategy that I recommend and try to follow in this article is simplicity. For example, I recommend that you use the Procmail defaults whenever possible and do not set unnecessary environment variables in your procmailrc file(s). For more about this, including problems caused by not using the defaults, see the Warnings ([Warning!]) notes in Step 4 below.


Modularize and Plug & Play

A key to good programming is modularization. This, along with simplicity, will help to make your Procmail configuration portable and will make it easy to plug in, unplug, or reorder recipes. Here are examples of recipe modules you might want to use:

In the Step-By-Step section below, I walk you through creating the first two recipe modules and then, after testing, I show you how to unplug rc.testing. I discuss rc.quarantine and rc.spamassassin in the Advanced Recipes section.





The rc in procmailrc and in my recipe module names is a Unix naming convention that stands for either runtime configuration, runlevel change, or run commands (take your pick!). Thanks to Richard Smith, the maintainer of, for telling me he thinks of rc as runtime configuration; Elmar Hinz for telling me he thinks of it as runlevel change; and Imperial College for FOLDOC, the Free On-Line Dictionary Of Computing, for its definition and history of rc.



Use Consistent Naming and Formatting Styles

Using consistent naming and formatting styles will help you keep your directories, files, and mailboxes organized. Here are the styles that I use:

What     My Naming & Formatting Style
directory   initial upper-case letter
file   all lower case
procmail recipe module   begins with rc.
unplugged command in an rc file   begins with ##
comment (that is not an unplugged command) in an rc file   begins with #
environment variable    all upper case; also see the 2005-Jan-20 message Re: Variable names by Ruud H.G. van Tol
symbolic link to a file   begins with L.  (for an example, see Tips for Managing Your Procmail Files below)
symbolic link to a directory   begins with LD.  
mailbox (*)   does not contain forward slash (/), dot (.), backslash (\), hash (#), colon (:), asterisk (*), percent (%), quotes, apostrophes, parentheses, brackets, or braces; is not the string  inbox  or  mbox  or  mail.txt  or  inbox.mtx   or  default    or  Mailbox  or any combination of upper and lower case letters of these strings. Also, because of this story, you may want to avoid using core as a mailbox name. (* Also see the Notes About Mailbox Names below.)
incoming mailbox   begins with -- or IN-  (I use one of these prefixes so that all my incoming mailboxes are grouped together when they they are sorted by name.)
incoming “Solicited Bulk Email” (SBE) mailbox   begins with --s- or IN-S-  (you could also think of the S as standing for subscription or shared)
archived SBE mailbox   begins with == or zz- or S- and ends with -YYYY-MM-DD (the date of the latest message in the box)
special mailbox such as SENT, DRAFTS, and TRASH   Some email clients and IMAP servers do not let users change the names of special mailboxes but if it's possible, I like to use all upper case for these so they are more noticeable. I also prefer to use the name SENT-FCC (FCC = “Folder Carbon Copy”) for my sent mailbox to distinguish it from SENT-BCC, which is where I deliver (via procmail) messages that I Bcc to myself.
personal special mailbox     begins with plus (+), dash (-), equals (=), or a number so that it is listed near the top when all mailboxes are sorted by name using an ASCII sort. For example, I use 2Reply for messages that I want to reply to and 2Web for messages that contain information that I'd like to incorporate into my web site.
“catch-all” mailbox   contains either the string catchall or dregs or fallthrough or dropthrough or wildcard or yellow or red (this is where messages that are not delivered to one of my virus, magenta, blue, green, or lime mailboxes are delivered; for more about catch-all mailboxes and my general email strategy, see Reverse Spam Filtering: Winning Without Fighting)
mailbox when I care about the mailbox format   ends with a meaningful extension, for example .unix for Unix mbox format or.cmbx for c-client MBX format.  (Tip: Do not use the extension .mbx because different mail clients use it to mean different mailbox formats and thus it is ambiguous. Also some viruses go after files with the .mbx extension.)


* Notes About Mailbox Names [Updated!]  
  Here are more details about my strategy for choosing mailbox names. These notes are in addition to the comments in the starred item (*) above.
  • I use dash (-) rather than underscore (_) or a space ( ) as a visual separator in my mailbox names. I don't like underscores because they are a pain to type (you need to hold down the SHIFT key) and they are sometimes hard to see (they can fade into the baseline of the text and looks like a space). I don't like spaces in mailbox names because in many tools, especially command-line tools, spaces need to be escaped.

  • [New!] Another reason to avoid the underscore (_) character in a mailbox name is discussed in the 2007-August thread with subject "-" and "_" in folder names in the dbmail mailing list.

  • The string “INBOX” has a special meaning to IMAP servers and if you give a mailbox this name, your IMAP client might not be able to see this mailbox on the IMAP server. This is because when it sends the string “INBOX” to the server, the server interprets it to mean a special mailbox, which is not necessarily the mailbox that has the name “INBOX”.

  • Each of the strings mbox, mail.txt, INBOX, and INBOX.MTX have a special meaning to clients and servers that are based on the University of Washington's c-client tools. It is best to not use any of these for a mailbox name, unless, of course, you want a mailbox to be interpreted in the special c-client way.

  • The string “default” has a special meaning to the qmail MTA and it is safest not to use this as a mailbox name.

  • The strings new, cur, and tmp are used in the internal structure of maildir-formatted mailboxes and, to avoid confusion, I recommend that you do not use any of these as a mailbox name.

  • The strings Trash, Discard, Junk, Junkmail, Spam, and Ham have a special meaning on some systems. For example, in the default configuration, the Trash, Discard, and Junkmail folders are periodically auto-deleted; at, “mail in the Trash folder will get thrown out automatically when it's a month old.” To ensure that you have complete control over your mailboxes, do not use any of the special mailbox names on your system. For example, I use a mailbox named MaybeSpam for my possibly-spam messages and I do not need to worry about my system auto-deleting these messages (because MaybeSpam is not a special mailbox on my system).

  • Do not use a forward slash (/), dot (.), or backslash (\) in a mailbox name because these are used as a namespace hierarchy separator on some IMAP servers. For example, Binc IMAP and UW IMAP use forward slash for the hierarchy separator; Lotus & Exchange use backslash; and Dovecot (when using Maildir-format), Mirapoint, Courier, & Cyrus all use dot. (Note that most IMAP servers can be configured to use a non-default hierarchy separator. For example, has configured their Cyrus server to use forward slash as the hierarchy separator.)

    Avoiding these characters in mailbox names makes it possible for you to have a consistent naming style across different IMAP systems, and should make your life easier if your system's IMAP server changes or if you move your mailboxes to a system using a different flavor of IMAP.

  • You might consider not using a dollar sign ($) or exclamation mark (!) in a mailbox name because some IMAP servers, for example Cyrus, do not allow these characters. However, Courier and UW IMAP do seem to allow these characters in a mailbox name.

  • You might consider not using a caret (^) in a mailbox name because Cyrus IMAP will convert any dot (.) in a mailbox name to a caret if the hierarchy separator is changed from slash to dot. If you use ^ in your mailbox names, you will not be able to distinguish between carets that have been converted from dots and carets that have always been carets.

  • I have been wondering if there is any problem with using tilde (~) as the 1st character in a mailbox name? If you have any thoughts about this, please post in this comp.mail.imap thread that I started 2005 Nov 18.

  • If your mail system allows dual-use names (which are aka hybrid folders), i.e., allows a mailbox and a directory (hierarchy) to have the same name, I recommend that you not use the same name for both a mailbox and a directory. This will make your life easier if you move your mailbox hierarchy to a system that does not support dual-use names. For example, if you use UW IMAP with mix-format mailboxes, Dovecot IMAP, Cyrus IMAP, our Courier IMAP, it is possible to create a container named Archive that contains both mailboxes and messages. My advice is to use this Archive container as either a container of only mailboxes (a directory) or as a container of only messages (a mailbox).

  • Some of the other characters and strings to avoid in mailbox names that I list above were suggested in the 2001-July-09 comp.mail.imap message Re: Mailbox Names (Was: Which IMAP Server is better?) and in the 2002-Sep-23 comp.mail.imap thread characters allowed in mailbox names.

  • Do not start a mailbox name with the hash character (#) because some IMAP servers interpret a string that begins with # as an IMAP namespace token. This is discussed in RFC 3501, section 5.1 (Mailbox Naming), which says “Two characters, "#" and "&", have meanings by convention, and should be avoided except when used in that convention.” The next item discusses the problem with ampersand (&).

  • You might also consider not using an ampersand (&), a space, or an upper-case character in a mailbox name for the reasons discussed in the gmane.mail.imap.dovecot thread Ampersand in Folder names causing folders to disappear?, in the gmane.mail.imap.courier.general thread IMAP Folders and the ampersand, in the EMD thread Ampersand in Folder Name, and in the FastMail.FM FAQ about How do I use FastMail.FM's subdomain addresses and "plus- addresses"?  Tip: If you use a Procmail recipe to deliver to a mailbox that contains a space in its name, you need to escape the space by preceding it with a backslash (\).

  • Another reason not to use an ampersand (&) in a mailbox name is that it might be interpreted as a MUTF7 string, rather than an ASCII string, by an IMAP server or client.

  • Some systems have problems with a special mailbox name — such as SENT, DRAFTS, SPAM, and TRASH — if it is created in a non-standard way, e.g. via procmail. This is discussed in this and this thread at



My Latest Mailbox-Naming Experiment

Request:  I'm revising my mailbox naming style and I'd like to learn about names that other people use, especially any mailbox-naming scheme that is in common use. I'm thinking about changing the prefix of my incoming mailbox names from IN- to something that will sort above all alphabetic characters in an ASCII sort. I'm leaning towards prefixing these box names with a dash (-), so, for example, incoming procmail mailing-list messages would be put in --procmail. And then I'd put the archive of that mailbox in zz-procmail-YYYY-MM-DD or ==procmail-YYYY-MM-DD because the leading zz- or == will make it sort below my incoming mailboxes. I realize that these are kind of odd-looking names so I'm interested to hear what ideas other people have — please let me know what you think and if you have suggestions.

Note 1:  Someone emailed me and mentioned that if a mailbox name starts with a dash, it is a pain to manipulate from a Unix shell. That is true, but it provides a bit of security if a lamer breaks into your account and tries to read your mailboxes using shell commands such as more or less or pine -f mailboxName (and it's not that much of a pain if you know the trick)!

Note 2:  I'm now using this naming scheme and so far I haven't had problems with Procmail or with any mail client or IMAP server that I've used. For example, here are mailbox names that could be used with my reverse-spam-filtering system:


To force my most important incoming mailboxes to the top of an ASCII sort, I prefix each mailbox name with an appropriate number of dashes. For example:


I actually use a modified version of this and don't really have a mailbox name that begins with seven dashes! If you are interested in why I name my incoming mailboxes after the colors of the rainbow, see Reverse Spam Filtering: Winning Without Fighting.



Ordering Procmail Flags

I recommend that you order Procmail flags using the style that Jari Aalto suggests on his Procmail Tips page in the section called The order of the flags. I use this style throughout this page, for example in the SpamAssassin recipes below.


Managing Spam

A lot of people are learning Procmail because they want to automatically separate non-spam messages from spam messages. My strategy is to do the following, in this order:

  1. Have my mail hosting provider do SMTP-level spam rejection using, for example, Greylisting, DNSBLs, or SPF (Sender Policy Framework).
  2. Quarantine or delete viruses.
  3. Deliver or forward known non-spam messages, possibly also setting appropriate flags/labels/keywords.
  4. Pipe the possibly-spam (not known non-spam) messages through a spam-detection tool, such as SpamAssassin, to assign a spam score or spam probability.
  5. Set appropriate flags/labels/keywords on possibly-spam messages.

To implement step number . . .

  1. see IMAP Service Providers page, which describes over 400 providers, many of whom offer SMTP-level spam rejection.
  2. see Snagging Viruses below.
  3. see some or all of the following:
    1. Step by Step Through Setting Up and Testing Procmail below, which includes recipes that catch and deliver specific “Solicited Bulk Email” (mailing-list and newsletter) messages.
    2. Alternatives to the ^TO_ Macro below, which includes more recipes that catch and deliver specific Solicited Bulk Email messages.
    3. Generic SBE Sorting below.
    4. Setting Keywords or Labels below.
    5. Minimizing False Positives With Greenlists and Bluelists below.
  4. see Using SpamAssassin below.
  5. see Setting Keywords or Labels below.

For more about my spam-deflexion strategy and about Unsolicited Bulk Email (UBE or spam), see my Reverse Spam Filtering: Winning Without Fighting page.

For other people's spam-deflexion strategies, see the December-2005 gmane.mail.procmail discussion about Spam and Procmail, which takes place in these two threads. Especially useful is this message from G.W. Haywood, in which he describes the system that he uses on his mail servers and says:

Most people haven't the faintest idea how much work is involved in keeping the bulk of spam and other junk at bay.


[ icon] I am collecting Spam-related links at



Before You Begin: Note About MH, maildir, and Traditional Unix Spool (mbox) Mailbox Formats

[Updated!] Overview

The step-by-step instructions below guide you through setting up Procmail to deliver to mailboxes that are in traditional Unix mail spool format (mbox). To deliver to a mailbox that is in maildir format, you need to append a forward slash (/) to the mailbox name. The table below gives examples of the various types of mailbox specifications that can be used in the action line of a Procmail recipe.


Unix mbox format
maildir format
      maildir format on a
Courier IMAP server
MH format (*)
IN-testing IN-testing/   .IN-testing/ IN-testing/.
IN-S-procmail IN-S-procmail/   .IN-S-procmail/ IN-S-procmail/.
IN-S-vim IN-S-vim/   .IN-S-vim/ IN-S-vim/.


  • If Procmail tries to deliver a message to a maildir, MH, or mbox mailbox that does not exist, Procmail will create the mailbox in the appropriate format and then deliver the message to it.

  • If a maildir or mbox mailbox does not exist, it is safest to let Procmail create it (see previous item) rather than trying to create it yourself using Unix commands.

  • In order for Procmail to successfully deliver to a pre-existing mailbox, the mailbox must be in the appropriate format. For example, a maildir or MH mailbox must be a directory and a Unix mbox mailbox must be a file.

  • If you deliver to maildir mailboxes, use procmail 3.15.2 or 3.22+.  3.14 has serious problems delivering to maildir mailboxes and 3.15, 3.15.1, 3.20, and 3.21 have minor problems.

  • (*) If you use MH mailboxes, you will probably want to use the MH/nmh rcvstore program to deliver messages. Details are in Beedub's Wiki in the section Using the procmail program.

  • If you want to deliver to another type of mailbox, consult the relevant documentation. For example, to deliver to . . .




An explanation of how Procmail delivers to various folder formats is in the latest (3.22) procmailrc man page. Here is the relevant section.

  [ . . .]
  Anything else will be taken as a mailbox  name  (either  a
  filename  or a directory, absolute or relative to the cur-
  rent directory (see MAILDIR)).  If it is a  (possibly  yet
  nonexistent) filename, the mail will be appended to it.
  If  it  is  a  directory,  the mail will be delivered to a
  newly created, guaranteed to be unique file named $MSGPRE-
  FIX* in the specified directory.  If the mailbox name ends
  in "/.", then this directory  is  presumed  to  be  an  MH
  folder;  i.e.,  procmail will use the next number it finds
  available.  If the mailbox name ends  in  "/",  then  this
  directory  is presumed to be a maildir folder; i.e., proc-
  mail will deliver the message to a file in a  subdirectory
  named  "tmp"  and  rename  it  to be inside a subdirectory
  named "new".  If the mailbox is  specified  to  be  an  MH
  folder  or maildir folder, procmail will create the neces-
  sary directories if they don't exist,  rather  than  treat
  the  mailbox as a non-existent filename.  When procmail is
  delivering to directories, you can specify multiple direc-
  tories  to  deliver  to  (procmail  will  do  so utilising

When delivering to a maildir or MH format mailbox, you do not need to use a lock file so the first line of a recipe does not need the second colon. For example, instead of using this as the first line:


you can use this:


There are examples of recipes that deliver to maildir-formatted mailboxes in Step 7D and in Using SpamAssassin below.


Details Specific to maildir Format


[Important!]  If you want your system mailboxes $ORGMAIL and $DEFAULT to be in maildir format, it is best to specify this in the procmail source code and recompile procmail. This is discussed in the following messages, which were posted to the Procmail mailing list.  

If you are delivering messages to maildir-formatted mailboxes that will be served to mail clients by Courier IMAP (which supports only maildir format mailboxes), put a dot (.) in front of the mailbox name in your Procmail recipe. This leading dot is a hierarchy separator and will ensure that IMAP clients can see these mailboxes. IMAP clients will display the mailbox name without the leading dot (or the trailing slash, which is just used to tell procmail the format of the mailbox and is not part of the name that's used on the Unix system).

Technical Note:  On Courier IMAP, private mailboxes reside under the “INBOX.” hierarchy. On the server, this hierarchy is usually in the directory $HOME/Maildir but users do not need to tell their IMAP clients the actual name of this directory because the IMAP protocol will pass that information to the IMAP client.



The Qmail MTA


Systems that use the qmail MTA usually use maildir-formatted mailboxes. To use Procmail with qmail, put a line like one of the following in the relevant dot-qmail file:

|preline /usr/local/bin/procmail ~/.procmailrc || exit 111
|preline procmail -m -p myprocmail.rc
|preline procmail

(It is not clear to me which of the above is best and it would be great if someone could fill me in so I can include more information about this here.)

To learn more about using Procmail with qmail, see:

Qmail Tip: Depending on the preline command that you use in the dot-qmail file, you may want to put EXITCODE=99 in the Variables Section of your procmailrc. This Procmail EXITCODE will tell qmail that procmail completely handled — e.g. processed & delivered — a message and that qmail can forget about it. If you do not specify this EXITCODE, qmail may think it needs to deliver the message after Procmail finishes processing it and then you will (probably) get two copies of a message, one delivered by Procmail and one delivered by qmail.



See Also


Step by Step Through Setting Up and Testing Procmail

These 18 steps walk you through ensuring that procmail is installed on your system, setting it up to sort your incoming mailing-list messages, and testing your setup.




[Important!]   Important:  For the following steps to work, you must be a regular user, not root.

If you are a system administrator who is learning Procmail, I highly recommend that you step through this procedure before you try to set up a global procmail rc file. You are much more likely to understand the basics of Procmail if you learn by doing (rather than by reading only). And your system & users will be much less likely to experience an email nightmare if you do your Procmail learning — and making mistakes — as a regular user!



  1. To find out if procmail is on your system and, if it is, what the path to it is, type one of the following commands.


    Shell Command
    csh, tcsh which procmail
    sh, bash, ksh type procmail
    various whereis procmail
    various where procmail
    various locate procmail

    Make a note of the path to procmail because this is needed in Step 9 below.

  1. To find out procmail's version, locking strategies, default rcfile, and your system mailbox (aka your default INBOX), type:
    procmail -v 


    • If you are using a version earlier than 3.11pre4, which was released on 29 October 1995, you need to use the procmail expression ^TO rather than the expression ^TO_ in Step 15.

    • If you are using version 3.13 or earlier, procmail cannot deliver to maildir mailboxes (unless you apply a patch to procmail or pipe a message to a program that can deliver to a maildir mailbox). If you deliver to maildir-formatted mailboxes, it is best to use procmail 3.15.2 or 3.22+.  3.14 has serious problems delivering to maildir mailboxes and 3.15, 3.15.1, 3.20, and 3.21 have minor problems.

    If your system does not have procmail or does not have the latest version, 3.15.2 or 3.22+, ask your system administrator to install it. You can find out what is the latest version of procmail and where to get it at

  2. Rename (move) ~/.forward, ~/.procmailrc, and the global procmailrc, if they exist. This will ensure that you do a clean Procmail setup.
    1. To find out if ~/.forward exists and what its contents are if it does, type:
      cat ~/.forward
      If ~/.forward exists, rename it using a command similar to this:
      mv -i ~/.forward ~/.forward-2007-11-27
      This will ensure that you use the optimal ~/.forward file for your system, which is discussed in Steps 8 and 9 below.

    2. To find out if ~/.procmailrc exists and what its contents are if it does, type:
      cat ~/.procmailrc
      If ~/.procmailrc exists, rename it using a command similar to this:
      mv -i ~/.procmailrc ~/.procmailrc-2007-11-27
      Steps 3 and 4 (in the next section) walk you through setting up a minimal ~/.procmailrc file. If you would like to use some of the recipes that are in your old procmailrc file, I recommend that you call them by using an INCLUDERC command in your new minimal ~/.procmailrc. For an example of an INCLUDERC command, see the end of Step 4 below (in the #### Processing Section ####).

    3. To find out if a global procmailrc exists and what its contents are if it does, type:
      cat /etc/procmailrc
      cat /usr/local/etc/procmailrc
      If a global procmailrc exists and if you are the administrator of your system, rename it using a command similar to this:
      sudo mv -i /etc/procmailrc /etc/procmailrc-2007-11-27
                change to the path
                  on your system
      After you have experience setting up and using a personal procmailrc, you can, if you want, re-install this renamed global procmailrc. Details about using a global procmailrc are in See if There is a Global procmailrc below.

      Note: As discussed here, viaVerio VPS accounts use /usr/local/etc/procmailrc for the global procmailrc file. Also note that you can view the VPS default files and directory structure in the /skel directory. (Verio is where I host the Infinite Ink web pages, including this page.)

      Warning: As discussed in this December-2005 gmane.mail.procmail thread, it seems that there is a Linux distribution that “out of the box” includes a broken /etc/procmailrc.



Set Up Your Procmail Files for Testing

  1. Create ~/.procmailrc by typing:
    pico -w .procmailrc




  3. Enter the following in your ~/.procmailrc either by typing it or by using copy & paste*. But first note these warnings.
    • Procmail does not support the expansion of tilde (~). You must use $HOME rather than the ~ character within your .procmailrc. This is documented in the procmailrc man page.

    • Make sure you replace  MAILDIR=$HOME/Msgs  with the directory where your personal (non-system-spool) mailboxes are stored and that this directory exists and is writable by your LOGNAME. The MAILDIR variable specifies Procmail's working directory and all relative paths are relative to this directory.

    • When you first test Procmail, do not set the PATH variable. As Philip Guenther said in this message,
      “you shouldn't alter PATH unless there's something actually missing from it or the order is wrong.”
    • As I discuss in Simplicity above, do not explicitly set any variable unnecessarily. In addition to not explicitly setting the PATH variable, which is discussed in the previous item, it is almost always best to not explicitly set the DEFAULT variable. For examples of problems caused by explicitly setting variables, see: The first two of these threads discuss problems caused by explicitly setting DEFAULT and the third thread discusses a problem caused by setting a user-invented variable named FORMAIL.

    To learn about the Procmail default environment variables on your system, see man procmailrc on your system.

    # Note: Anything after a hash character (#) is a comment & is ignored by procmail.
    #### Begin Variables Section ####
    # It is essential that you set SHELL to a Bourne-type shell if
    # external commands are run from your procmailrc, for example if
    # you use rc.spamassassin, rc.quarantine, or other advanced recipes.
    # Setting SHELL should not be needed for the simple sorting recipes in 
    # this step-by-step section, but to be safe and to future proof your
    # procmailrc, set it anyway! Details are in Check Your $SHELL and $PATH.
    # Directory for storing procmail configuration and log files
    # You can name this variable anything you like, for example
    # PROCMAILDIR, or don't set it (but then don't refer to it!)
    # LOGFILE should be specified ASAP so everything below it is logged
    # Put ## before the next line if you want no logging (not recommended)
    # To insert a blank line between each message's log entry in $LOGFILE, 
    # uncomment the next two lines (this is helpful for debugging)
    ## LOG="
    ## "
    # Set VERBOSE to yes when debugging; VERBOSE default is no
    ## VERBOSE=yes
    # Replace $HOME/Msgs with the directory where your personal (non-system-spool) mailboxes reside 
    # Mailboxes in maildir format or served by Courier IMAP are often in $HOME/Maildir
    # Mailboxes served by UW IMAP are sometimes in $HOME, sometimes in $HOME/mail, & sometimes elsewhere
    # MAILDIR default is the value of $HOME
    # Make sure that $MAILDIR exists and that it is a directory!
    # * On most systems $MAILDIR is a subdirectory of $HOME
    # * Upon reading a line that contains MAILDIR=
    #     Procmail does a chdir to $MAILDIR
    #      ...and $MAILDIR becomes the Procmail working directory
    #       ...and relative paths are relative to $MAILDIR
    # * Do not include a trailing slash in your MAILDIR setting
    # * The $MAILDIR directory must exist and must be writable by your LOGNAME
    # * The MAILDIR variable is an entirely different entity from maildir mailbox format
    #### End Variables Section; Begin Processing Section ####  
    # Messages that fall through all your procmail recipes are delivered
    # to your default INBOX. To find out yours, run 'procmail -v' 
    #### End Processing Section #### 
    # EOF
    [New!] *Copy & Paste Tip: A concise version of the above procmailrc is in Step 17 below. If you have problems pasting this into the vim editor, see Vim Tip #330: how to stop auto indenting at

  4. To create the directory where you will store your procmail-related files (this is $PMDIR that you set in Step 4), type:
    mkdir Procmail
  5. Create an rc file for testing by typing:
    cd Procmail
    pico -w rc.testing
  6. Enter the following 5 lines in ~/Procmail/rc.testing:
    * ^Subject:.*test
    # EOF

    1. The first line contains a zero (0), not the letter O. For now do not worry about the meaning of this recipe; it is explained in Dissecting a Recipe in the Understanding and Refining Your Procmail Recipes section below.

    2. Log File and Mailbox Creation
      • If a log file or mailbox does not exist, Procmail will create it. It is usually best to let Procmail create a non-existent mailbox rather than creating it yourself using an external tool.

      • Procmail will create a log file or mailbox using a umask of 077, unless you or your system administrator changed the Procmail default umask, for example, by setting the UMASK variable in a procmailrc file.

    3. IN-testing is a traditional mbox-format mailbox and is located in your $MAILDIR directory ($HOME/Msgs in this example), which you defined in Step 4 above. Important: Procmail will not create the $MAILDIR directory, so make sure that it already exists. However, as discussed in the previous item (B), Procmail will create the IN-testing mailbox if it does not exist.

    4. To deliver to a maildir-format mailbox that will be served by a Courier IMAP server, use the following recipe instead of the mbox recipe in Step 7 above.
      # In the next line, note the missing 2nd colon (:), which means "do not use a lockfile"
      * ^Subject:.*test
      # In the previous line, note the leading dot (.) and trailing slash (/)
      Details about this and other mailbox formats are in Before You Begin: Note About MH, maildir, and Traditional Unix Spool (mbox) Mailbox Formats above.

      • Important maildir Note 1:  Do not specify the cur, new, or tmp subdirectories because these are dealt with automatically by Procmail (as long as there is a slash (/) after the mailbox name in the Procmail recipe).

      • Important maildir Note 2: If you want your default inbox to be a maildir-format mailbox, it is best to specify this in the procmail source code and recompile procmail.

      • Important maildir Note 3: You must be using Procmail version 3.15.2 or version 3.22+ for Procmail to be able to correctly create and deliver to maildir-formatted mailboxes.



Set Up Your .forward File (not required on most systems)

In 1994 when I wrote the Filtering Mail FAQ, which is what this document evolved from, most Unix systems used sendmail as the message transfer agent (MTA) and Procmail was invoked via the .forward file. Nowadays, on most systems, the .forward file is not used to invoke procmail. Instead, either:



  • Philip Guenther, the current Procmail maintainer, recommends that you first try testing your .procmailrc without a .forward file -- that is: Skip Steps 8 and 9.

  • If that does not work, come back here and create a .forward file.

  • If creating a .forward file also does nt work, ask your system administrator what is your MTA and what you need to do to set up Procmail as your LDA.

  • A default Verio VPS2 account does not have procmail installed. To install procmail on a VPS2 system, you need to run vinstall procmail-lda. Details are in Procmail - E-Mail Sorting and Filtering Utility at


  1. [not required on most systems] Create a ~/.forward file by typing the following. (Pico's -w command-line argument tells pico not to auto-wrap lines, that is, don't insert extra line breaks.)
    pico -w .forward
  2. [not required on most systems] Enter the following in your ~/.forward:
    The vertical bar (|) is a pipe and is typed as SHIFT-backslash on a standard US keyboard. Make sure you replace /absolute/path/to  with the correct path for procmail (see Step 1) and include both the leading and trailing double quote mark (").

[Note]   If sendmail is configured to use smrsh (sendmail restricted shell), you will only be able to invoke the version of procmail that is listed as an smrsh-allowed program. For more about this, see What are some typical installation problems? in era eriksson's Procmail FAQ and Q3.34 -- What does "foo not available for sendmail programs" mean? in the Sendmail FAQ.  



Check File Types and Set File & Directory Permissions

  1. Make sure that .forward (if it exists), .procmailrc, and rc.testing are in Unix ASCII text format by typing
    file .procmailrc
    file ~/Procmail/*
    file .forward
    For each of these that exist, the response should be ASCII text or ASCII English text. If it is anything else, for example ASCII text, with CRLF line terminators, go to Make Sure Your Configuration Files Use LF (Line Feed) Line Terminators in the Troubleshooting section below and fix this problem.

  2. Starting with version 3.14, Procmail will not trust your .procmailrc if either it or your home directory is either group or world writable. Also, on some systems your .forward file, if it exists, needs to be world-readable & not executable and your home directory needs to be world-searchable in order for the message transfer agent to “see” the .forward file. To set these permissions, type the following:
    chmod go-w,a+x .
    chmod go-w .procmailrc
    chmod 644 .forward
    If you skipped Step 8 and 9, you obviously don't need to chmod your non-existent .forward file. (But it won't hurt if you do!)

    To check these file and directory permissions, see Check File and Directory Permissions in the Troubleshooting section.

[Note]   Once your .forward (if it is needed to invoke procmail) and .procmailrc files are in place, procmail is alive. To kill it, see Pulling the Plug on Procmail below.  



Test Your Procmail Setup

  1. Send yourself two test messages: one that contains procmail testing in the Subject and one that does not contain the string test in the Subject.

  2. Use your mail client, such as pine or mutt, to check that the messages were delivered correctly. The one with procmail testing in the Subject should be in the mailbox $MAILDIR/IN-testing and the one without test in the Subject should be in your default inbox. Ways to view your mailboxes are described in Accessing Your Mailboxes below.

If these two messages were not delivered correctly, see Troubleshooting below.



Create Recipes to Sort Solicited Bulk Email

  1. After you successfully test procmail, create rc.subscriptions, or rc.sbe if you prefer that name, for sorting solicited bulk email (newsletters and mailing lists) into mailboxes. To do this, type:
    cd Procmail
    pico -w rc.subscriptions
  2. In rc.subscriptions create a recipe, like the two example recipes below, for each mailing list to which you are subscribed.
    * ^
    * ^
    The first recipe puts messages that are sent to the procmail mailing list into a mailbox named IN-S-procmail and the second recipe puts messages that are sent to the vim mailing list into a mailbox named IN-S-vim. The following table describes the meaning of the second recipe.

    Notation Meaning
    :0 Begin a recipe
      : Use a lock file
    * Begin a condition
     ^TO_ Look for a header that begins with To, Cc, Resent-To, or another destination specification, followed by any or no characters, followed by an email address that begins with the string...
    IN-S-vim If there is a match, put the message in the mailbox $MAILDIR/IN-S-vim and stop processing this message; if there is not a match, pass the message to the next recipe

    [Important!]   Important Notes About Procmail's  ^TO_  Macro  
    • ^TO_ is not a normal regular expression; it is a special procmail expression designed to catch an email address — or the beginning of an email address — that is in any destination header (To, Cc, Resent-To, etc.). For details, see the MISCELLANEOUS section of the procmailrc man page and Jari Aalto's TO_ Macro Deciphered.
    • Sometimes the actual destination address is not in any destination header, for example if the message was Bcc'd (blind courtesy copied). For more about this, see the following sections below:
    • To use the special ^TO_ expression, you need to be using at least procmail version 3.11pre4 (see Step 1 for how to check the version). If you are using an earlier version, replace ^TO_ with ^TO, which works essentially the same as ^TO_ but is not as precise.
    • Do not put a space between the caret (^) and TO or between TO and the underscore (_) in ^TO_.
    • Both the letter T and the letter O must be capitalized in ^TO_.
    • Do not put a space or any character between ^TO_ and the email address you are matching on; it must be ^TO_beginning-of-address or ^TO_fully-qualified-address. An exception is if you are using Procmail's extraction operator (\/) to assign the address to a variable.
    • Do not put .* or left angle bracket (<) or both (.*<) immediately after the underscore in ^TO_. Equivalents of these are built into the ^TO_ expression. For an exception to this (and an excellent use of the word "eviscerate"), see the discussion between David W. Tamkin and Martin Ward in the message Re: ackmail.rc not acking correctly? in the Procmail list.
    • Most of the time ^TO_ is better to use than ^TO. For exceptions to this, see Ruud H.G. van Tol's Re: Error on recipe, and the discussion between Martin McCarthy and Nuno Teixeira in the message Re: Newbie question: filters.
    • The expression ^TO_address will match on any of these strings: address, foo+address, bar+address, anything+address, etc. For details, see this 2004-Nov-25 message and the rest of the thread.




    • Put the busiest mailing lists at the beginning of your rc.subscriptions file so those messages will be caught and delivered before they have been checked by a lot of recipes. This both speeds up processing and makes it less likely that a little-used recipe might accidentally match on a message that would better be handled by a more frequently used recipe.

    • I discuss alternate — and more accurate — ways to sort mailing lists in Alternatives to the ^TO_ Macro below.




  3. Repeat the procedure given in Test Your Procmail Setup (Steps 12 and 13) to make sure things are still working.

  4. "Unplug" rc.testing 1) so that it won't catch non-testing messages that contain the string test in the Subject and 2) to save processing power. To turn the line into a comment, put # at the beginning of that INCLUDERC line. Your .procmailrc will now look like the following (possibly with the other comments that I include in Step 4 above or your own comments).
    #### Begin Variables Section ####
    # Next line is needed if programs are invoked from your procmailrc
    PMDIR=$HOME/Procmail      # Make sure this directory exists!
    ## LOG="
    ## "
    ## VERBOSE=yes
    MAILDIR=$HOME/Msgs        # Make sure this directory exists!
    ####  End Variables Section; Begin Processing Section  #### 
    ## INCLUDERC=$PMDIR/rc.testing  
    # Messages that fall through all your procmail recipes are delivered
    # to your default INBOX. To find out yours, run 'procmail -v'
    #### End Processing Section #### 
    # EOF


Tips for Managing Your Procmail Files


[Important!]   Do not try to deliver mail to a symbolic or hard link. Because of potential locking problems, a mailbox that Procmail delivers to should be an actual file and the $ORGMAIL mailbox, which is discussed in the Troubleshooting section below, must not be a symbolic link or a file with more than one hard link.  




Accessing Your Mailboxes

After procmail delivers messages to your mailboxes, you can access your mailboxes using

If you are looking for an IMAP service provider that has procmail installed, see my list of Free and Reasonably-Priced IMAP Service Providers -- most of the providers in the list that give Unix shell access also have procmail installed.


Mailbox Locking

If you use a mail or news client to change a mailbox that is receiving messages — for example, to delete a message — make sure that both procmail and your client use the same locking scheme. To determine what locking strategies are used by your installation of procmail, and the order in which these locking strategies are used, run:

procmail -v

and look at the value of “Locking strategies.”

To learn about file locking, see:


  • Make sure that you are not delivering to mailboxes in Unix spool (mbox) format on an NFS or any other network file system since locking does not help on those systems. For a possible workaround to this, see the comp.mail.imap message Re: UoW IMAP, lock files and multiple servers by Mark Crispin.

  • The Netscape mail client does no locking of its local mailboxes, meaning that there is no safe way to deliver directly to them.

  • Kmail seems to be flaky about locking local mailboxes. For details, search the KDE Documentation for procmail.


Commands for Specific Clients

Here are instructions for how to use some clients to open a mailbox that is in that client's default mailbox directory. (Please send me information about other mail and news clients!)

    Client    Default Mailbox
Command Line Within Client   Lock?  
  pine ~/mail pine -if mailbox G mailbox yes  
  mutt ~/Mail mutt -f +mailbox c +mailbox yes  
  elm ~/Mail elm -f =mailbox c =mailbox yes  
  mail ~/mail mail -f /path/mailbox  yes  
  nn ~/News nn +mailbox G +mailbox no  

If a client does not use a lock file, you should not use that client to change the mailbox while it is receiving messages. To learn more about your mail or news client, see your client's documentation. I describe how to set up Pine mailbox collections in Setting Up Local and Remote Folder Collections in my Power Pine.

Using Multiple Clients to Access Your Mailboxes

Most Unix mail clients store mailboxes in a directory named either "Mail" or "mail" and most Unix NNTP clients use a directory named "News." If you want to use more than one client to access your mailboxes (or make it easy to do that in the future), you can use the Unix ln command to link the directory where your mailboxes are stored to the names of the mailbox directories used by other clients. Here are instructions for merging the mailboxes in your existing mailbox directories into a new directory named Msgs, and then linking this directory to the names mail, Mail, and News. In Steps 3-5 below replace mail with the name of one of your existing mailbox directories.

  Type this To do this
cd Go to your home directory.
2 mkdir Msgs Create a directory named Msgs. (Alternatively, you could use the mv command to rename one of your existing mailbox directories to Msgs.)
3 mv -i mail/* Msgs/. Move files in the directory named mail to the directory named Msgs and inquire if files with the same name should be overwritten. Answer no (n) to these inquiries.
4 mv -i mail/Duplicate Msgs/Unique  Move file with a duplicate name to the Msgs directory and rename it to a unique name. Do this for each duplicate name you encountered in Step 3.
5 rmdir mail Delete the mail directory

Repeat Steps 3-5 replacing mail with the name of your other existing mailbox directories. Now symbolically link the Msgs directory to mail, Mail, and News, which are the most commonly used mailbox directory names, by doing the following.


  Type this To do this
  ln -s Msgs mail  Link the Msgs directory to the name mail.
  ln -s Msgs Mail Link the Msgs directory to the name Mail.
  ln -s Msgs News Link the Msgs directory to the name News.

Of course, you can also link the Msgs directory to any other name that a program uses for its mailbox directory. Now all your mailboxes are in one place and you can easily save to and access them from different news and mail clients.


[Important!]   The above procedure works only if your mailboxes are in a single-file format, such as traditional Unix mbox format, and your mail and NNTP clients can all access the same mailbox formats.  


[Tip]   In Step 3 above, I put slash dot after the target directory name (i.e., Msgs/.) to ensure that a directory named Msgs rather than a file named Msgs is the target.  




Tracking Your Incoming Messages

The Procmail log is located in $LOGFILE, which, if you used the instructions in Step 4 above, is $HOME/Procmail/pmlog. The contents of $LOGFILE depend on the values of $VERBOSE, $LOG, $LOGABSTRACT, and $TRAP, which you can read about in the Environment section of the procmailrc man page. You can use many commands to view the log including  cat, more, less , and my favorite, tail, which I discuss in the next section.


Following Your Log with tail -f

If you want to continually follow your log, you can use

tail -f $HOME/Procmail/pmlog

To start tailing with the last 50 lines of the log, use

tail -n 50 -f $HOME/Procmail/pmlog

which on my system is equivalent to

tail -50 -f $HOME/Procmail/pmlog

To quit live monitoring your log, type


If you want to be able to run other commands while the tail is happening, use & to put it in the background:

tail -f $HOME/Procmail/pmlog &

To learn about tail, see man tail.

Another tail option is to use Paul Chvostek's ProcMail Log Watch (pmlw), which is an “awk script that tails your procmail log file, summarizing results and giving you basic traffic statistics, live.”


Summarizing Your Log with Mailstat

You can use mailstat, a script that is part of the procmail package, to get a concise summary of your procmail log file. To see if it is on your system type one of the following commands:

which mailstat
type mailstat
whereis mailstat
where mailstat
locate mailstat

If mailstat is on your system, type:

mailstat $HOME/Procmail/pmlog

This moves pmlog to pmlog.old and displays a concise description of the contents that looks like the following:

  Total  Number Folder
  -----  ------ ------
   9964    3    IN-S-procmail
   3408    1    IN-S-vim
  -----  ------
  13372    4

You may want to put the mailstat command in your .login or .profile so that each time you log in you will see a list of how many messages you have received since the last time you ran mailstat, and what mailboxes these messages were delivered to. Or, if your system lets you use the cron command to run programs on a regular schedule, you could automatically run mailstat once a day or once a week and either save the results in a file or mail the results to yourself. A typical cron command line to collect the stats at 1:00 each morning and mail them to yourself would be:

0 1 * * * mailstat $HOME/Procmail/pmlog | mail YourAddress

To get a listing of pmlog.old, the previous log file, use the -o command-line argument:

mailstat -o $HOME/Procmail/pmlog

To get help on the mailstat command-line arguments, type one of the following:

mailstat -h
man mailstat  (I think this works only on a Debian Linux system)
If mailstat is not on your system, ask your system administrator to install it. It is located with all the other procmail tools (see for where to get procmail).
[Tip]   Your procmail log file will keep growing unless you regularly delete it by using mailstat, the Unix rm command, or some other technique. To minimize logging, put VERBOSE=no (which is the default) and LOGABSTRACT=no in your .procmailrc. To turn logging off, which I do not recommend, turn the LOGFILE setting in your .procmailrc file into a comment by preceding it with #, for example:
    ## LOGFILE=whatever 



Summarizing Your Log with Other Scripts

Other scripts that you can use to summarize a Procmail log are:


Customizing What's Logged

Some ideas for changing what is logged and where it is logged are in


Sending Log Entries or Messages to an RSS/Atom/XML Feed

To be notified about incoming email messages in an RSS/Atom/XML feed reader, you can use a service or tool such as one of the following. Note that most feeds can be accessed by anyone, so make sure that you either secure your feed or send only non-private messages to your feed.


To use one of these services, you could set up Procmail to forward messages (or message headers or other message fragments) to the appropriate email address at the service provider.


See Also

I list more tools and services that can be used to deflect email messages to RSS/Atom/XML feeds — and vice versa — on the following pages. These pages include links to tools & services that can be used for doing many different types of message deflexion.

Please tell me about other tools or services that can be used to send a message or Procmail log entry to an RSS/Atom/XML feed.

[Tip]   [Opera 9: your web, your choice] If you are looking for a desktop feed reader, check out Opera, which is free/gratis, ad-free, and registration-free for all. To me, it's especially nice when the Newsfeeds are set up with View > Display > List and message on right (as opposed to the default, which is List and message below). You can, of course, configure Newsfeeds (and all of Opera) however you like!

Opera is also a multi-platform standards-based customizable HTTP, IRC, BitTorrent, NNTP, & IMAP client.



Using General Email Notification Tools

In addition to the Procmail-specific notification tools that I discuss above, there are many other programs, such as biff, that can notify you about incoming messages. For details, see:

Also, some IMAP clients can be set up to monitor mailboxes on IMAP servers. For example, I run Mulberry along with my primary mail client, Pine, mainly for its customizable monitoring of mailboxes and mailbox-specific alerts.

On the Power Pine page, I discuss techniques for Checking for Recent Messages in Pine. Especially useful are the “newmail-fifo” and “newmail-window” features, which are available in Pine 4.62+.



Understanding and Refining Procmail Recipes

Anatomy of a Recipe

A Procmail recipe looks like this:

:0 flags: LockfileName  
* condition1-PMRE    (PMRE = Procmail regular expression)
* condition2-PMRE  
exactly one action item

where flags, the second colon (:), LockfileName, and the condition lines are optional. So a minimal Procmail recipe looks like this:

exactly one action item

which means perform the exactly one action item on every message that is passed to this recipe and don't do any mailbox locking (that's what the missing second colon means).

A recipe that uses no flags and does not explicitly specify the lock file, but instead uses the implicit lock file, looks like this:

* condition1-PMRE
* condition2-PMRE  
exactly one action item

In this case, the header only is passed to the conditions and if both condition1-PMRE AND condition2-PMRE are satisfied, the whole message (header & body) is passed to the exactly one action item and procmail stops processing the message.




ORing Conditions

In the previous section, we saw that it is easy to create a Procmail recipe that ANDs conditions. If you want to OR conditons, see Jari's ORing traditionally, ORing and score recipe, and ORing by using De Morgan rules. There is an example of “ORing traditionally” in Using the Extraction Operator (\/) and $MATCH to Sort Solicited Bulk Email below. Dallman Ross's virus-snagger recipes include elegant examples of ORing with scores.


Dissecting the rc.testing Recipe

The recipe in rc.testing is:

* ^Subject:.*test

The following table explains the meaning of this recipe.


Notation Meaning
:0 Begin a recipe
  : Use a lock file
* Begin a condition
  ^Subject: Look for a header that begins with the string Subject:
           .    ... followed by . (any character)
            *        ... 0 or more of preceding item [i.e. any, possibly empty, sequence of characters]
             test            ... followed by the string test
IN-testing If there is a match, put the message in the mailbox $MAILDIR/IN-testing and stop processing this message; if there is not a match, pass the message to the next Procmail recipe


Matching a Word

If you want a recipe to match only the word test, rather than the string test, surround test with the Procmail word delimiters \< and \> as in the following:

* ^Subject:.*\<test\>

This recipe would not match on a message that contained procmail testing in the Subject but it would match on a message that contained procmail test in the Subject. The next section includes another example of a Procmail recipe condition that uses \< (the example is in the Tip).

To learn more about Procmail regular expressions, see regular expression in the Terminology section above and Jari Aalto's Procmail and Egrep Differences. Jari includes technical details about Procmail's word delimiters.





Important Warning: Procmail Cannot Reliably Route Users' Messages in a Virtual-Domain Dropbox  

The most frequently asked question about Procmail is “How can I use Procmail to separate messages that were sent to different addresses?” And the answer is: “That is a job for the MTA (message transfer agent).” Unfortunately, it is now common for people to have a virtual (aka vanity) domain and to not be able to use an MTA to route the domain's mail. Instead, the domain's mail is delivered to a “dropbox” and then people try to use Procmail to do the routing long after the messages pass through the MTA that is running on the domain's purported mail server (the server pointed to by the DNS MX record for the domain). This is fraught with problems as you will discover if you try to do it.

The current Procmail maintainer, Philip Guenther, summed it up well in a message in the procmail mailing list in which he said:

You can't do virtual domains in pure procmail, as you need the MTA to provide you with the original envelope recipient address. Once you have that, sort the messages on that directly (do *not* use ^TO_).

Sometimes the MTA is set up to record the original envelope recipient address in one of the following headers.

Header         Comment
Delivered-To:   used by qmail and its companions preline and safecat; used by postfix when possible as discussed here and here; used by courier (when courier is the MTA) and its companion maildrop; used by getmail; used at Gmail as discussed below, GMX, and Verio
X-Delivered-To:   used at FastMail.FM as discussed here
Envelope-To:   used by exim as discussed in the book Exim: The Mail Transfer Agent near the end of this section of Chapter 3; used at providers who use the cPanel web-hosting control panel; used at
X-Envelope-To:   used by sendmail with help from procmail, for details see the sendmail-related links below; used at and
X-Original-To:   used by postfix 2.0.?+ as discussed here and here; used at DreamHost as discussed here; used at
X-Apparently-To   used by Yahoo!
X-MailNull-To:   used at
X-Rcpt-To:   was used at the now defunct
X-Real-To:   used by CommuniGate Pro as discussed here; used at

And then you can use a Procmail recipe, such as the following recipe, to process messages sent to a specific address in your virtual domain.

* ^X-Rcpt-To:.*secretBccAddress@my\.domain

Note that the condition in this recipe uses \. (backslash dot) to specify an actual dot. If you use . without a preceding backslash, it is a metacharacter that means any character.




  • I discuss reasons why you might want to use a secret Bcc address on my IMAP Service Providers page in the section "What to Look For in an IMAP Service Provider" in this auto-Bcc item, and in my blog in the item titled Server-Side Sent Messages.

  • If you use a recipe similar to the above X-Rcpt-To example, I recommend that you use a regular expression that is more accurate than .* to match the characters between the colon (:) and the beginning of the email address. The example recipe above will also catch an address, such as anotherSecretBccAddress, that contains the address that you want to match as a substring. The best regular expression depends on the format of the header that your incoming MTA injects and on the characters that are allowed in the left hand side of an email address in your domain. A reasonably generic option is this:
    * ^X-Rcpt-To:(.*\<)?secretBccAddress@my\.domain
                 this PMRE is discussed in this section of Jari's PM Tips

  • Because of dictionary spam and blowback (aka backscatter or outscatter) from spam that was sent with your domain name in a forged From header, I recommend that you set up your domain's email so that it does not use a catch-all mailbox. Instead, email sent to a non existent recipient should be rejected at the SMTP level. Most email hosting providers have a control panel where the domain administrator (e.g. you!) can turn off the catch-all for your domain(s).

    Important: Do not try to use Procmail to reject messages. If you do, you will be contributing to the spam problem and your system will very likely be added to blocklists. This is discussed in Rejecting or “Bouncing Back” a Message below.

  • In addition to the original envelope recipient address, the original envelope sender address is also useful. On some systems, this address is in a Return-Path header. Here is an excerpt from a Tuffmail Help page about this topic:
    "The envelope sender may or may not be the 'From' address displayed by your email client. The envelope sender is the sender address provided in the SMTP 'MAIL FROM:' command. This address is also known as the return address or error address. Mail delivered to a mailbox on [the Tuffmail] system will have a 'Return-Path:' header added that contains the envelope sender address issued in the SMTP 'MAIL FROM:' command."



[Important!]  Even if your mail-hosting provider has set up their MTA to inject a header such as X-Rcpt-To into incoming messages, there can still be problems. For example,
  • A spammer might have constructed the original message with a fake “envelope” header line, for example a fake X-Rcpt-To header.
  • The message may have been routed through another system and that system's MTA injected the state of the envelope (as it was at that point) into the header. For example, as discussed below, messages sent to the Vim mailing list contain a  Delivered-To:  header.
  • If a message is for multiple local recipients, some MTAs do not inject this type of header.



List of Links: “Why Headers Don't Matter” and More

[Note]Once SPF (Sender Policy Framework) is adopted, some headers from some users will matter, i.e., be trustable. Currently no header should be trusted.

For exhaustive information about this, see:

  1. chromatic's weblog entry titled One Question Certification Tests for E-Mail Filter Authors and subtitled “I'm normally skeptical of certification programs, but anyone who writes a program intended to scan and to respond to incoming e-mail should be required to pass a one question test before proceeding.”

    [Important!] I recommend that everyone who creates email filters take chromatic's one question test, especially if your filters use auto-replies or white/green/red/black/block lists! If you pass that test, here's my one question super advanced followup test:
    If a@b.c is the recipient of an email message, which headers will contain the address a@b.c?
    To check your answer, see the links below.

  2. era eriksson's Procmail FAQ: Why Headers Don't Matter

  3. era eriksson's Procmail FAQ: Why can't I match on the BCC: header?

  4. era eriksson's Procmail FAQ: How do I implement a virtual domain? Or, how can I let several local users share the same POP mailbox at the upstream? Or, what is the most frequently made wrong assumption about mail delivery?

  5. Jari Aalto's Procmail Tips: Bcc lecture by Alan Stebbens

  6. Jari Aalto's Procmail Tips: Bcc lecture by Philip Guenther

  7. Jari Aalto's Procmail Tips: What is that first From_ header?, which includes this: "A problem arises however when people start creating virtual domains. When sendmail does the aliasing (usually by mailertable I believe?), it totally loses the original envelope recipient address in the rewriting. All the addresses get rewritten to the same thing, and sendmail thus has no reason to differentiate them. Having lost their independent identities, the now-same multiple recipients are merged to form one call to the local mailer. The key point here is that once the envelope recipient is lost by the virtual domain alias, THERE IS NO WAY TO GET IT BACK!"

  8. Bart Schaefer's 2004-Dec-11 message to the Procmail list, in which he discusses that it is possible to “have procmail at the provider insert the special header information that's recognized by the downstream procmail for local routing. That would, however, mean the dropbox would get one copy of the mail for every downstream recipient rather than one copy for all downstream recipients...

  9. Virtual Hosting with Sendmail and Q3.29 -- How can I add a header specifying the actual recipient when having multiple users in a virtual domain go to a single mailbox?

  10. Andrzej Filip's Deliveries to Shared Mailboxes (sendmail)

  11. Philip Guenther's sendmail-related message Re: Procmailers beware: BCC handling in the Procmail mailing list

  12. Dave Sill's Life with qmail: Configuring Virtual Domains

  13. Fetchmail

  14. Getmail FAQ

  15. the Procmail mailing-list thread virtual domain multiple users filter

  16. Jason R. Mastaler's TMDA Pre-Configuration page, which includes information about getting envelope information from various MTAs. Jason says “TMDA receives much of its information about the envelope of an incoming message from environment variables set by the MTA. Most importantly, SENDER (the full envelope sender address), RECIPIENT (the full envelope recipient address), and EXT or EXTENSION (the recipient address extension).”

  17. Ken Lucke's Reading Email Headers

  18. > Discussions about Email Services > The Technical Zone... > Guide to email headers? How easily can these be forged?

  19. SpamAssassin Bugzilla Bug 2142: Need code to infer MAIL FROM: address from message (this bug discussion includes a link to this page!)

  20. John Conover's E-mail "Received: " Header IP Address Auditing

  21. Jonathan de Boyne Pollard's 2004-July-5 message in comp.mail.misc Re: received header field

  22. Sean B. Straw's 2004-July-14 message in the procmail list Re: local procmail filtering before using sendmail smarthost, in which he says
    “There is a procmail mantra. Please recite it with me:

  23. [ icon] My bookmarks about email envelopes.


[Updated!] Alternatives to the ^TO_ Macro

The recipes that I suggest in Step 15 for sorting solicited bulk email use the special procmail expression ^TO_, which catches any message that contains the list address in the To, Cc, Resent-To, or some other destination header. If someone sends a message to a mailing list by putting the mailing list address in the Bcc header, this address will usually not appear in any of the destination headers that the ^TO_ expression checks — that's why it is called Blind Carbon Copy!

You can catch these Bcc'd messages, and all other messages that are sent to the list, by determining a header that all messages that are passed to the list contain, and messages that are not sent to the list do not contain. Such a header depends on either the mailing-list management software that the list is using or the address that you used to subscribe to the list (this will work if you use a unique address for each list you join). Examples of such headers are:

For example, you can catch all messages that are sent - including those that were Bcc'd - to the vim mailing list by using the following recipe:
* ^Delivered-To:.*
And the following recipe will catch all messages that are sent to the procmail mailing list.
* ^List-ID:.*procmail.lists.RWTH-Aachen.DE

(This procmail recipe works on messages sent to the procmail mailing list after 18 May 2000, which is when the mailing list management software changed and started including the List-ID header.)



  1. Default Procmail conditions are not case sensitive so you do not need to worry about the case you use in a condition. For example, headers that begin with List-ID, List-Id, and any variation in capitalization will all match on the beginning of the second condition above.

  2. Most regular expressions, including Procmail regular expressions, use dot (.) to match any character. To match an actual dot, you need to use \. (backslash dot). For example, to be precise, use vim@vim\.org rather than, which would match on (and lots of other addresses with any character where the dot (.) is in

  3. Many auto-responder and solicited-bulk-email messages include one of these headers:
    Precedence: bulk
    Precedence: list
    Using a Procmail recipe condition that checks for a Precedence header might be useful...
    • if you are doing a simple bulk/non-bulk sort of your email; or
    • if a mailing-list recipe's conditions are not strong enough and are incorrectly matching on some messages that were not sent to the list; or
    • in an auto-responder recipe.
    For details about these and other Precedence headers, see List of precedence codes in Jari Aalto's PM Tips.

  4. Details about the above and other message headers are in the RFCs mentioned above (2919 & 2369), RFC 2076 - Common Internet Message Headers, RFC 4021 - Registration of Mail and MIME Header Fields, and IANA's Permanent Header Registrations.




[Tip]   Some people prefer to use the ^TO_ expression to catch mailing-list messages because:
  1. A message that is Bcc'd to a list is often spam and since the ^TO_ expression does not catch Bcc'd messages, these spam messages won't be put in your mailing-list mailbox.

  2. A message that is sent both to you personally and to the list will be put into the list's mailbox twice, rather than once in the list's mailbox and once in your personal-correspondence inbox. To get rid of duplicate messages, you can use the duplicate-catching recipe that is described in the procmailex manual page (but make sure you read the paragraph that begins with the word “Beware”!).

  3. If you interact with the mailing-list server by sending, for example, an unsubscribe or help request, the auto-reply message will not be put in the mailing-list's mailbox (because it will be sent directly to your address rather than the list address). Some other list-catching Procmail recipes, for example one that uses the List-ID header, might put these list-management auto-replies into the list box where it could get lost in the crowd of list messages.

  4. If the the mailing-list management software changes but the mailing-list address stays the same, your procmail recipe will still work.

Details about the ^TO_ expression are in Step 15's Important Note About Procmail's ^TO_ Macro.



Advanced Recipes

Using the Extraction Operator (\/) and $MATCH to Sort Solicited Bulk Email

If you subscribe to a lot of mailing lists and each one has its own recipe like this:

* ^

You can speed up processing by combining all your subscription recipes into a single recipe like this:

* ^TO_\/(subscription1|subscription2|subscription3)

Here is what this means:


Notation Meaning
:0 Begin a recipe
  : Use a lock file
* Begin a condition
 ^TO_ Look for a header that begins with To, Cc, Resent-To, or another destination specification, followed by any or no characters, followed by an email address that begins with...
      \/ [Begin extraction; if there is a match after the extraction operator \/, put it into a variable named MATCH. ]
       (subscription1|subscription2|subscription3) ...the string subscription1 or subscription2 or subscription3.
IN-S-$MATCH If there is a match, put the message in the mailbox $MAILDIR/IN-S-$MATCH and stop processing this message; if there is not a match, pass the message to the next recipe

The disadvantage of this recipe is that your mailbox will be named whatever you specify as subscriptionn. For example, if you use this:

* ^TO_\/(|

Your mailboxes will be named:

which are ugly and would be a pain to type in your mail client or at a command-line prompt. So you might want to use the following:

* ^TO_\/(procmail|vim)

This produces nice mailbox names but has the disadvantage that it might match on messages that were not actually sent to the mailing lists. For example, it would match on a message sent to (FYI, Vimala is an Indian name that means "pure.") You can refine this recipe by appending the "at" character (@) to the condition:

* ^TO_\/(procmail|vim)@

This should be pretty good about matching only messages that were actually sent to the list but now your mailbox names look like this:


To delete the trailing @ from the mailbox names, you can use the following recipe (assuming you are using Procmail version ??? or later):

* ^TO_\/(subscription1|subscription2|subscription3)@
* MATCH ?? ()\/[^@]+

Here is what this recipe means:


Notation Meaning
:0 Begin a recipe
  : Use a lock file
* Begin a condition
 ^TO_ Look for a header that begins with To, Cc, Resent-To, or another destination specification, followed by any or no characters, followed by an email address that begins with...
      \/ [Begin extraction; if there is a match after the extraction operator \/, put it into a variable named MATCH. ]
       (subscription1|subscription2|subscription3)@ ...the string subscription1@ or subscription2@ or subscription3@.
* If the first condition was satified, begin the second condition; if the first condition failed, pass the message to the next recipe.


Test the variable named MATCH against...
          ()\/ [Begin extraction; if there is a match after the extraction operator ()\/, put it into a variable named MATCH (replacing the old value).]
              [^@] ...any character other than the @ character
                  + one or more of previous item. In this case the test is looking for a non-empty sequence of characters that does not contain the @ character.
IN-S-$MATCH If the test was successful (i.e., if the original $MATCH contained a non-empty sequence of characters that did not contain the @ character), put the message in the mailbox $MAILDIR/IN-S-$MATCH and stop processing this message; if the test failed, pass the message to the next recipe (the only way this test would fail would be if subscriptionN contained only @ characters!).



Downcasing a Mailbox Name

Most mailing lists are sorted fine by the above recipe, but there is a problem if the string subscriptionn in the mailing-list address is not consistent in the capitalization of its letters. For example, debian-user messages are delivered to mailboxes named


and all other combinations of upper- and lower-case letters that list participants use in the ^TO_ address. This happens when mailing-list-management software does not rewrite the list address into a canonical form and instead leaves it in the form that the message's author used.

To solve the problem with the inconsistent capitalization of the string 'debian-user' and any other non-canonicalized list addresses, you can do one of the following.


Generic SBE Sorting

One way to avoid the inconsistent-capitalization problem described in the previous section is to extract the list name from a header that is inserted by the mailing-list software, such as Sender, List-ID, List-Post, Mailing-List, or one of the other alternatives to ^TO_ that I list above. For a simple example of extracting the mailing-list name from the Sender header and using $MATCH to construct the mailbox name, see the Recipes section at the bottom of this FreeBSD Diary Procmail page. This contains Neil Blakey-Milner's recipe for sorting all the FreeBSD lists that he subscribes to.

Sean B. Straw, of Professional Software Engineering, has a much more generic SBE sorting system. He created listname_id.rc, which extracts the list name from the headers of a message and assigns it to a variable named LISTNAME. He then uses something like the following in his .procmailrc.

* ! LISTNAME ?? ^^^^

For more about this, see:

Note that I do not currently use these generic-SBE recipes but I plan to try them one of these days.


[Note]   If the extracted $LISTNAME contains a dot (.), forward slash (/), or backslash (\) and the mailbox IN-S-$LISTNAME is accessed using IMAP, the IMAP server may interpret one of these characters as an IMAP namespace hierarchy separator. For details, see Notes About Mailbox Names above.  



More Examples of the Extraction Operator

In the sections Using SpamAssassin and Using a Nesting Block to Optimize the SpamAssassin Recipes below, there is an example of using the extraction operator to prepend text at the beginning of the Subject of a message. This technique can also be used to append text to the end of the Subject.

Dallman Ross's Virus Snaggers include recipes that extract the values of the Content-Type and From headers and assign them to variables named CTYPE and VFROM, respectively.

Also see Philip Guenther's 1997-Jan-15 message Re: Wierd regex Behaviory [sic] in the Procmail list.



Forwarding and Plus Addressing

In addition to the techniques for downcasing a mailbox name listed above, another option is to use forwarding and plus addressing. I discovered this because I deflect some of my mailing-list messages to my and accounts and use plus addressing to deliver directly to an appropriate mailbox or “label” at Gmail. For example, instead of delivering to a mailbox named IN-S-$MATCH as in the extraction-operator recipe above, I forward these messages by putting the following in the recipe's action line:

! MyUID+$

or this:

! MyUID+$

or to route these messages to both Tuffmail and GMail, I use this:

! MyUID+$ MyUID+$
                           Note that these 2 addresses are separated by a space 
                           If this doesn't work try using comma space (', ') or comma (',') instead

If a mailbox named $MATCH exists in my Tuffmail mailstore, the message is automatically delivered directly to it. In other words, all Debian-user messages are delivered to a mailbox named debian-user (if it already exists) regardless of how the string dEbIaN-uSeR was capitalized in the original message or in the envelope recipient address that Tuffmail received.

To learn more about “plus addressing,” which is also known as “subaddressing,”  “user-extension addressing,”  and “detailed addressing,” see my bookmarks about plus addressing and this section of my IMAP Service Providers page.

To learn more about Gmail (aka Google Mail), see my bookmarks related to Gmail and the Gmail discussion groups, especially the threads about The PLUS (+) feature and Filtering for list mail. At Gmail you need to create a Gmail filter to automatically label incoming messages. The Gmail MTA records the original envelope recipient address (for example MyUID+$ in a Delivered-To header, but unfortunately the Gmail filter cannot filter on this header. I describe how I get around this in a 2004-July-20 message with the subject Tip: Simultaneously file a message in an IMAP mailbox and assign a Gmail label that I posted to the Procmail list — make sure you read the entire thread.

Gmail Tips: 




  • When the action item of a Procmail recipe is a forward action, a lock file is not needed. In other words, the first line of the recipe should begin with :0 and should not contain a second colon (:).

  • If you want to use Procmail to forward a message, do not also use a .forward file to forward the message. This is discussed in Troubleshooting below.

  • If you want to both forward a message and keep a copy on the system on which Procmail is running, use Procmail's c (copy) flag, for example, use a recipe like this:
    :0 c
    * condition						
    Or if you want to unconditionally forward a copy of all mail that gets to this point in the procmailrc, use a recipe like this:
    :0 c
    In either case, beware of potential mail loops, which are discussed in The Problems with Forwarding below.

  • If you want to use procmail to “send” a message to a mailbox on the system on which procmail is running, it is usually better to simply use a delivery recipe rather than a forwarding recipe. Otherwise you can have a “NASTY mail loop,” as Sean B. Straw discusses in this 03-Jun-03 message Re: procmailrc flow -- global, per-user?

  • If you use the qmail MTA, you may need to explicitly set the procmail EXITCODE variable to tell qmail that procmail successfully processed the message. Links to information about this are in The Qmail MTA above.

  • The ! action uses the value of the Procmail SENDMAIL variable to forward a message. The Procmail default is almost always fine and usually you should not need to explicitly set the SENDMAIL variable. To learn more about this, see man procmailrc and Sean B. Straw's message Re: Forwarding blocked by ISP, using sendmail instead.

  • The word forward sometimes means MUA-style forward, but in Procmail it means MTA-style forward, which is also known as redirect, resend, remail, relay, send again, or bounce forward. I discuss these terms, as well as the term bounce back, below.


The Problems With Forwarding

Doing MTA-style forwarding with Procmail can be problematic, most notably there can be problems with:

For more about this and related problems, see:



Snagging Viruses

  • Currently: Because of the current batch of viruses, I recommend that you quarantine — but do not auto-delete — all messages that have attachments with a “nasty extension,” including .zip.
  • 2006-05-03: Robert Allerstorfer released Softlabs AntiVirus (SoftlabsAV) 0.8.8.
  • 2006-01-20: John D. Hardin released E-mail Sanitizer 1.151.
  • 2005-05-21: Dallman Ross added npd.rc to Virus Snaggers (vsnag). “npd.rc ... has one purpose: stop the neo-Nazi spam spew put out by the Sober.Q worm. ... You don't even need to run vsnag to use this.”
  • Regularly: Catherine Hampton releases a new version of SpamBouncer.
  • Regularly: Nikos Kantarakias releases a new version of YAVR.

Details about these programs are below.


Nowadays many mail service providers give their users the option to have incoming mail scanned for viruses, but if either . . .

then you can use Procmail — preferably running on your incoming mail server — to detect and snag viruses. There are many Procmail recipes that (attempt to) do this, including:




When you are choosing or creating a virus-snagging recipe, or any recipe, do not use a recipe that has an H or B flag in the top line (any line that starts with :0). This will help you avoid a bug that is described (along with how to work around it) in the following messages.

If you decide to use a recipe that uses the B flag in the top line, make sure that there is not — and never will be — an earlier recipe that has the H flag in the top line.


[ icon] I am collecting Virus-related links at



Using SpamAssassin

2007 August 9: The Apache Software Foundation released SpamAssassin 3.2.3.


SpamAssassin is free/libre open-source software (FLOSS) that can be used to analyze a message and tag it with a “spamminess” score. The higher the score, the more likely it is that the message is spam. After a message is tagged, Procmail can be used to filter the message to an appropriate mailbox, assign an IMAP keyword (label), or delete it.




The recipes below are specific to my system and my configuration files. Before using these recipes, you need to...

  1. Edit the recipes below so that they work with your system. For example:
    • If you do not use maildir-formatted mailboxes, change the delivery recipes so that they use the correct delivery syntax for your system.

  2. Edit your SpamAssassin configuration file (usually or user_prefs) so that an X-Spam-Level header is inserted into your SpamAssassinated messages. The X-Spam-Level header is used in the SpamAssassin Procmail recipes below.

    Be aware that SpamAssassin 3.x is not backward compatible with SpamAssassin 2.x so make sure that you 1] read the UPGRADE documentation and 2] run  spamassassin --lint --debug  after you upgrade! The SpamAssassin Procmail recipes below should work with both SpamAssassin 3.x and 2.x, provided you have configured SpamAssassin to
    add_header all Level _STARS(R)_
                                this character is the "X-Spam-Level character"
    I use R (for Red/Rubbish) as the X-Spam-Level character because 1] in Procmail, and many other filtering tools, it is easier to match R than * (asterisk), which is the default; and 2] spammers are more likely to forge SA headers using the default spam-level character (*).

  • Tip 1: If you want the spam score to be injected into the Subject header (or From or To header) of spammy messages, for example messages with a spam score of 4 or more, put settings like the following in your SpamAssassin configuration file.
    required_score 4
    rewrite_header Subject {_SCORE(0)_}
                                   ^  ^ I use squiggly braces, {}, because 
                                   |    square brackets, [], are special in IMAP 
                                   zero padding, details here
    If you use these two settings, it will be easy to use an email client to sort (order) your messages by spamminess and find false positives (non-spam messages that were flagged as spam). I discuss this, and more, in my blog item titled Using a MaybeSpam Mailbox.

    (Note that required_score is called required_hits in old (outdated!) versions of SpamAssassin.)

  • Tip 2: If you want to use an email client — either instead of or in addition to Procmail — to manage your spammy email, make sure that you use the spam headers that your email client is looking for. For example:

For more information about configuring SpamAssassin, see the SpamAssassin Docs, especially   man Mail::SpamAssassin::Conf (which is also known as perldoc Mail::SpamAssassin::Conf). The message Re: add headers by Theo Van Dinter is also useful.


#  For these recipes to work, you need to first set the standard Procmail
#  environment variables, which are described in the step-by-step section
#  above. Since the first two recipes below pipe messages through external
#  programs, you must ensure that PM is using a Bourne-type shell. 
# Recommendation 1: Filter your viruses, greenlisted & solicited-bulk
#  email before you plug in your SpamAssassin recipes. This will save 
#  CPU/memory and make it less likely that a non-spam message is tagged 
#  as spam.
# Recommendation 2: Read the SA discussion group and make sure that 
# you are using the most up-to-date version of SA and that you know
# about any caveats.
# If a message is larger than 256000 bytes (~250 KB), I use the 
# extraction operator (\/) and formail, which is part of the 
# Procmail package, to tag the Subject with {* -BIG- *}
# so I can easily tell that the message was not analyzed 
# by SA and I should be wary of it because it is rare for a 
# legitimate message to be this big. I do not use SA on 
# large messages because it consumes too much CPU/memory.
# Note: This is an example of a non-delivering recipe and all
# messages will pass through it and continue to the next recipe. 
:0 fh w
* > 256000
* ^Subject:\/.*
| formail -I "Subject: {* -BIG- *} $MATCH"
# ELSE if the previous recipe's conditions did not match (i.e., if the
# message is smaller than or equal to 250 KB), pipe it through spamc 
# (the client part of the spamc/spamd client-server pair). 
# Note: No lock file is needed for spamc.
:0 E f w 
| /absolute/path/to/spamc

# If the spamd daemon is not running on your system, comment out the
# above spamc recipe and uncomment the following (much less efficient)
# spamassassin recipe. The explicit lock file (spamassassin.lock)
# ensures that this recipe invokes only one instance of spamassassin
# at a time. This is to try to prevent the memory-hog spamassassin from
# using too much CPU/memory.
## :0 E f w: spamassassin.lock
## | /absolute/path/to/spamassassin
# If the spam score is 49.00 or higher (at least 49 R's), put it in my
# --infrared mailbox. I do this because Finding Bad Spam Delights Geeks and
# I might want to post about these in What's your highest-scoring spam.
# Note that SA 2.60+ records at most 50 spam-level "stars" so if you
# specify 51 or more "stars" in a Procmail recipe, it will never match.
# Important: If your "star" character (aka X-Spam-Level character) is a
# PMRE metacharacter, such as * or +, escape it with a backslash (\) so it
# will be interpreted as a literal character rather than a metacharacter.
# If the spam score is between 10.00 and 48.99, put it in my --2delete
# mailbox. Once I am assured that only spam is delivered to this box,
# I will have procmail delete it (discussed below). 
* ^X-Spam-Level: RRRRRRRRRR
# If the score is between 5.00 and 9.99, put it in my --red mailbox
# (which some people call the Spam or Junk mailbox).
* ^X-Spam-Level: RRRRR
# All messages that get here are put in my --yellow mailbox (which 
# some people call MaybeSpam or MaybeJunk). This includes {* -BIG- *} 
# messages and messages with a score of 4.99 or less.
# IMPORTANT: The 4 delivering recipes above are delivering to mailboxes
#  that are in maildir format on a Courier IMAP server. That's why no
#  lock file is used and why each mailbox specification begins with dot (.)
#  and ends with forward slash (/).  If you use a different mailbox format,
#  make sure you change these delivering recipes so that they are
#  appropriate for your system.


Using a Nesting Block to Optimize the SpamAssassin Recipes

We can improve the SpamAssassin-related recipes in the previous section by immediately delivering any {* -BIG- *} message. This will stop the processing of the message and avoid checking if it has an X-Spam-Level header, which it should not have because it was not piped through spamc. One way to do this is to replace the first recipe above with a recipe whose exactly one action item (discussed in Anatomy of a Recipe above) is a nesting block. For example, you could replace it with a recipe similar to the following.

# This outer "container" recipe is a non-delivering recipe and does
# not need a lock file. That's why there is no colon (:) after :0 in 
# the next line.
* > 256000
 :0 fh w
 * ^Subject:\/.*
 | formail -I "Subject: {* -BIG- *} $MATCH"
# IMPORTANT: In this example, the --yellow mailbox is in mbox format
#  and thus a lockfile is needed. If you use a different mailbox format,
#  make sure that you change the delivering recipe so that it is 
#  appropriate for your system.

This is an example of a nesting block, which you can read about in man procmailrc and see examples of in man procmailex. For information about and links to the Procmail manual pages, see The Fine Man Pages below.

See Also:



[Updated!] Setting Keywords or Labels

Inspired by cheap disk space and Opera Mail's & Gmail's search-don't-sort approach to email, some people are starting to keep all their messages in one giant universal mailbox and then using a combination of keywords (aka labels or flags or tags) and saved searches to zoom in on various groups of messages (“create virtual mailboxes”). This system has a number of advantages over using separate mailboxes, including:

I have not yet switched to this one-mailbox strategy, but I have started delivering my “yellow” (unknown, possibly spam) messages, which I discuss in the Using SpamAssassin section above, to my $DEFAULT mailbox. To set an IMAP keyword on these messages, I use a Procmail recipe like the following.

Note: The dollar sign ($) is escaped with a backslash (\) so it will not be interpreted as a Procmail metacharacter.

# this recipe will usually work with an mbox-formatted mailbox on a UW IMAP server	
* condition that matches a message that is yellow (unknown, possibly spam)
  :0 fh w
  | formail -i "X-Keywords: \$Label5" 

I then have my mail clients, Alpine, Pine 4.60+, Cone, Mulberry 4.0.1+, and SeaMonkey Suite, set up so that messages that have the $Label5 keyword are colored yellow.

If you use Opera Mail, the $Label5 IMAP keyword is not supported and you instead need to use an IMAP keyword named XOPL-N. For example, if you would like your possibly-spam messages to be labeled “Funny” ([clown (Funny label icon)]) in Opera Mail, substitute the following in the recipe above:

| formail -i "X-Keywords: XOPL-6"

I have tested this only with the Opera 9.0 Preview. Please let me know what, if any, IMAP keywords are supported in other versions of Opera.




If you have any tips about using Procmail to set keywords, state, flags, or any IMAP metadata, please let me know. I'm especially interested in the best way to do this for various mailbox formats and various IMAP servers.  


See Also:



Deleting a Message


[Important!]   Before you use a procmail recipe to delete a message, you should first have the recipe deliver to a 2delete or infrared mailbox (see the SpamAssassin recipe above for an example). Then monitor this mailbox — and delete the messages by hand — for about a month. After you are sure that the recipe catches only messages that you want to delete, edit the recipe so that it deletes the messages.  


One way to have procmail delete a message is to deliver it to /dev/null by using a recipe such as this:

* ^X-Spam-Level: RRRRRRRRRR

Another way to delete a message is to set the HOST variable to anything other than the hostname of the machine on which procmail is running. This will make Procmail immediately stop reading the procmailrc and return an exitcode of zero (success). For example:

* ^X-Spam-Level: RRRRRRRRRR
{ HOST = adios }

Another option, which is a variation of the previous option, is to unset the HOST variable by using a recipe like this:

* ^X-Spam-Level: RRRRRRRRRR
{ HOST }

This last recipe is more cryptic to someone — including you — who might try to understand it in the future so I recommend explicitly setting HOST to something such as adios or byebye or, which will make for better self-documenting code (aka literate programming). For more about the HOST variable, see Jari Aalto's Procmail Tips page in the section called Variable HOST and Dallman Ross's message to the Procmail list Re: How to tell promail to stop processing recipes?


  • Setting the HOST variable is more efficient than “delivering” to /dev/null.

  • A variable assignment, such as the HOST assignment above, is not considered an action item and so needs to be done within a nesting block (i.e., inside curly braces).

  • None of these three recipes need a lock and using one will cause procmail to complain about an “extraneous lockfile.” For details about why it does not make sense to lock /dev/null, see David W. Tamkin's 2004-03-14 message Re: looking for simple procmail recipe in comp.mail.misc.

  • Tip: If you use IMAP, you might want to set the IMAP \Deleted flag rather than actually deleting a message. This way you can use an IMAP client to monitor and expunge \Deleted messages. I discuss this in Using a MaybeSpam Mailbox in my blog.



Rejecting or “Bouncing Back” a Message

By the time Procmail gets a message it is too late to reject it at the SMTP level (aka “block it at the SMTP level” or “send a 5xx error code”). It is sometimes possible to use Procmail to “bounce back” a message or to send a fake SMTP-rejection message, but this is not recommended because...

  1. your system's receiving MTA will have already told the sending MTA that the message was accepted,
  2. it is often impossible for Procmail to determine the correct address to send the bounce-back message to,
  3. if you do use Procmail to send a bounce-back message, it will often be filtered or ignored by the recipient, and
  4. your system might be put on a block list.

For more about all this, see:




The word bounce is sometimes used to mean bounce forward, which is also known as redirect, resend, remail, relay, or MTA-style forward. Because of the potential for confusion, I try to always use either the phrase bounce forward or bounce back instead of the single word bounce, unless it is absolutely clear from the context which type of bounce I mean.

Note that bouncing forward, which can be done using ! in a procmail action item, also has problems. For details about bounce forwarding, see Forwarding and Plus Addressing above, especially the subsection called The Problems With Forwarding.

[ icon] I am collecting links about both bouncing forward and bouncing back in my bookmarks under the tag Messaging/Bouncing.




Minimizing False Positives With Greenlists and Bluelists

[prism separating light] If you use recipes, such as the SpamAssassin recipes above, to try to sort spam into a “red” (rubbish) box, you will no doubt have experienced a

false positive (FP) — a non-spam message that was falsely identified as spam and delivered to a rubbish box.

A key to avoiding this type of false positive is to first sort messages that are almost surely not spam. For example, I use a bluelist and a greenlist, along with Procmail, to pre-sort my solicited-bulk-email (SBE) and my trusted (good) non-SBE senders.¹

To be able to optimally use this strategy, you need...

  1. recipes that identify and sort “green” and “blue” messages into appropriate mailboxes. For example, I use a recipe similar to the Solicited-Bulk-Email recipe above to deliver my blue (bulk) messages to appropriate blue boxes and a recipe similar to this or this to deliver my green messages to my green box (which, of course, could be set up to be the $DEFAULT box).

  2. to invoke your bluelist and greenlist recipes after virus-detection tools are invoked.²

  3. to invoke your bluelist and greenlist recipes before spam-sorting recipes are invoked.²

  4. tools and automated systems that make it easy for you — and only you — to view and update your greenlists and bluelists using any mail client running anywhere.³ Possibilities include:
    1. Doing updates by having every message that you send auto-Bcc'd to a secret magnet-update address. The addresses in the To and Cc headers of these messages would then be automatically added to your greenlist by Procmail. In order to correctly identify and process these Bcc'd messages, procmail needs to be able to determine the original envelope recipient address (i.e., the address that was put in the Bcc header) of incoming messages.
    2. Doing an update via commands that you send in an email message or via a message that you bounce forward to specific secret magnet-update addresses. These messages could be processed by procmail recipes that do different things depending on the original envelope recipient address (i.e., which secret magnet-update address the message was bounce forwarded to).
    3. Using the IMAP COPY command to copy representative messages into your 2greenlist, 2bluelist, 2ungreenlist, and 2unbluelist IMAP mailboxes and then periodically run a script against these mailboxes to update your procmail-usable greenlist and bluelist.
    4. Using an IMAP client to compose a DRAFT message that contains magnet-update commands and periodically run a script against your DRAFT mailbox to update your procmail-usable magnets.
    5. A generalization of the previous technique (#4D) is to place messages in a magnet-update mailbox and use IMAP keywords or flags to specify what type of magnet the message represents (e.g., whether it should be used to create a green, blue, or red magnet). For an example of magnet keywords, see the keywords that I use, which include my greenFrom and sbeRecip keywords.
    6. Using server-side address books to maintain your greenlist and bluelist and then periodically run a script against these address books to update your procmail-usable greenlist and bluelist. Mulberry, Pine, Cone, and Mohogany are examples of email clients that support server-side address books. Pine uses IMAP to store & update remote address books and Mulberry can use either IMSP or the defunct ACAP. For some details about how I do this, see my 2005-Mar-01 message in the spamtools list.
    7. LOAF, which is a distributed-social-network greenlisting tool, that currently works with Pine (and Procmail of course!).

  5. tools that makes it easy to create and populate your base greenlist and bluelist. For example, I do this by running a shell script (like this) against my SENT mailboxes and my Pine address books.


Soon I (and I hope others) will write about various ways to implement this in the upcoming Infinite Ink wiki-blog, which will probably be based on Dokuwiki. For now, see:


¹ Some people and programs stratify messages using whitelists and blacklists, and call the messages that are in between these extremes “gray.” I prefer to use the metaphor of the full color spectrum to stratify my messages and that's why I deliver messages to magenta, violet, blue, green, lime, yellow, red, and infrared mailboxes.
The terms “whitelist” and “greenlist” are discussed in this message and this message in the Procmail list.

² In the ideal world, mailing-list management software would detect (& block!) viruses & spam, and not send these to the list members. But because 1) everyone, including mailing-list management software, can be infected; 2) viruses can be engineered to sneak into green & blue boxes; and 3) viruses can be destructive, I recommend that you check all messages for viruses.

³ When thinking about how to implement tools and procedures for maintaining greenlists and bluelists, we need to remember that most users are not going to have (or want) direct access to their server or their procmail recipes. We also cannot assume anything about their email client and we do not want to force them to do updates through a web browser (although that could be an option). [It sure would be nice to be able to assume clients and servers that support IMAP mailboxes, IMAP keywords, IMAP annotations, and server-side address books though!]




Pulling the Plug on Procmail

Once the .forward and .procmailrc files are in place and readable by your message transfer agent, procmail is plugged in and will be invoked each time a message arrives for you. If you have a problem, such as losing messages or a mail loop, you can quickly unplug procmail by getting rid of your .forward file. One way to do this is to rename it by typing the following:

mv .forward .forward.OFF

Just in case procmail is your system's local delivery agent (or becomes the LDA in the future), it is a good idea to also rename your .procmailrc file by typing:

mv .procmailrc .procmailrc.OFF

To turn procmail back on, type the following:

mv .forward.OFF .forward
mv .procmailrc.OFF .procmailrc


[Note]   Did you notice I violated my naming style by using capital letters in a file name?! Bear in mind the wise words of Ralph Waldo Emerson in his essay Self-Reliance:
A foolish consistency is the hobgoblin of little minds, adored by little statesmen and philosophers and divines.




If messages are not delivered correctly, here are steps you can use to try to solve the problem.


Look at Your Log File

Look at your $LOGFILE ($HOME/Procmail/pmlog) to see if you can determine what the problem is.


Look for Typos & Misplaced Comments in Your Configuration Files

Check these, and any other Procmail configuration files that you are using, for typos.


Also, if you have comments within a recipe, move them completely outside the recipe, for example, like this:

# comment
# another comment
rest of the recipe with no embedded comments

Comments are not allowed in some parts of a recipe and it is safest to not use them at all within a recipe. For example, if you specify a conditon like this:

* condition             # comment
then Procmail will interpret the string  # comment  to be part of the regular expression that it is trying to match!


Make Sure Your Configuration Files Use LF (Line Feed) Line Terminators

Make sure that each configuration file is a Unix ASCII text file with Line Feed (aka \n or ^J or ASCII character 10 or LF) line terminators. To view all characters in a file, both printing and non-printing characters, run this command:

cat -vet filename | less
     ||+--display tab as '^I'
     |+--display end of each line as '$'
     +--display non-printing characters

If filename contains a Carriage Return character, which will almost always cause a problem in a Procmail rc file, it will be displayed as ^M by this variation of the cat command.

Alternatively, on some () sytems, you can run this command:

file filename

Or, to check all files in your Procmail directory, run this:

file ~/Procmail/*

Each Procmail configuration file should be listed as one of the following.

ASCII text 
ASCII English text

If a file was created or edited on a non-Unix system and transferred using Copy & Paste, Samba, or a non-ASCII FTP transfer, the file might be listed as one of these:

ASCII text, with CRLF line terminators
ASCII text, with CRLF, CR, LF line terminators

Each of these means that there are lines in the file that are terminated with something other than the Line Feed character.

[Important!]  (‡) Not all versions of the file command distinguish between the different types of ASCII files -- does anyone know which versions of file make this distinction??? To learn more about the  file  command, see the  file  man page at, or (preferred) on your system.  


Since Unix uses only the Line Feed character to terminate a line, the Carriage Return character (aka \r or ^M or ASCII character 13 or CR) is interpreted to be a regular character by Procmail and it will almost always cause a problem. For examples of this causing a problem in Procmail and suggestions for how to fix it, see the following:

Tip 1: An easy way to fix the carriage-return problem in a single file is to open it in either nano or pico and then simply writeOut and eXit. For example, run  pico -w filename  and then:

Press...  To...
========  =====
^O        writeOut
ENTER     accept the filename
^X        eXit

This will convert the file to Unix format (LF line terminators) if it's not already in Unix format.

Tip 2: Another option is to use the command-line tool dos2unix, which is also known as tofrodos.

Tip 3: To learn about ASCII file transfers, see Dan Tobias's Use ASCII mode for HTML FTP transfers.


Check File and Directory Permissions

Use the instructions below to check the file and directory permissions of your .forward file. (These were set with the chmod commands in Step 11.)

Type This To Do This
cd Go to your home directory
ls -l .forward  Check the access permissions of your .forward; it should say -rw-r--r--
ls -l .procmailrc  Check the access permissions of your .procmailrc; it should say -rw-r--r-- (or what else will work here???)
ls -ld . Check the access permissions of your home directory; it should say drwx?-x?-x  where each question mark may be the letter r or a hyphen (drwx--x--x, drwxr-xr-x, drwxr-x--x, drwx--xr-x are each acceptable)


  • Not all systems require the .forward file to be world readable so you might be able to set your home directory permissions to drwx------ and your .forward file permissions to -rw-------.

  • On many systems the .forward and .procmailrc files will not be used if they are group or world writable. Whether your system has this limitation or not, you probably do not want other people to be able to edit your .forward and .procmailrc files!


Turn on Full Logging

If the above steps do not locate the problem, edit your ~/.procmailrc so that it includes the following lines. If you're following the instructions on this page, variations of these lines are already in your .procmailrc.

Test procmail by sending yourself messages as described in Steps 12 and 13 again. Look at your $LOGFILE, which will contain verbose entries and a blank line between each message's log entry (that's what the two-line LOG setting does), to see if you can now determine what the problem is.

If you can't figure out what's going on in your log because messages are arriving simultaneously and their log info is intertwined, see Bart Schaefer's message Re: Procmail log intelligibility and David W. Tamkin's followup message in the Procmail mailing list.

After you decipher your log and get procmail to work, you probably will want to set VERBOSE=no and "unplug" the LOG line by preceding it with # (or ## if you are using my style).


See if There is a Global procmailrc

If there is a global procmailrc file on your system, its settings and recipes are used by all users on the system and it is read before your personal procmailrc file. It often resides in one of the following files:


If neither of these files exist on your system, it is possible that your system administrator configured Procmail to use a different global rc file. The location of the global rc file may be documented in the Procmail manual page on your system. To see how your local Procmail is configured, type

man procmail

followed by


The second command searches forward in the man page for the string  global  and will jump to a line that looks something like this:

/etc/procmailrc        initial global rcfile

If the manual page is from the same install as the Procmail binaries, it should contain the correct path to the global rc file. If neither the procmail man page nor exploring your system turns up a global procmail rc file, ask in your system's discussion group or ask your system administrator.

Another thing to look for on your system is the directory /etc/procmailrcs. To see if this directory is on your system and to list the directory's contents if it exists, type

ls -l /etc/procmailrcs
                     make sure you type this s! 

To learn more about the global procmailrc file, the files in the procmailrcs directory, what user the recipes in these files are run as, and how they relate to the user procmailrc file, see:


Check $SHELL and $PATH

If you invoke programs from your .procmailrc, it is possible that either the SHELL or PATH environment variable that procmail is using is causing problems. To check the settings that procmail is using, put the following three lines in your .procmailrc after the line that sets the LOGFILE environment variable.

LOG="My PATH is currently $PATH
My SHELL is currently $SHELL

The third line contains only the double quote character. It closes the beginning quote, which is on the first line, and inserts an extra linefeed (and thus a blank line) in your log to make it more readable.

Next, send yourself a message so that the commands in your .procmailrc are run and the above lines are appended to your $LOGFILE. Now view the tail of your log using for example

tail -n 30 $HOME/Procmail/pmlog

This displays the last 30 lines of your log. If $SHELL is anything other than the Bourne shell (sh), the Bourne again shell (bash), or another Bourne shell derivative, put a line like this at the top of your .procmailrc file.


Of course you should make sure that /bin/sh exists on your system! To determine the path to sh on your system, run one of the following:

which sh
type sh
whereis sh
where sh
locate sh

For some information about the problems with non-Bourne-derived shells, see the 2004-Jan-29 message Re: forward to multiple users by David W. Tamkin.

If your $PATH does not contain all the directories from which you run programs and if you don't always specify the absolute path to programs, you need to add the needed directory (or directories) to your $PATH. For example, if you installed a CVS version of SpamAssassin (SA) in your $HOME directory and if you want to invoke that version of spamassassin or sa-learn from Procmail, you may want to add a line like this


This line should be put near the top of your .procmailrc. For example, immediately after the SHELL setting.


[Important]   ... you shouldn't alter PATH unless there's something actually missing from it or the order is wrong.   
  -- Philip Guenther in a message in the procmail mailing list  




In this Quick Start, I suggest that you do not explicitly set the Procmail DEFAULT and ORGMAIL environment variables, which are used to specify the default inbox (defined above) and the ORiGinal default inbox, respectively. Instead I suggest that you use Procmail's default DEFAULT and default ORGMAIL settings because doing this . . .

If you want to override the default DEFAULT setting, include lines similar to the following in your .procmailrc:

MAILDIR=$HOME/Msgs        # Make sure this directory exists!	

Note that the mailbox IN-catchall will be located in the MAILDIR directory (as long as the value of DEFAULT is specified using a relative path rather than an absolute path). If you want DEFAULT to be a maildir-formatted mailbox (rather than mbox-formatted), append a trailing slash (/) to the mailbox name. For example, use this:

or, if this maildir-formatted mailbox will be served by a Courier IMAP server, use this:
        Note the leading dot

[Important!] In any case, the Procmail MAILDIR variable, which is an entirely different entity from maildir mailbox format, should be specified in your .procmailrc without a trailing slash.


If you want your DEFAULT maildir-formatted mailbox to be at the top level of your Procmail MAILDIR directory, you can put something like these two lines in your .procmailrc:

MAILDIR=$HOME/Maildir        # Make sure this directory exists!	
                     Note that DEFAULT includes a trailing '/' and MAILDIR does not

Alternatively, you could use these two lines:


Or these two lines:


I prefer to explicitly set DEFAULT to $HOME/Maildir/ rather than $MAILDIR/ or ./ because there are sections of my procmailrc where I change Procmail's current working directory ($MAILDIR), and I want DEFAULT to have a fixed value, i.e., be independent of the cwd.

On a Courier IMAP server with a default configuration, these settings will make your Procmail “default inbox” or “system mailbox” (i.e., the mailbox that is specified by the Procmail DEFAULT variable) be the mailbox that is served when an IMAP client sends a request for the IMAP INBOX. Note that INBOX is a special IMAP name and the IMAP protocol translates this special name to the actual default mailbox on that particular IMAP server. Examples of actual default mailboxes include:

$HOME/Maildir (often used on a Courier IMAP server).

[Yes, it is confusing that the word maildir has three different meanings — the name of the mailbox format (maildir), the name of the Procmail variable (MAILDIR), and the name of the directory (Maildir)!]


You can check $DEFAULT and $MAILDIR, which $DEFAULT may depend on, by using the technique described in the previous section, i.e., by putting the following three lines in your .procmailrc after the lines that set the LOGFILE, MAILDIR, and DEFAULT environment variables.

LOG="My MAILDIR Directory is currently $MAILDIR
My DEFAULT Inbox is currently $DEFAULT

If Procmail is unable to deliver to $DEFAULT, for example if there is no space available, it will attempt to deliver to $ORGMAIL. To determine $ORGMAIL, run:

procmail -v

and look at the value of “Your system mailbox.”



  • Make sure that Procmail is able to both create and write to the mailboxes $DEFAULT and $ORGMAIL.

  • If you want to change the value of $ORGMAIL, it is best to specify this in the procmail source code and recompile procmail.

  • The $ORGMAIL mailbox must not be a symbolic link or a file with more than one hard link.

  • If you are using maildir-formatted mailboxes, it is best to specify both $ORGMAIL and $DEFAULT in the procmail source code and recompile. This is discussed above in Details Specific to maildir Format.  

    Question: What, if any, problem will occur if you set DEFAULT to a maildir-formatted mailbox in your .procmailrc rather than in the source code???


Where is my Mail?

The first thing to do when you are trying to figure out where Procmail delivered your mail is to look at your log file. If it is hard to interpret your log file, or if you don't have a log file, good places to look for missing messages are your $DEFAULT and $ORGMAIL mailboxes. If Procmail cannot deliver a message to the intended mailbox, it will try to deliver it to $DEFAULT. If it cannot deliver to $DEFAULT, it will try to deliver to $ORGMAIL. Details are in the previous section, Check $DEFAULT and $ORGMAIL.


Does ~/.forward Exist?

To see if ~/.forward exists and display it if it does, type the following

cat ~/.forward

If this file exists and if your system is set up to use it, it is invoked before Procmail. If you want your mail to be processed by the recipes that are in your ~/.procmailrc file, set up your system so that your ~/.forward file either

If you want to both forward messages and use Procmail, do the forwarding via a Procmail recipe.

For more about the ~/.forward file, see Set Up Your .forward File (not required on most systems) above and the next section.


Try Alternate .forward Files (not relevant on most systems)

If you invoke procmail via a .forward file and you are still having problems, try these alternate .forward files and see era eriksson's Debugging Procmail Recipes at


[Important]   If your system uses procmail as its local delivery agent or uses an MTA that does not respect the .forward file, this section is not relevant to you.  


The command you put in your .forward file depends on the version of Unix your system is running, the message transfer agent your system is using, and how your system administrator configured the system. On some systems the procmail manual page contains information that is specific to your system, including the best command to put in your .forward file. To see what is suggested in your system's procmail manual page, type the following at your system's Unix prompt:

man procmail | less

To search forward in the manual page for the word kludge, type:


The command in the paragraph below the paragraph that contains the word kludge may be the best command to use on your system. If you want to read earlier text in the manual page, you can go up half a page by typing u.

If neither the .forward command in Step 9, which is


nor the one suggested in your system's procmail man page work, try a modified version of the following

"|IFS=' ' && exec /absolute/path/to/procmail -f- || exit 75 #nancym"




  • Make sure you include all the quotation marks, both double (") and single (').
  • The vertical bar (|) is a pipe, and on a U.S. keyboard is typed as SHIFT-backslash.
  • Replace /absolute/path/to with the correct path for procmail (see Step 0).
  • Replace nancym with your user ID. You need to put your user ID in your .forward so that it will be different from any other .forward file on your system. This circumvents a design error in sendmail. If your system uses an MTA other than sendmail, the comment (what's after the #) is not needed but does not hurt.
  • If procmail resides below your home directory, type the absolute path. Do not expect $HOME, ~, or a relative path to work in your .forward file, since commands in a .forward file are run from sendmail without setting up your normal login environment.
  • The .forward file must be a real file


If that doesn't work, try these (with nancym replaced by your login name of course!):

"|exec /usr/local/bin/procmail #nancym"
"|exec /usr/local/bin/procmail USER=nancym"
"|IFS=' ';exec /usr/local/bin/procmail #nancym"
"|IFS=' ';exec /usr/local/bin/procmail USER=nancym"
"|/usr/local/bin/procmail #nancym"
"|IFS=' '&&p=/usr/local/bin/procmail&&test -f $p&&exec $p -f-||exit 75#nancym"

These formats can be tried in different combinations; and the leading "| can be tried as |", or vice versa. Make sure you replace nancym with your user ID!  era eriksson's Procmail FAQ includes a detailed explanation of the last .forward command.


[little green bug] Known Procmail Bugs

For more about Procmail bugs and patches for fixing them, see Philip's TODO list for procmail, Philip's list for procmail warts, the Procmail HISTORY file, and the October 2004 thread in the Procmail list about Who is the procmail maintainer?


More Troubleshooting Links

If you are still having problems, see:



See Also

The Fine Man Pages

Make sure you read the six Procmail man pages on your system. If the manual pages are from the same install as the Procmail binaries on your system, they will document the configuration that is specific to your system. To find out which Procmail version is documented, type man procmail and then type  /SOURCE  to search for the SOURCE section. For example, here is the SOURCE section of man procmail at and

If you want to read or link to hypertext man pages, here are the 3.22, (version 3.22 I think), 3.15.2 and 3.15.1 man pages. Some links in the man pages are broken so I recommend that you use the or pages.

The following man pages are not part of the Procmail package, but may be useful to you.

Many more man pages are available at the FreeBSD Hypertext Man Pages, where you can choose from a drop-down list of over 100 flavors and versions of Linux and Unix. Some have recent Procmail man pages and some have ancient ones.



Other Docs Shipped with Procmail

You can get concise help for procmail, formail, lockfile, and mailstat by typing the following at the Unix prompt on your system

   procmail -h
   formail -h
   lockfile -h
   mailstat -h

More Procmail docs are sometimes in /usr/share/doc/procmail, but these are very outdated and you can get more current and robust Procmail information in the documents listed in the next two sections.



Links to Pages that Link to this Page

This is one of the most popular pages here at Infinite Ink. I am collecting a list of pages that link to this page so I can find out where everyone is coming from, to provide some links that might be interesting to readers of this article, and as a way to thank everyone who links to this page.



More Links



Procmail Discussion Groups

Public discussion groups are a tremendous resource and they — along with the fine manual — are where I learned almost everything I know about Procmail. For details about the Procmail mailing list, including how to subscribe and unsubscribe, see / mailman / listinfo / procmail. In addition to participating in the list via email, you can access — and in some cases participate in — the list using any of the following.

[G] For an overview of the various Gmane incarnations of the Procmail list, including a form for searching the Gmane archive of the list, see Information about gmane.mail.procmail. Currently the Gmane archive of the Procmail list goes back to February 2002, but it would be great if someone would submit the entire Procmail list archive to Gmane. If you would like to support Gmane and get rid of the Gmane Google ads, donate money to Gmane.

There are a lot of other places around the Net where people discuss Procmail, including the groups that show up in the results of these searches:

If you visit the Usenet group comp.mail.misc (c.m.m), please ignore the anonymous coward, his many aliases (one of which is AC), and any thread started by AC or an AC alias.  Tip: To maintain (or restore!) your sanity, I recommend avoiding c.m.m altogether.


[Note]   Many archives munge email addresses in order to hide them from email-address harvesters. But this is a problem when the discussion is about an email address (or about a fragment of an email address). For example, a 2004-Nov-26 message from Ruud H.G. van Tol with Subject “Re: alleged bug in ^TO_ macro: character '+' *is* allowed in emails” was archived in many different ways, including: Tip:  At Gmane you can view the unmunged version of a message by appending /raw to the message's URL. This is discussed in the Gmane FAQ.  



In addition to searching discussion groups, which is discussed in the previous section, you can use the following links to search for Procmail-related tools and documents.

You can also use this form to search the web, the Infinite Ink site, or the site (my blog) for information about Procmail (or about anything!).

Infinite Ink




Questions to You the Reader



Author Blurb for the Book (feedback is welcome on this too!)

Nancy McGough started Infinite Ink,, in 1992. Infinite Ink is dedicated to writing, teaching, and publishing about mathematics, science, computing, and philosophy. Before she started Infinite Ink, Nancy worked at Microsoft first as a technical writer and then as a program manager designing tools and strategies to improve communication and information access within Microsoft. The project, called Integration of Information Access Tools (IOIAT), included WinBBS, a MS Windows front end to Usenet News. Nancy has taught mathematics and computer science courses at universities, colleges, and at a grade school. She is a fan of standards-compliant, modular, open-source software, and she is especially interested in intertwingular software and software that helps people communicate and collaborate. Her primary software tools are Pine and Mulberry for IMAP messaging; nn and Pine for NNTP messaging; Dreamweaver and Vim for web page development; Vim for powerful text editing; SecureCRT for ssh connections & port forwarding; Powermarks for intertwingular bookmark management; Info Select for intertwingular information management; and (of course!) Procmail for automated message processing. Her favorite operating systems are Mac OS X & FreeBSD and her favorite mail- and web-hosting providers are Verio and




Thanks to Philip Guenther, the current former Procmail maintainer, for sending me feedback on the 23 April 2001 incarnation of this page and for all the work he's done on Procmail.

Thanks to John Levine of Taughannock Networks for giving me an account on his system which is running Courier IMAP, Qmail, and Procmail. It's because of this account that I was able to learn about and write about delivering to maildir-formatted mailboxes.

Thank you to these people who sent me feedback on this Procmail Quick Start:

And to these people who sent me feedback back in 1994 when I first wrote the Filtering Mail FAQ:

Thank you also to the developers of procmail, especially the creator, Stephen R. van den Berg, and the current maintainer, Philip Guenther; the people who have written procmail documentation; the members of the Procmail mailing list; and everyone else who has sent me feedback. Please let me know if I have left you out of my thank-you lists, or if you know the URL of any of the unlinked people in the lists.

Thanks to Norm Walsh and Lenny Muellner for letting me use these DocBook admonition graphics:

[Tip]   Tip
[Note]   Note
[Important!]   Important
[Warning!]   Warning

Finally thank you to my friends, family, and Internet acquaintances who have helped me to make Infinite Ink what it is. Special thanks to Bob Tinkelman of New York Net for giving me a free T1 line to my apartment (wow!) and to Sean Shapira of Jazzie Systems for giving me free web space and bandwidth for years.

Procmail Quick Start: An introduction to email filtering with a focus on procmail
Copyright © Infinite Ink & Nancy McGough
  1st published in Filtering Mail FAQ 1994
published here 1999
updated 05-Jun-2006
tweaked 27-Nov-2007