Switch to SpeakEasy.net DSL

The Modular Manual Browser

Home Page
Manual: (OSF1-V5.1-alpha)
Apropos / Subsearch:
optional field


  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   part    of    the	   procmail    source	 distribution

  Sort out all mail coming from	the scuba-dive mailing list  into  the	mail-
  folder 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
	  ! williamATsomewhere.edu


  An equivalent	solution that accomplishes the same:

       :0 c
       * ^From.*peter
       * ^Subject:.*compilers
       ! williamATsomewhere.edu

	  :0 A

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

       :0 c
       * ^From.*peter
       * ^Subject:.*compilers
       ! williamATsomewhere.edu

       * ^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	subsequently.

       :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'; other-
  wise the lockfile would be removed as	soon as	the  pipe  has	accepted  the

       :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  indivi-
  dual	messages,  and	store  them  into  surfing, using surfing.lock as the

       * ^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 locallockfile.

       * ^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	 gen-
  erally 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: yourATown.address
       | (formail -r -I"Precedence: junk" \
	   -A"X-Loop: yourATown.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 aproximately	8192 bytes).  If the name was new, an autore-
  ply will be sent.

  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

       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: yourATown.address
       | formail -rD 8192 vacation.cache

	 :0 ehc		# if the name was not in the cache
	 | (formail -rI"Precedence: junk" \
	      -A"X-Loop: yourATown.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

       * (^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 direc-
  tory folder.	It is actually only one	file with two extra hardlinks.

       * (^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-

       * 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  throw-
  ing 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	 pro-
  gram	is running.  This problem is expected to be fixed in some future ver-
  sion of MH, but until	then, you'll have to balance the risk of lost or cor-
  rupt 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


       * ^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	vari-
  ables	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	some-
  thing	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: yournameATyour.address
       | formail -A "X-Loop: yournameATyour.address" |	\
	  $SENDMAIL -oi	yournameATthe.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

       * !^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

       * ^Subject: send	file [0-9a-z]
       * !^X-Loop: yournameATyour.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:	yournameATyour.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	necessary):

       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 chrisATwhere.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), binmail(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