Man Linux: Main Page and Category List


       procmailex - procmail rcfile examples


       $HOME/.procmailrc examples


       For a description of the rcfile format see procmailrc(5).

       The   weighted   scoring  technique  is  described  in  detail  in  the
       procmailsc(5) man page.

       This man page shows several example recipes.  For examples of  complete
       rcfiles  you can check the NOTES section in procmail(1), or look at the
       example rcfiles in /usr/share/doc/procmail/examples.


       Sort out all mail coming from the  scuba-dive  mailing  list  into  the
       mailfolder scubafile (uses the locallockfile scubafile.lock).

              * ^TOscuba

       Forward all mail from peter about compilers to william (and keep a copy
       of it here in petcompil).

              * ^From.*peter
              * ^Subject:.*compilers
                 :0 c


       An equivalent solution that accomplishes the same:

              :0 c
              * ^From.*peter
              * ^Subject:.*compilers

                 :0 A

       An equivalent, but slightly slower solution that accomplishes the same:

              :0 c
              * ^From.*peter
              * ^Subject:.*compilers

              * ^From.*peter
              * ^Subject:.*compilers

       If  you  are fairly new to procmail and plan to experiment a little bit
       it often helps to have a  safety  net  of  some  sort.   Inserting  the
       following  two  recipes  above all other recipes will make sure that of
       all arriving mail always the last 32 messages will  be  preserved.   In
       order  for it to work as intended, you have to create a directory named
       `backup' in $MAILDIR prior to inserting these two recipes.

              :0 c

              :0 ic
              | cd backup && rm -f dummy `ls -t msg.* | sed -e 1,32d`

       If your system doesn't generate or generates incorrect leading `From  '
       lines  on  every mail, you can fix this by calling up procmail with the
       -f- option.  To fix the same problem by different means, you could have
       inserted  the  following  two  recipes  above all other recipes in your
       rcfile.  They will filter the header of any mail through formail  which
       will  strip  any  leading  `From  ',  and  automatically regenerates it

              :0 fhw
              | formail -I "From " -a "From "

       Add the headers of all messages that didn't come from the postmaster to
       your  private header collection (for statistics or mail debugging); and
       use the lockfile `headc.lock'.  In order to make sure the  lockfile  is
       not  removed  until  the  pipe has finished, you have to specify option
       `w'; otherwise the lockfile would be removed as soon as  the  pipe  has
       accepted the mail.

              :0 hwc:
              * !^FROM_MAILER
              | uncompress headc.Z; cat >>headc; compress headc

       Or, if you would use the more efficient gzip instead of compress:

              :0 hwc:
              * !^FROM_MAILER
              | gzip >>headc.gz

       Forward  all  mails  shorter  than  1000  bytes  to my home address (no
       lockfile needed on this recipe).

              * < 1000
              ! myname@home

       Split up incoming digests from the  surfing  mailing  list  into  their
       individual messages, and store them into surfing, using surfing.lock as
       the locallockfile.

              * ^Subject:.*surfing.*Digest
              | formail +1 -ds >>surfing

       Store everything coming from  the  postmaster  or  mailer-daemon  (like
       bounced   mail)   into   the   file  postm,  using  postm.lock  as  the

              * ^FROM_MAILER

       A simple autoreply recipe.  It makes sure that neither  mail  from  any
       daemon (like bouncing mail or mail from mailing-lists), nor autoreplies
       coming from yourself will be autoreplied to.  If this precaution  would
       not  be  taken,  disaster  could result (`ringing' mail).  In order for
       this recipe to autoreply to all the incoming mail, you should of course
       insert  it  before  all  other  recipes in your rcfile.  However, it is
       advisable to put it after any  recipes  that  process  the  mails  from
       subscribed  mailinglists;  it  generally is not a good idea to generate
       autoreplies to  mailinglists  (yes,  the  !^FROM_DAEMON  regexp  should
       already  catch  those,  but  if the mailinglist doesn't follow accepted
       conventions, this might not be enough).

              :0 h c
              * !^FROM_DAEMON
              * !^X-Loop: your@own.mail.address
              | (formail -r -I"Precedence: junk" \
                  -A"X-Loop: your@own.mail.address" ; \
                 echo "Mail received.") | $SENDMAIL -t

       A more complicated autoreply  recipe  that  implements  the  functional
       equivalent of the well known vacation(1) program.  This recipe is based
       on the same principles as the last one (prevent  `ringing'  mail).   In
       addition   to  that  however,  it  maintains  a  vacation  database  by
       extracting  the  name  of  the  sender  and   inserting   it   in   the
       vacation.cache  file  if  the  name was new (the vacation.cache file is
       maintained by formail which will make sure that it always contains  the
       most  recent  names,  the  size  of the file is limited to a maximum of
       approximately 8192 bytes).  If the name was new, an autoreply  will  be

       As  you  can  see,  the  following  recipe  has  comments  between  the
       conditions.  This is allowed.  Do not put comments on the same line  as
       a condition though.

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

              :0 Whc: vacation.lock
               # Perform a quick check to see if the mail was addressed to us
              * $^To:.*\<$\LOGNAME\>
               # Don't reply to daemons and mailinglists
              * !^FROM_DAEMON
               # Mail loops are evil
              * !^X-Loop: your@own.mail.address
              | formail -rD 8192 vacation.cache

                :0 ehc         # if the name was not in the cache
                | (formail -rI"Precedence: junk" \
                     -A"X-Loop: your@own.mail.address" ; \
                   echo "I received your mail,"; \
                   echo "but I won't be back until Monday."; \
                   echo "-- "; cat $HOME/.signature \
                  ) | $SENDMAIL -oi -t

       Store  all  messages concerning TeX in separate, unique filenames, in a
       directory named texmail (this directory has to exist); there is no need
       to use lockfiles in this case, so we won't.

              * (^TO|^Subject:.*)TeX[^t]

       The  same as above, except now we store the mails in numbered files (MH
       mail folder).

              * (^TO|^Subject:.*)TeX[^t]

       Or you could file the mail in several directory  folders  at  the  same
       time.  The following recipe will deliver the mail to two MH-folders and
       one directory folder.  It is actually only  one  file  with  two  extra

              * (^TO|^Subject:.*)TeX[^t]
              texmail/. wordprocessing dtp/.

       Store  all  the  messages  about  meetings  in  a  folder  that is in a
       directory that changes every month.  E.g. if it were January 1994,  the
       folder  would have the name `94-01/meeting' and the locallockfile would
       be `94-01/meeting.lock'.

              * meeting
              `date +%y-%m`/meeting

       The same as above, but, if the `94-01' directory wouldn't have existed,
       it is created automatically:

              MONTHFOLDER=`date +%y-%m`

              :0 Wic
              * ? test ! -d $MONTHFOLDER
              | mkdir $MONTHFOLDER

              * meeting

       The same as above, but now by slightly different means:

              MONTHFOLDER=`date +%y-%m`
              DUMMY=`test -d $MONTHFOLDER || mkdir $MONTHFOLDER`

              * meeting

       If  you are subscribed to several mailinglists and people cross-post to
       some of them, you usually receive several  duplicate  mails  (one  from
       every  list).   The following simple recipe eliminates duplicate mails.
       It tells formail to keep an 8KB cache file in which it will  store  the
       Message-IDs  of  the most recent mails you received.  Since Message-IDs
       are guaranteed to be unique for every new mail, they are ideally suited
       to  weed  out  duplicate mails.  Simply put the following recipe at the
       top of your rcfile, and no duplicate mail will get past it.

              :0 Wh: msgid.lock
              | formail -D 8192 msgid.cache

       Beware if you have delivery problems in  recipes  below  this  one  and
       procmail  tries  to  requeue the mail, then on the next queue run, this
       mail will be considered a duplicate and will be thrown away.  For those
       not quite so confident in their own scripting capabilities, you can use
       the following recipe instead.  It puts duplicates in a separate  folder
       instead  of  throwing them away.  It is up to you to periodically empty
       the folder of course.

              :0 Whc: msgid.lock
              | formail -D 8192 msgid.cache

              :0 a:

       Procmail can deliver to MH folders directly, but, it  does  not  update
       the  unseen  sequences  the  real  MH manages.  If you want procmail to
       update those as well, use a recipe like the following which  will  file
       everything  that contains the word spam in the body of the mail into an
       MH folder called spamfold.  Note the local lockfile,  which  is  needed
       because  MH  programs  do  not  lock  the sequences file.  Asynchronous
       invocations of MH programs that change the sequences file may therefore
       corrupt  it  or  silently  lose  changes.   Unfortunately, the lockfile
       doesn't completely solve the problem as rcvstore could be invoked while
       `show'  or `mark' or some other MH program is running.  This problem is
       expected to be fixed in some future version  of  MH,  but  until  then,
       you'll  have  to  balance the risk of lost or corrupt sequences against
       the benefits of the unseen sequence.

              :0 :spamfold/$LOCKEXT
              * B ?? spam
              | rcvstore +spamfold

       When delivering to emacs folders  (i.e.,  mailfolders  managed  by  any
       emacs  mail package, e.g., RMAIL or VM) directly, you should use emacs-
       compatible lockfiles.  The emacs mailers are a bit braindamaged in that
       respect,  they  get very upset if someone delivers to mailfolders which
       they already have in their  internal  buffers.   The  following  recipe
       assumes that $HOME equals /home/john.


              * ^Subject:.*whatever

       Alternatively,  you  can  have  procmail  deliver  into  its own set of
       mailboxes, which you then periodically empty  and  copy  over  to  your
       emacs files using movemail.  Movemail uses mailbox.lock local lockfiles
       per mailbox.  This actually is  the  preferred  mode  of  operation  in
       conjunction with procmail.

       To  extract  certain  headers from a mail and put them into environment
       variables you can use any of the following constructs:

              SUBJECT=`formail -xSubject:`    # regular field
              FROM=`formail -rt -xTo:`        # special case

              :0 h                            # alternate method
              KEYWORDS=| formail -xKeywords:

       If you are using temporary files in a procmailrc file, and want to make
       sure  that  they  are removed just before procmail exits, you could use
       something along the lines of:

              TRAP="/bin/rm -f $TEMPORARY"

       The TRAP keyword can also be used to change the exitcode  of  procmail.
       I.e.  if  you want procmail to return an exitcode of `1' instead of its
       regular exitcodes, you could use:

              TRAP="exit 1;"   # The trailing semi-colon is important
                               # since exit is not a standalone program

       Or, if the exitcode does not need to depend on the  programs  run  from
       the TRAP, you can use a mere:


       The  following  recipe  prints  every  incoming  mail that looks like a
       postscript file.

              :0 Bb
              * ^^%!
              | lpr

       The following recipe does the same, but is a bit  more  selective.   It
       only prints the postscript file if it comes from the print-server.  The
       first condition matches only if it is found in the header.  The  second
       condition only matches at the start of the body.

              :0 b
              * ^From[ :].*print-server
              * B ?? ^^%!
              | lpr

       The same as above, but now by slightly different means:

              * ^From[ :].*print-server
                :0 B b
                * ^^%!
                | lpr


              :0 HB b
              * ^^(.+$)*From[ :].*print-server
              * ^^(.+$)*^%!
              | lpr

       Suppose  you  have  two  accounts, you use both accounts regularly, but
       they are in very distinct places (i.e., you can  only  read  mail  that
       arrived at either one of the accounts).  You would like to forward mail
       arriving at account one to account two, and the other way around.   The
       first  thing  that comes to mind is using .forward files at both sites;
       this won't work of course, since you will  be  creating  a  mail  loop.
       This  mail  loop  can  be  avoided by inserting the following recipe in
       front of all other recipes  in  the  $HOME/.procmailrc  files  on  both
       sites.   If  you  make sure that you add the same X-Loop: field at both
       sites, mail can now safely be  forwarded  to  the  other  account  from
       either of them.

              :0 c
              * !^X-Loop: yourname@your.main.mail.address
              | formail -A "X-Loop: yourname@your.main.mail.address" | \
                 $SENDMAIL -oi yourname@the.other.account

       If  someone  sends  you a mail with the word `retrieve' in the subject,
       the following will automatically send back the contents of info_file to
       the  sender.   Like in all recipes where we send mail, we watch out for
       mail loops.

              * !^From +YOUR_USERNAME
              * !^Subject:.*Re:
              * !^FROM_DAEMON
              * ^Subject:.*retrieve
              | (formail -r ; cat info_file) | $SENDMAIL -oi -t

       Now follows an example for a very simple fileserver accessible by mail.
       For more demanding applications, I suggest you take a look at SmartList
       (available from the same  place  as  the  procmail  distribution).   As
       listed,  this  fileserver  sends  back at most one file per request, it
       ignores the body of incoming mails, the Subject: line has to look  like
       "Subject: send file the_file_you_want" (the blanks are significant), it
       does not return files that have names starting with a dot, nor does  it
       allow  files  to be retrieved that are outside the fileserver directory
       tree (if you decide to  munge  this  example,  make  sure  you  do  not
       inadvertently loosen this last restriction).

              * ^Subject: send file [0-9a-z]
              * !^X-Loop: yourname@your.main.mail.address
              * !^Subject:.*Re:
              * !^FROM_DAEMON
              * !^Subject: send file .*[/.]\.
                MAILDIR=$HOME/fileserver # chdir to the fileserver directory

                :0 fhw                   # reverse mailheader and extract name
                * ^Subject: send file \/[^ ]*
                | formail -rA "X-Loop: yourname@your.main.mail.address"

                FILE="$MATCH"            # the requested filename

                :0 ah
                | cat - ./$FILE 2>&1 | $SENDMAIL -oi -t

       The  following  example  preconverts  all  plain-text  mail arriving in
       certain encoded MIME formats into a more compact 8-bit format which can
       be  used  and displayed more easily by most programs.  The mimencode(1)
       program is part of Nathaniel Borenstein's metamail package.

              * ^Content-Type: *text/plain
                :0 fbw
                * ^Content-Transfer-Encoding: *quoted-printable
                | mimencode -u -q

                   :0 Afhw
                   | formail -I "Content-Transfer-Encoding: 8bit"

                :0 fbw
                * ^Content-Transfer-Encoding: *base64
                | mimencode -u -b

                   :0 Afhw
                   | formail -I "Content-Transfer-Encoding: 8bit"

       The following one is rather exotic, but it only serves to demonstrate a
       feature.   Suppose  you  have  a  file  in  your  HOME directory called
       ".urgent", and the (one) person named in that file is the sender of  an
       incoming  mail,  you'd  like  that mail to be stored in $MAILDIR/urgent
       instead of in any of the normal mailfolders it would have  been  sorted
       in.   Then  this  is  what  you  could  do  (beware,  the filelength of
       $HOME/.urgent should  be  well  below  $LINEBUF,  increase  LINEBUF  if

              URGMATCH=`cat $HOME/.urgent`

              * $^From.*${URGMATCH}

       An   entirely   different   application   for   procmail  would  be  to
       conditionally apply filters to a certain (outgoing) text  or  mail.   A
       typical  example  would be a filter through which you pipe all outgoing
       mail, in order to make sure that it will be MIME  encoded  only  if  it
       needs  to be.  I.e. in this case you could start procmail in the middle
       of a pipe like:

              cat newtext | procmail ./mimeconvert | mail chris@where.ever

       The mimeconvert rcfile could contain something  like  (the  =0x80=  and
       =0xff= should be substituted with the real 8-bit characters):

              DEFAULT=|     # pipe to stdout instead of
                            # delivering mail as usual
              :0 Bfbw
              * [=0x80=-=0xff=]
              | mimencode -q

                :0 Afhw
                | formail -I 'MIME-Version: 1.0' \
                   -I 'Content-Type: text/plain; charset=ISO-8859-1' \
                   -I 'Content-Transfer-Encoding: quoted-printable'


       procmail(1), procmailrc(5), procmailsc(5), sh(1), csh(1), mail(1),
       mailx(1), uucp(1), aliases(5), sendmail(8), egrep(1), grep(1), biff(1),
       comsat(8), mimencode(1), lockfile(1), formail(1)


       Stephen R. van den Berg
       Philip A. Guenther