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


Personal Opportunity - Free software gives you access to billions of dollars of software at no cost. Use this software for your business, personal use or to develop a profitable skill. Access to source code provides access to a level of capabilities/information that companies protect though copyrights. Open source is a core component of the Internet and it is available to you. Leverage the billions of dollars in resources and capabilities to build a career, establish a business or change the world. The potential is endless for those who understand the opportunity.

Business Opportunity - Goldman Sachs, IBM and countless large corporations are leveraging open source to reduce costs, develop products and increase their bottom lines. Learn what these companies know about open source and how open source can give you the advantage.

Free Software

Free Software provides computer programs and capabilities at no cost but more importantly, it provides the freedom to run, edit, contribute to, and share the software. The importance of free software is a matter of access, not price. Software at no cost is a benefit but ownership rights to the software and source code is far more significant.

Free Office Software - The Libre Office suite provides top desktop productivity tools for free. This includes, a word processor, spreadsheet, presentation engine, drawing and flowcharting, database and math applications. Libre Office is available for Linux or Windows.

Free Books

The Free Books Library is a collection of thousands of the most popular public domain books in an online readable format. The collection includes great classical literature and more recent works where the U.S. copyright has expired. These books are yours to read and use without restrictions.

Source Code - Want to change a program or know how it works? Open Source provides the source code for its programs so that anyone can use, modify or learn how to write those programs themselves. Visit the GNU source code repositories to download the source.


Study at Harvard, Stanford or MIT - Open edX provides free online courses from Harvard, MIT, Columbia, UC Berkeley and other top Universities. Hundreds of courses for almost all major subjects and course levels. Open edx also offers some paid courses and selected certifications.

Linux Manual Pages - A man or manual page is a form of software documentation found on Linux/Unix operating systems. Topics covered include computer programs (including library and system calls), formal standards and conventions, and even abstract concepts.