Subject: Standard "libraries" (both query & code)

From: "Alan K. Stebbens <[email-masked]>" <[email-masked]>
Date: Wed, 19 Oct 1994 21:58:36 -0700

Are there any standard libraries for procmail?  In either case, I've got
a few to contribute, and would appreciate improvements.

I created a directory, /local/procmail/lib, in which I've placed some
procmailrcs which can be included by many users, so they don't have to
reinvent the wheel.

One is called "headers.rc", which defines variables matching standard
mail headers.  I've found it useful, for example, to match addresses
only on a "To:" header (or one of its counterparts), but not "Cc:" (and
its alternates), unlike "^TO" which matches either the To: or Cc:
fields.

Then there is "dupcheck.rc" which does a duplicate mail check, throwing
away the duplicate.

The third is "ackmail.rc" which does an auto-acknolwedgement, if
appropriate.

Lastly, I've included how I use these.

headers.rc
============================= cut here ===================================
# procmail rc to define patterns to recognize the headers
#
# Use these is recipes like this:
#
#  # If mail is from john or mary, then file in "+urgent"
#  :0
#  * $ $FROM(john|mary)@
#  urgent/.
#
#  # if the mail is directly to me, then file it
#  :0
#  * $ $TO($USER)@
#  mymail/.
# 
# These patterns span any comment text before and after email addresses
# Use PRE_ADDR_SPAN before any names; it will span a string of non-address
# characters up to the beginning of a valid email address.
PRE_ADDR_SPAN='(.*[^(.%@a-zA-Z0-9])?'

# Use POST_ADDR_SPAN after any names; it will span a string of non-address
# characters up to the a comma "," or the end of the line
POST_ADDR_SPAN='(([^),.!:a-zA-Z0-9].*)?(,|$[^>]))'

# Use $FROM to match mail from someone
FROM="(^(((Resent-)?(From|Sender)|X-Envelope-From):|>?From )$PRE_ADDR_SPAN)"

# Use $TO to match mail to someone (but only "To:", not "Cc:")
TO="(^((Original-)?(Resent-)?To|(X-Envelope|Apparently(-Resent)?)-To):$PRE_ADDR_SPAN)"

# Use $CC to match mail to someone (but only "Cc:", not "To")
CC="(^((Original-)?(Resent-)?Cc|(X-Envelope|Apparently(-Resent)?)-Cc):$PRE_ADDR_SPAN)"

# For completeness, this should be roughly equivalent to ^TO
TOCC="($TO|$CC)"

# Pattern to recognize lists by precedence
LIST_PRECEDENCE='(^Precedence:.*(junk|bulk|list))'

# Names of common list mailers
LIST_MAILERS='((Mailer-)?daemon|root|LISTSERV|[a-zA-Z0-9-]+-(list|request|owner)|\
Majordomo|Mailagent|Postmaster|mmdf|news|n?uucp)'

# Pattern to put them all together
FROM_LIST="($LIST_PRECEDENCE|$FROM$LIST_MAILERS$POST_ADDR_SPAN)"

============================= cut here ===================================

dupcheck.rc -- check for duplicate mail
============================= cut here ===================================
# procmailrc to check for duplicates
# check for duplicate mail using the msgid

# Turn off comsat -- so it won't get called
# notifing the user about mail "delivered" via
# the formail check.

OLDCOMSAT=${COMSAT:-off}
COMSAT=off

# Remove duplicate messages
:0 Wh: .msgid.lock
| formail -D 8192 .msgid.cache

COMSAT=$OLDCOMSAT
OLDCOMSAT

============================= cut here ===================================

ackmail.rc -- acknowledge mail
============================= cut here ===================================
# autoack.rc -- procmail rc to autoacknowledge mail
#
# Setup the following variables:
#
# MY_ADDR	- preferred email address for the user
#
# MY_NAMES	- regex matcing personal names & alternatives;
#		  ultimately, only mail addressed to $MY_NAMES
#		  will be acknowledged; defaults to the
#		  contents of $SIGNATURE or $HOME/.signature, in
#		  that order.
#
# NOACKS	- regex matching people from whom to NOT 
#		  acknowledge mail; defaults to $MY_ADDR
#
# ACKS		- file containing the acknowledgement cache;
#		  defaults to $MAILDIR/.acks.cache
#
# ACKMSG	- file containing the message to reply with;
#		  defaults to $MAILDIR/ackmsg
#
# FROMSIG	- From: header to use in the auto-ack; defaults
#		  to "Mailer-Daemon of $USER"
#
# And be sure PATH includes the directory containing "formail".

# If the mail is directly to me, and not an auto-reply itself 
# then do the auto-ack 

MY_NAMES=${MY_NAMES:-${SIGNATURE:-`cat $HOME/.signature 2>/dev/null`}}
ACKS=${ACKS:-$MAILDIR/.acks.cache}
ACKMSG=${ACKMSG:-$MAILDIR/ackmsg}
FROMSIG=${FROMSIG:-"Mailer-Daemon of $USER"}
NOACKS=${NOACKS:-$MY_ADDR}

:0 ch
* !^FROM_DAEMON
* !^Subject: .*(\[ack(nowledgement)?\]|[Aa]uto(matic)[- ]?[Rr]eply|\
		[Vv]acation)
* !$^X-Loop: $MY_ADDR
* !$^(((Resent-)?(From|Sender)|X-Envelope-From):|>?From ).*($NOACKS)
* $^TO($MY_NAMES)
{
    # We're forking for the auto-ack, shut up comsat, and
    # assume that, in this process, the mail is delivered
    COMSAT=off
    DELIVERED=yes

    # Check the mail to see if we have replied recently, and
    # if so, if we should reply again
    DATE=`date +'%D'`
    FROM=`formail -rzx To:`
    SUBJ=`formail -zx Subject: | sed -e 's/^Re: *//g' -e 's/["~]/_/g'`

    # Check the cache for a recent ack
    :0:$ACKS.$LOCKEXT
    * !? fgrep -s "$FROM $DATE" $ACKS
    | ( fgrep -v "$FROM" $ACKS ; echo "$FROM $DATE" ) >$ACKS.new ; \
      rm -f $ACKS ; mv $ACKS.new $ACKS ; \
      ( formail -rI"From:       $FROMSIG" \
		 -I"Reply-To:   $MY_ADDR" \
		 -I"Precedence: junk" \
		 -I"Subject:    Re: $SUBJ [acknowledgement]" \
		 -I"X-Loop:     $MY_ADDR" \
		 -I"References:" ; \
	sed -e "s~\$SUBJECT~$SUBJ~" $ACKMSG ) \
      | $SENDMAIL -oi -t
}

============================= cut here ===================================
# procmailrc for AKS
#
# Basic philosophy:
#
#  1. Mail is assumed to be MH-based
#  2. Drop all daemon-based mail in +admin
#  3. If mail is from NOACKS list, drop in +inbox
#  4. If mail is to ME, and not an ack, and an ack hasn't
#     been sent recently, generate an auto-ack
#  5. Scan mail for junk & drop
#  6. Leave any remaining mail in +other
#  
SHELL=/bin/sh
PROCDIR=/eci/procmail
BIN=$PROCDIR/bin
LIB=$PROCDIR/lib

PATH=$PATH:$BIN
MAILDIR=$HOME/Mail
LOGFILE=$MAILDIR/Log

VERBOSE=off

# Do the duplicate mail check
INCLUDERC=$LIB/dupcheck.rc

# Pull in the standard header patterns
INCLUDERC=$LIB/headers.rc

# Mail folders to drop things into
DEFAULT=other/.
INBOX=inbox/.
ADMIN=admin/.

MY_ADDR=[email-masked]
MY_NAMES="(aks|alan|stebbens|a.stebbens|alan.stebbens)"
FROMSIG="Alan's Mailer-Daemon <$MY_ADDR>"

STAFF='(aks|toad|carl|em|mce|stu|stefan|theodora|bruno)'
REQUEST='((ccse|request|help|problem)(-(dist|staff))?)'
NOACKUSERS='(rog|tel|probert)'
NOACKS="($STAFF|$REQUEST|$NOACKUSERS)$POST_ADDR_SPAN"

# Define a patter matching local mail address (also matches user@host; ie:
# no domain)
FROM_LOCAL="$FROM.*\.ucsb\.edu"

# Send any root, postmaster, or daemon mail to +admin
:0:
* $ $TO(root|[PpHh]ostmaster|(mailer-)?daemon)(@|$)
$ADMIN

# If the mail is to me, do some special things
:0
* ^TOaks
{
    # Don't ack our staff or people who we don't want to send acks to
    :0:
    * $ $FROM$NOACKS
    $INBOX

    # Do any autoacknowledgements
    INCLUDERC=$LIB/ackmail.rc

    # If the mail is directly to me, -> +inbox
    :0:
    * $ $TO(aks)([,@]|$)
    $INBOX

    # If the mail is to an administrative alias, -> +admin
    :0:
    * $ ^TO($REQUEST|$STAFF)$POST_ADDR_SPAN
    $ADMIN

    # If the mail is from a ucsb host, -> +inbox
    :0: 
    * $ $FROM_LOCAL
    $INBOX

    # Otherwise drop it all in the default box
    :0:
    $OTHER
}

# It is not mail specifically to me; must be a candidate for
# junkmail filtering..

INCLUDERC=$HOME/.junkmailrc

# If mail is from some kind of daemon, drop it in the +admin folder
:0:
* ^FROM_MAILER
$ADMIN

# If the mail is to an administrative alias, -> +admin
:0:
* $ ^TO($REQUEST|$STAFF)$POST_ADDR_SPAN
$ADMIN

# If the mail is from a LOCAL host, put it into +inbox
:0:
* $ $FROM_LOCAL
$INBOX

# Drop any remaining into $DEFAULT

============================= cut here ===================================

+-------------------------+-----------------------------------------+
| Alan Stebbens           | University of California, Santa Barbara |
| Email: [email-masked] | Center for Computational Sciences 	    |
| CCSE:  (805) 893-3221	  |  & Engineering (CCSE)		    |
| Voice: (805) 893-8135   | 3107 Engineering I			    |
| Fax:   (805) 893-8121   | Santa Barbara, CA 93106		    |
+-------------------------+-----------------------------------------+