UC San Diego SearchMenu

Procmail (Email Filtering Agent)

Procmail is a program available on all ACMS machines which allows you to automatically process your email as it arrives into your account. You can sort, delete, forward, and store messages depending on their sender, their subject, or other characteristics. For example, you could have Procmail direct all messages from your friend at UC Berkeley into a folder called "berkeley". You could then read the messages in this folder at your leisure.

To use Procmail you need to create a set of "recipes," or instructions, for Procmail to follow each time you receive a message. These "recipes" reside in a file called ".procmailrc" in your home directory. You can use a Unix editor, such as vi or pico, to create this file. See the vi or vim help articles for assistance in using vi.

The following two sections, "Examples of common uses," and "A more complex example," lead you through the creation of several recipes that you might want to copy or modify for your own use. Please read the fourth section, "Resolving problems with procmail, " if you have any trouble with your new Procmail recipe set.

Examples

Common uses

                                      PROCMAIL: EXAMPLES OF COMMON USES
                                                                           
   Procmail is a versatile program and can be put to a number of uses.
   Some common applications include:
   
         * Saving letters from a particular person to an Elm folder
         * Saving letters with a particular subject to a Pine folder
         * Deleting messages from a particular person
         * Forwarding messages to different addresses based on the sender.
           
   Each of these examples may be used as-is, without modification, or you
   may change them to suit your particular needs. Please see the "man
   procmail" manual entry for more specific information on Procmail's
   capabilities and functions. In particular, many of these rules can be
   used at the same time simply by including them all in the same
   .procmailrc file.
   
   For each of the following samples you must create a file called
   '.procmailrc' in your Unix home directory. See the articles available
   under 'help editor' for basic help on creating this file.
   
Saving letters from a particular person to a folder

        The following '.procmailrc' file will save messages coming from
   anybody with "peter" in their email address, including
   "peter@ucsd.edu," "jpeters@ucsd.edu," and others. The messages will be
   saved into an Elm folder called 'peter.folder'. This folder is
   accessible under Elm through the "c)hange folder" command at the main
   menu, or from Pine using its 'Folder Index' command.
   
   Please note that the first rule in this file doesn't really have
   anything to do with mail from Peter. It's there to ensure that you
   don't lose mail in the event of an error in your .procmailrc file;
   every message will be copied to a folder called "backup" before
   anything else is done with it. Once you're satisfied that everything
   is working properly, you can remove the section so that your disk
   quota isn't used up by copies of old messages.
   
   Place the following into your .procmailrc file:
   

                         # Remove these three lines when you're sure this works
                         :0 c:
                         Mail/backup.folder

                         :0:
                         * ^From.*peter
                         Mail/peter.folder

   You can, of course, substitute your own folder name for "peter.folder"
   above, and you can also use another email name instead of "peter".
   
Deleting messages from a particular person

        It's sometimes necessary to mechanically ignore messages sent from
   one person or account. Here's how you can do it with Procmail.
   
   Please note that this will only throw away these messages. If you're
   receiving threatening or harassing messages from somebody, please
   contact acs-consult@ucsd.edu so that more direct action can be taken.
   
   Put the following into a .procmailrc file:

                         # Remove these three lines when you're sure this works
                         :0 c:
                         Mail/backup.folder

                         :0
                         * ^From.*evildude@somewhere.edu
                         /dev/null

   Here, the only thing for you to customize is the e-mail address of the
   person you wish to ignore. You should be as specific as possible when
   writing out this e-mail address, since you probably don't want to
   randomly delete messages simply because they're from someone with
   "peter" in their login name.
   
   The '/dev/null' folder listed here isn't really a folder; it's more
   like the system's trash can. You can use it anywhere you'd list a
   folder name, but remember that messages put into this folder are
   DESTROYED!
   
Forwarding messages to different addresses based on the sender.

        This is the most complicated example so far. Sometimes you have more
   than one email account, but you don't want to forward ALL your mail
   from the other accounts into your main one (for instructions on this,
   see the 'help forward' article). Here's an example which only forwards
   e-mail from the CSE department to a separate address:
   

                         # Remove these three lines when you're sure this works
                         :0 c:
                         Mail/backup.folder

                         :0
                         * ^From.*cse-announce
                         ! metoo@somethingelse.ucsd.edu

   Note that you can use a "* ^Subject:" line instead of the ^From line
   above if you want to forward messages with a certain subject to
   another account. Also note the "!" exclamation point at the beginning
   of the line which signifies that the mail should be forwarded to the
   following address.

Combining several 'recipes' in one .procmailrc

                                      PROCMAIL: A MORE COMPLEX EXAMPLE
                                                                           
   As was mentioned in the previous article, it's possible to combine a
   number of rules into one '.procmailrc' recipe file. The following
   .procmailrc file incorporates most of the ideas you learned previously
   into a single recipe file. Note the second rule which contains two
   criteria which must be satisfied before the mail is forwarded to
   another e-mail address.
   

                  # Once again, remove these lines when you're satisfied
                  # that everything is working properly.
                  :0 c:
                  Mail/backup.folder

                  # This rule will forward all mail from peter with the
                  # word 'compilers' in the subject to the e-mail address
                  # 'william@somewhere.edu'
                  :0
                  * ^From.*peter
                  * ^Subject:.*compilers
                  ! william@somewhere.edu

                  # Save all mail from 'cse-dept' to an Elm folder.
                  :0:
                  * ^From.*cse-dept
                  Mail/deptmail.folder

                  # Save any mail with 'scuba' in the Subject: to an Elm
                  # folder.  Note that if for some reason you received
                  # mail from the 'cse-dept' about 'scuba', the message would
                  # have be saved to the first folder rather than this one.
                  :0:
                  * ^Subject:.*scuba
                  Mail/scuba.folder

Sending an auto reply while on vacation

PATH=/bin:/usr/bin:/software/common/bin
MAILDIR=$HOME/mailroom      #you'd better make sure it exists
LOGFILE=$MAILDIR/procmail.log   #recommended

#   Vacation work-alike                  (3/6/98) Accurso
#
#   This is an annotated and slightly modified version of the 
#   vacation work-alike example given in "man procmailex".
#   The use of ^TO is the significant modification.
#   See also "man procmailrc".
#   
#   First we must decide whether to send an auto reply.
#   All the egrep conditions (* lines) must be satisfied.
#   If so, headers (h) of the current message are fed to
#   formail which checks the vacation.cache to find out
#   if the sender has already received an auto reply.
#   We will lock vacation.lock while processing this
#   recipe to avoid clashes when updating the cache.
#   
#   This recipe waits (W) for a return from formail.
#   Without the (c) procmail would stop processing
#   after completing this recipe because it is
#   a delivery recipe, it delivers headers to formail.
#   
#   The conditions ^TO and ^FROM_DAEMON are more than
#   meet the eye.  
#
#   ^TOzz1demo is satisfied if zz1demo
#   appears in any recipient header To: Cc: Bc:.
#   This avoids sending auto replies to messages that
#   were addressed to an alias or maillist, but not
#   explicitly to zz1demo.
#
#   !^FROM_DAEMON makes sure we do not auto reply to
#   messages from any of a wide variety of daemons.
#   
#   "!^X-Loop: zz1demo@ieng9.ucsd.edu" avoids replying
#   to our own auto reply, notice below that this X-Loop
#   header is inserted into the auto replies we send out.

SHELL=/bin/sh    # for other shells, this might need adjustment

:0 Whc: vacation.lock
* ^TOzz1demo
* !^FROM_DAEMON
* !^X-Loop: zz1demo@ieng9.ucsd.edu
| formail -rD 8192 vacation.cache

#   Due to (e) recipe below is executed if the preceding one
#   returns an error status.  In this case it is not really
#   and error, it is just the signal from formail to go
#   ahead with the auto reply.  Notice that if in the 
#   preceding recipe the egrep conditions are not met
#   and that causes the formail cache check to be 
#   skipped, procmail is [somehow] clever enough to skip
#   this recipe.
#   
#   The headers (h) of the current message are fed to the
#   formail in this recipe in order to construct the
#   headers for the auto reply.
#   
#   The (c) in this recipe causes the whole
#   current message to be processed after this recipe.
#   Typically that means it will be processed with no
#   further recipies and that is how you get a copy in your
#   mailbox.  There is no need for a lock while executing
#   this recipe so none is used.

:0 ehc         # if the name was not in the cache
  | (formail -rA"Precedence: junk" \
   -A"X-Loop: zz1demo@ieng9.ucsd.edu" ; \
   echo "I received your mail, but I will be away"; \
   echo "from the office until Monday Dec 15th."; \
   echo " ";\
   echo "If this is an urgent matter, please call my office XXX-XXXX ";\
   echo " ";\
   cat $HOME/.sig \
  ) | $SENDMAIL -oi -t

Automatically discarding or returning unwanted mail

Return to sender with "reject" notice (not for spam!)

# This procmailrc will automatically reject and bounce mail from
# certain addresses. NOTE: DO NOT USE THIS FOR SPAM! Only use it for
# folks that you know have a valid return address.
#
# This file can be dropped into your home directory as '.procmailrc', or
# inserted into your existing '.procmailrc', with or without the
# comments.
# -zz1sn 2/18/98

#
# The :0 is the start of a rule. Note, blank lines in a rule are NOT
# happy. Don't insert any blank lines between the :0 and the line with
# $SENDMAIL, or the rule won't work. Also, don't put any comments
# within the rule, either.

#
# The *^From:.*example.*nuisance
#  line indicates the string you want to match. If the From
# header in the e-mails you want to match looks something like
# From: Block Head <llarry@ancientgames.com>
# you can use a rule like: *^From:.*llarry.*ancientgames
# or perhaps something like *^From:.*Block Head
# (Remember, case is important - capitals are different from lowercase!)
#
# You want to be as specific as possible, but general enough to
# catch the person's e-mails. The '*^From: bit ensures that the
# rule only matches on the 'From:' header, and the '.*' sequence
# is a wildcard (match 0 or more occurrences of any character).
#
# Replace 'example.*nuisance' with your expression; otherwise, this
# rule won't do a thing.
# 
# If you want to reject mail from more than one source you can
# repeat the whole rule (from the :0 line to the SENDMAIL line)
# as many times as necessary in your .procmailrc file.  Put
# a blank line between rules.
#
# This rule bounces the mail. First, it pipes through a series of
# commands that generate a new e-mail. 'formail' takes the old e-mail
# and generates a response; we replace the 'From:' line with
# 'devnull@ucsd.edu' (which silently discards all mail) to prevent
# mail loops caused by ricocheting bounces.
#
# We then pipe the result through $SENDMAIL -oi -t, which tells
# sendmail to ignore dots as end-of-file markers, and to grab the
# sender/recipient info from the message body. 
#
# Note syntax; anything that should be in the message needs to go in
# an 'echo' statement inside the parentheses. It should be
# double-quoted, and should not contain funny characters (*, $, etc.).
# The ' \' (space-backslash) needs to be at the end of each line
# except the last to indicate that technically the entire rule belongs
# on one line.
#
:0
*^From:.*example.*nuisance
|( formail -rI"From: Responses will be automatically discarded <devnull@ucsd.edu>"; \
   echo "Your mail has been administratively rejected."; \
   echo "It was NOT received." \
 ) | $SENDMAIL -oi -t

Discard/block e-mail messages (without return to sender)

# This procmailrc will automatically reject and discard mail from
# certain addresses. 
#
# This file can be dropped into your home directory as '.procmailrc', or
# inserted into your existing '.procmailrc', with or without the
# comments.
# -zz1sn 3/09/98

#
# The :0 is the start of a rule. Note, blank lines in a rule are NOT
# happy. Don't insert any blank lines between the :0 and the line with
# $SENDMAIL, or the rule won't work. Also, don't put any comments
# within the rule, either.

#
# The *^From:.*example.*nuisance
#  line indicates the string you want to match. If the From
# header in the e-mails you want to match looks something like
# From: Block Head <llarry@ancientgames.com>

# you can use a rule like: *^From:.*llarry.*ancientgames
# or perhaps something like *^From:.*Block Head
# (Remember, case is important - capitals are different from lowercase!)
#
# You want to be as specific as possible, but general enough to
# catch the person's e-mails. The '*^From: bit ensures that the
# rule only matches on the 'From:' header, and the '.*' sequence
# is a wildcard (match 0 or more occurrences of any character).
#
# Replace 'example.*nuisance' with your expression; otherwise, this
# rule won't do a thing.
#
# This rule silently discards all mail containing the matched From:
# address. If you want to discard mail from more than one address,
# duplicate the entire 3-line rule, from :0 to /dev/null (changing the
# wildcard expression appropriately)
#
#
:0
*^From:.*example.*nuisance
/dev/null

Resolving problems with procmail

                                      RESOLVING PROBLEMS WITH PROCMAIL
                                                                           
   If you're having problems with Procmail, you might want to see a Zebra
   in person: 
Zebra hours and locations.
   
   The full documentation for Procmail is available online under the Unix "man" command. Look under the "man procmail" command for an
   introduction to the available documentation.