1Please read the README file in this directory first. 2.ex 3.Id $Id: procmailex.man,v 1.54 2001/08/04 06:08:20 guenther Exp $ 4.TH PROCMAILEX 5 \*(Dt BuGless 5.na 6.SH NAME 7procmailex \- procmail rcfile examples 8.SH SYNOPSIS 9.B @PROCMAILRC@ examples 10.ad 11.SH DESCRIPTION 12For a description of the rcfile format see 13.BR procmailrc (5). 14.PP 15The weighted scoring technique is described in detail in the 16.BR procmailsc (5) 17man page. 18.PP 19This man page shows several example recipes. For examples of complete rcfiles 20you can check the NOTES section in 21.BR procmail (1), 22or look at the example rcfiles part of the procmail source distribution 23(procmail*/examples/?procmailrc). 24.SH EXAMPLES 25Sort out all mail coming from the scuba-dive mailing list into the mailfolder 26scubafile (uses the locallockfile scubafile.lock). 27.Sx 3 28:0: 29* ^TOscuba 30scubafile 31.Ex 32Forward all mail from peter about compilers to william (and keep a copy 33of it here in petcompil). 34.Sx 10 35:0 36* ^From.*peter 37* ^Subject:.*compilers 38{ 39 :0 @CONTINUE@ 40 ! william@somewhere.edu 41 42 :0 43 petcompil 44} 45.Ex 46An equivalent solution that accomplishes the same: 47.Sx 7 48:0 @CONTINUE@ 49* ^From.*peter 50* ^Subject:.*compilers 51! william@somewhere.edu 52 53 :0 @ALSO_NEXT_RECIPE@ 54 petcompil 55.Ex 56An equivalent, but slightly slower solution that accomplishes the same: 57.Sx 9 58:0 @CONTINUE@ 59* ^From.*peter 60* ^Subject:.*compilers 61! william@somewhere.edu 62 63:0 64* ^From.*peter 65* ^Subject:.*compilers 66petcompil 67.Ex 68If you are fairly new to procmail and plan to experiment a little bit 69it often helps to have a 70.I safety net 71of some sort. Inserting the following two recipes above all other recipes 72will make sure that of all arriving mail always the last 32 messages will 73be preserved. In order for it to work as intended, you have to create 74a directory named `backup' in $MAILDIR prior to inserting these two recipes. 75.Sx 5 76:0 @CONTINUE@ 77backup 78 79:0 @IGNORE_WRITERR@@CONTINUE@ 80| cd backup && rm \-f dummy `ls \-t msg.* | sed \-e 1,32d` 81.Ex 82If your system doesn't generate or generates incorrect leading `@FROM@' 83lines on every mail, you can fix this by calling up procmail with 84the \-@FROMWHOPT@@REFRESH_TIME@ option. To fix the same problem by 85different means, you could have inserted the following two 86recipes above all other recipes in your rcfile. They will filter the header 87of any mail through formail which will strip any leading `@FROM@', and 88automatically regenerates it subsequently. 89.Sx 2 90:0 @FILTER@@PASS_HEAD@@WAIT_EXIT@ 91| formail \-@FM_DEL_INSERT@ "@FROM@" \-@FM_ADD_IFNOT@ "@FROM@" 92.Ex 93Add the headers of all messages that didn't come from the postmaster 94to your private header collection (for 95statistics or mail debugging); and use the lockfile `headc.lock'. In order 96to make sure the lockfile is not removed until the pipe has finished, 97you have to specify option `@WAIT_EXIT@'; otherwise the lockfile would be 98removed as soon as the pipe has accepted the mail. 99.Sx 3 100:0 @PASS_HEAD@@WAIT_EXIT@@CONTINUE@: 101* !@FROMMkey@ 102| uncompress headc.Z; cat >>headc; compress headc 103.Ex 104Or, if you would use the more efficient gzip instead of compress: 105.Sx 3 106:0 @PASS_HEAD@@WAIT_EXIT@@CONTINUE@: 107* !@FROMMkey@ 108| gzip >>headc.gz 109.Ex 110Forward all mails shorter than 1000 bytes to my home address (no lockfile 111needed on this recipe). 112.Sx 3 113:0 114* < 1000 115! myname@home 116.Ex 117Split up incoming digests from the surfing mailing list into their individual 118messages, and store them into surfing, using surfing.lock as the locallockfile. 119.Sx 3 120:0: 121* ^Subject:.*surfing.*Digest 122| formail @FM_SKIP@1 \-@FM_DIGEST@@FM_SPLIT@ >>surfing 123.Ex 124Store everything coming from the postmaster or mailer-daemon (like bounced 125mail) into the file postm, using postm.lock as the locallockfile. 126.Sx 3 127:0: 128* @FROMMkey@ 129postm 130.Ex 131A simple autoreply recipe. It makes sure that neither mail from any daemon 132(like bouncing mail or mail from mailing-lists), nor autoreplies coming from 133yourself will be autoreplied to. If this precaution would not be taken, 134disaster could result (`ringing' mail). In order for this recipe to autoreply 135to all the incoming mail, you should of course insert it before all other 136recipes in your rcfile. However, it is advisable to put it 137.I after 138any recipes that process the mails from subscribed mailinglists; it generally 139is not a good idea to generate autoreplies to mailinglists (yes, the 140!@FROMDkey@ regexp should already catch those, but if the mailinglist 141doesn't follow accepted conventions, this might 142.I not 143be 144.IR enough ). 145.Sx 6 146:0 @PASS_HEAD@ @CONTINUE@ 147* !@FROMDkey@ 148* !^X-Loop: your@own.mail.address 149| (formail \-@FM_REPLY@ \-@FM_DEL_INSERT@"Precedence: junk" \e 150 \-@FM_ADD_ALWAYS@"X-Loop: your@own.mail.address" ; \e 151 echo "Mail received.") | $SENDMAIL \-t 152.Ex 153A more complicated autoreply recipe that implements the functional equivalent 154of the well known 155.BR vacation (1) 156program. This recipe is based on the same principles as the last one (prevent 157`ringing' mail). In addition to that however, it maintains a vacation database 158by extracting the name of the sender and inserting it in the vacation.cache 159file if the name was new (the vacation.cache file is maintained by formail 160which will make sure that it always contains the most recent names, the size 161of the file is limited to a maximum of approximately 8192 bytes). If the name 162was new, an autoreply will be sent. 163.PP 164As you can see, the following recipe has comments 165.B between 166the conditions. 167This is allowed. Do 168.B not 169put comments on the same line as a condition though. 170.Sx 18 171SHELL=/bin/sh # for other shells, this might need adjustment 172 173:0 @WAIT_EXIT_QUIET@@PASS_HEAD@@CONTINUE@: vacation.lock 174 # Perform a quick check to see if the mail was addressed to us 175* $^To:.*\e<$\eLOGNAME\e> 176 # Don't reply to daemons and mailinglists 177* !@FROMDkey@ 178 # Mail loops are evil 179* !^X-Loop: your@own.mail.address 180| formail \-@FM_REPLY@@FM_DUPLICATE@ 8192 vacation.cache 181 182 :0 @ERROR_DO@@PASS_HEAD@@CONTINUE@ # if the name was not in the cache 183 | (formail \-@FM_REPLY@@FM_DEL_INSERT@"Precedence: junk" \e 184 \-@FM_ADD_ALWAYS@"X-Loop: your@own.mail.address" ; \e 185 echo "I received your mail,"; \e 186 echo "but I won't be back until Monday."; \e 187 echo "-- "; cat $HOME/.signature \e 188 ) | $SENDMAIL \-oi \-t 189.Ex 190Store all messages concerning TeX in separate, unique filenames, in a directory 191named texmail (this directory has to exist); there is no need to use lockfiles 192in this case, so we won't. 193.Sx 3 194:0 195* (^TO|^Subject:.*)TeX[^t] 196texmail 197.Ex 198The same as above, except now we store the mails in numbered files (MH mail 199folder). 200.Sx 3 201:0 202* (^TO|^Subject:.*)TeX[^t] 203texmail/. 204.Ex 205Or you could file the mail in several directory folders at the same time. 206The following recipe will deliver the mail to two MH-folders and one 207directory folder. It is actually only one file with two extra hardlinks. 208.Sx 3 209:0 210* (^TO|^Subject:.*)TeX[^t] 211texmail/. wordprocessing dtp/. 212.Ex 213Store all the messages about meetings in a folder that is in a directory 214that changes every month. E.g. if it were January 1994, the folder 215would have the name `94-01/meeting' and the locallockfile would be 216`94-01/meeting.lock'. 217.Sx 3 218:0: 219* meeting 220`date +%y-%m`/meeting 221.Ex 222The same as above, but, if the `94-01' directory wouldn't have existed, it 223is created automatically: 224.Sx 9 225MONTHFOLDER=`date +%y-%m` 226 227:0 @WAIT_EXIT_QUIET@@IGNORE_WRITERR@@CONTINUE@ 228* ? test ! \-d $MONTHFOLDER 229| mkdir $MONTHFOLDER 230 231:0: 232* meeting 233${MONTHFOLDER}/meeting 234.Ex 235The same as above, but now by slightly different means: 236.Sx 6 237MONTHFOLDER=`date +%y-%m` 238DUMMY=`test \-d $MONTHFOLDER || mkdir $MONTHFOLDER` 239 240:0: 241* meeting 242${MONTHFOLDER}/meeting 243.Ex 244If you are subscribed to several mailinglists and people cross-post to 245some of them, you usually receive several duplicate mails (one from every 246list). The following simple recipe eliminates duplicate mails. It tells 247formail to keep an 8KB cache file in which it will store the Message-IDs of 248the most recent mails you received. Since Message-IDs are guaranteed to 249be unique for every new mail, they are ideally suited to weed out duplicate 250mails. Simply put the following recipe at the top of your rcfile, and 251no duplicate mail will get past it. 252.Sx 2 253:0 @WAIT_EXIT_QUIET@@PASS_HEAD@: msgid.lock 254| formail \-@FM_DUPLICATE@ 8192 msgid.cache 255.Ex 256.B Beware 257if you have delivery problems in recipes below this one and procmail tries 258to requeue the mail, then on the next queue run, this mail will be considered 259a duplicate and will be thrown away. For those not quite so confident in 260their own scripting capabilities, you can use the following recipe instead. 261It puts duplicates in a separate folder instead of throwing them away. 262It is up to you to periodically empty the folder of course. 263.Sx 5 264:0 @WAIT_EXIT_QUIET@@PASS_HEAD@@CONTINUE@: msgid.lock 265| formail \-@FM_DUPLICATE@ 8192 msgid.cache 266 267:0 @ALSO_N_IF_SUCC@: 268duplicates 269.Ex 270Procmail can deliver to MH folders directly, but, it does not update 271the unseen sequences the real MH manages. If you want procmail to 272update those as well, use a recipe like the following which will file 273everything that contains the word spam in the body of the mail into an 274MH folder called spamfold. Note the local lockfile, which is needed 275because MH programs do not lock the sequences file. Asynchronous 276invocations of MH programs that change the sequences file may therefore 277corrupt it or silently lose changes. Unfortunately, the lockfile 278doesn't completely solve the problem as rcvstore could be invoked while 279`show' or `mark' or some other MH program is running. This problem is 280expected to be fixed in some future version of MH, but until then, 281you'll have to balance the risk of lost or corrupt sequences against 282the benefits of the unseen sequence. 283.Sx 3 284:0 :spamfold/$LOCKEXT 285* @BODY_GREP@ ?? spam 286| rcvstore +spamfold 287.Ex 288When delivering to emacs folders (i.e., mailfolders managed by any emacs 289mail package, e.g., RMAIL or VM) directly, you should use emacs-compatible 290lockfiles. The emacs mailers are a bit braindamaged in that respect, they get 291very upset if someone delivers to mailfolders which they already have in their 292internal buffers. The following recipe assumes that $HOME equals /home/john. 293.Sx 5 294MAILDIR=Mail 295 296:0:/usr/local/lib/emacs/lock/!home!john!Mail!mailbox 297* ^Subject:.*whatever 298mailbox 299.Ex 300Alternatively, you can have procmail deliver into its own set of mailboxes, 301which you then periodically empty and copy over to your emacs files using 302.BR movemail . 303Movemail uses mailbox.lock local lockfiles per mailbox. This actually is 304the preferred mode of operation in conjunction with procmail. 305.PP 306To extract certain headers from a mail and put them into environment 307variables you can use any of the following constructs: 308.Sx 5 309SUBJECT=`formail \-@FM_EXTRACT@Subject:` # regular field 310FROM=`formail \-@FM_REPLY@@FM_TRUST@ \-@FM_EXTRACT@To:` # special case 311 312:0 @PASS_HEAD@ # alternate method 313KEYWORDS=| formail \-@FM_EXTRACT@Keywords: 314.Ex 315If you are using temporary files in a procmailrc file, and want to make 316sure that they are removed just before procmail exits, you could use 317something along the lines of: 318.Sx 2 319TEMPORARY=$HOME/tmp/pmail.$$ 320TRAP="/bin/rm \-f $TEMPORARY" 321.Ex 322The TRAP keyword can also be used to change the exitcode of procmail. 323I.e. if you want procmail to return an exitcode of `1' instead of its 324regular exitcodes, you could use: 325.Sx 3 326EXITCODE="" 327TRAP="exit 1;" # The trailing semi-colon is important 328 # since exit is not a standalone program 329.Ex 330Or, if the exitcode does not need to depend on the programs run from 331the TRAP, you can use a mere: 332.Sx 1 333EXITCODE=1 334.Ex 335The following recipe prints every incoming mail that looks like a postscript 336file. 337.Sx 3 338:0 @BODY_GREP@@PASS_BODY@ 339* ^^%! 340| lpr 341.Ex 342The following recipe does the same, but is a bit more selective. It only 343prints the postscript file if it comes from the print-server. The first 344condition matches only if it is found in the header. The second condition 345only matches at the start of the body. 346.Sx 4 347:0 @PASS_BODY@ 348* ^From[ :].*print-server 349* B ?? ^^%! 350| lpr 351.Ex 352The same as above, but now by slightly different means: 353.Sx 7 354:0 355* ^From[ :].*print-server 356{ 357 :0 @BODY_GREP@ @PASS_BODY@ 358 * ^^%! 359 | lpr 360} 361.Ex 362Likewise: 363.Sx 4 364:0 @HEAD_GREP@@BODY_GREP@ @PASS_BODY@ 365* ^^(.+$)*From[ :].*print-server 366* ^^(.+$)*^%! 367| lpr 368.Ex 369Suppose you have two accounts, you use both accounts regularly, but they are 370in very distinct places (i.e., you can only read mail that arrived at either one 371of the accounts). You would like to forward mail arriving at account one to 372account two, and the other way around. The first thing that comes to mind is 373using .forward files at both sites; this won't work of course, since you will 374be creating a mail loop. This mail loop can be avoided by inserting the 375following recipe in front of all other recipes in the @PROCMAILRC@ files on 376both sites. If you make sure that you add the same X-Loop: field at both 377sites, mail can now safely be forwarded to the other account from either of 378them. 379.Sx 4 380:0 @CONTINUE@ 381* !^X-Loop: yourname@your.main.mail.address 382| formail \-@FM_ADD_ALWAYS@ "X-Loop: yourname@your.main.mail.address" | \e 383 $SENDMAIL \-oi yourname@the.other.account 384.Ex 385If someone sends you a mail with the word `retrieve' in the subject, the 386following will automatically send back the contents of info_file to the 387sender. Like in all recipes where we send mail, we watch out for mail 388loops. 389.Sx 6 390:0 391* !^@FROM@+YOUR_USERNAME 392* !^Subject:.*Re: 393* !@FROMDkey@ 394* ^Subject:.*retrieve 395| (formail \-@FM_REPLY@ ; cat info_file) | $SENDMAIL \-oi \-t 396.Ex 397Now follows an example for a very simple fileserver accessible by mail. 398For more demanding applications, I suggest you take a look at 399.B SmartList 400(available from the same place as the procmail distribution). 401As listed, this fileserver sends back at most one file per request, it 402ignores the body of incoming mails, the Subject: line has to look 403like "Subject: send file the_file_you_want" (the blanks are significant), 404it does not return files that have names starting with a dot, nor does 405it allow files to be retrieved that are outside the fileserver directory 406tree (if you decide to munge this example, make sure you do not inadvertently 407loosen this last restriction). 408.Sx 18 409:0 410* ^Subject: send file [0-9a-z] 411* !^X-Loop: yourname@your.main.mail.address 412* !^Subject:.*Re: 413* !@FROMDkey@ 414* !^Subject: send file .*[/.]\e. 415{ 416 MAILDIR=$HOME/fileserver # chdir to the fileserver directory 417 418 :0 fhw # reverse mailheader and extract name 419 * ^Subject: send file \e/[^ ]* 420 | formail \-@FM_REPLY@@FM_ADD_ALWAYS@ "X-Loop: yourname@your.main.mail.address" 421 422 FILE="$MATCH" # the requested filename 423 424 :0 ah 425 | cat \- ./$FILE 2>&1 | $SENDMAIL \-oi \-t 426} 427.Ex 428The following example preconverts all plain-text mail arriving in certain 429encoded MIME formats into a more compact 8-bit format which can be used 430and displayed more easily by most programs. The 431.BR mimencode (1) 432program is part of Nathaniel Borenstein's metamail package. 433.Sx 17 434:0 435* ^Content-Type: *text/plain 436{ 437 :0 @FILTER@@PASS_BODY@@WAIT_EXIT@ 438 * ^Content-Transfer-Encoding: *quoted-printable 439 | mimencode \-u \-q 440 441 :0 @ALSO_NEXT_RECIPE@@FILTER@@PASS_HEAD@@WAIT_EXIT@ 442 | formail \-@FM_DEL_INSERT@ "Content-Transfer-Encoding: 8bit" 443 444 :0 @FILTER@@PASS_BODY@@WAIT_EXIT@ 445 * ^Content-Transfer-Encoding: *base64 446 | mimencode \-u \-b 447 448 :0 @ALSO_NEXT_RECIPE@@FILTER@@PASS_HEAD@@WAIT_EXIT@ 449 | formail \-@FM_DEL_INSERT@ "Content-Transfer-Encoding: 8bit" 450} 451.Ex 452The following one is rather exotic, but it only serves to demonstrate a 453feature. Suppose you have a file in your HOME directory called ".urgent", 454and the (one) person named in that file is the sender of an incoming mail, 455you'd like that mail to be stored in $MAILDIR/urgent instead of in any of the 456normal mailfolders it would have been sorted in. Then this is what you could 457do (beware, the filelength of $HOME/.urgent should be well below $LINEBUF, 458increase LINEBUF if necessary): 459.Sx 5 460URGMATCH=`cat $HOME/.urgent` 461 462:0: 463* $^From.*${URGMATCH} 464urgent 465.Ex 466An entirely different application for procmail would be to conditionally 467apply filters to a certain (outgoing) text or mail. A typical example 468would be a filter through which you pipe all outgoing mail, in order 469to make sure that it will be MIME encoded only if it needs to be. 470I.e. in this case you could start procmail in the middle of a pipe like: 471.Sx 1 472cat newtext | procmail ./mimeconvert | mail chris@where.ever 473.Ex 474The 475.B mimeconvert 476rcfile could contain something like (the =0x80= and =0xff= should 477be substituted with the real 8-bit characters): 478.Sx 10 479DEFAULT=| # pipe to stdout instead of 480 # delivering mail as usual 481:0 @BODY_GREP@@FILTER@@PASS_BODY@@WAIT_EXIT@ 482* [=0x80=-=0xff=] 483| mimencode \-q 484 485 :0 @ALSO_NEXT_RECIPE@@FILTER@@PASS_HEAD@@WAIT_EXIT@ 486 | formail \-I 'MIME-Version: 1.0' \e 487 \-I 'Content-Type: text/plain; charset=ISO-8859-1' \e 488 \-I 'Content-Transfer-Encoding: quoted-printable' 489.Ex 490.SH "SEE ALSO" 491.na 492.nh 493.BR procmail (1), 494.BR procmailrc (5), 495.BR procmailsc (5), 496.BR sh (1), 497.BR csh (1), 498.BR mail (1), 499.BR mailx (1), 500.BR binmail (1), 501.BR uucp (1), 502.BR aliases (5), 503.BR sendmail (8), 504.BR egrep (1), 505.BR grep (1), 506.BR biff (1), 507.BR comsat (8), 508.BR mimencode (1), 509.BR lockfile (1), 510.BR formail (1) 511.hy 512.ad 513