Subject: Re: Auto-Reply

From: Alan Stebbens <[email-masked]>
Date: Tue, 11 Apr 1995 15:12:50 -0700

> I'm trying to figure out what recipe will let me do auto-replies. Can 
> somebody please send me a simple one (with explanations, please...) that 
> I can modify. Thanks,

Well, this one may not be simple, but it works fine for me and others..

Alan

# ackmail.rc -- procmail rc to acknowledge mail (with either a 
#		vacation message, or an acknowledgement)
#
# Author: Alan Stebbens <[email-masked]>
#
# $Id: ackmail.rc,v 1.2 1995/02/10 04:16:13 aks Exp $
# $Source: /fs/eci1c/home/staff/aks/src/mail/procmail/lib/RCS/ackmail.rc,v $
#
# Usage:
#
#   After setting the variables below appropriately, add the following
#   to your .procmailrc:
#
#      INCLUDERC=ackmail.rc
#
# Features:
#
#  If the file $VACAMSG exists, it is assumed that the user is in
#  "vacation mode", and mail will be acknowledged with the contents of
#  the $VACAMSG file, with the subject line appended with "[on
#  vacation]".
#
#  If $VACAMSG doesn't exist, and $ACKMSG does, mail will be
#  acknowledged with the contents of $ACKMSG with the subject line
#  appended with "[acknowledgment]".
#
#  If neither the file $ACKMSG nor $VACAMSG exists, this recipe does
#  nothing.
#
#  Mail from any daemon or the usual set of mailing lists will not be
#  acknowledged (uses ^FROM_DAEMON).
#
#  Mail from any of a set of configured users ($NOACKS) will not be
#  acknowledged (be default, this includes the user).
#
#  Mail from any user will only be acknowledged once per day.
#
#  Regardless of whether or not "ackmail.rc" acknowledges the mail, any
#  recipes following the INCLUDERC will continue to filter the incoming
#  mail (that is, it is not considered to be delivered).
#
# Before including the "ackmail.rc" file, be sure to 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 acknowledgment cache;
#		  defaults to $MAILDIR/.acks.cache
#
# ACKMSG	- file containing the message to reply with;
#		  defaults to $MAILDIR/ackmsg
#
# VACAMSG	- file containing the message to reply with;
#		  defaults to $MAILDIR/vacation.msg
#
# FROMSIG	- From: header to use in the auto-ack; defaults
#		  to "Mailer-Daemon of $USER"
#
# And be sure PATH includes the directory containing "formail".

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

# Handy regexp patterns (taken from "headers.rc")
PRE_ADDR_SPAN='(.*[^-(.%@a-zA-Z0-9])?'
POST_ADDR_SPAN='(([^),.!:a-zA-Z0-9].*)?(,|$[^>]))'
FROM="(^(((Resent-)?(From|Sender)|X-Envelope-From):|>?From )$PRE_ADDR_SPAN)"

# Begin the tests
# 1. Is it addressed to me (using any of my names)?
# 2. Is there an acknowledgement file or vacation message file?
# 3. Is the mail NOT from any kind of daemon
# 4. Is the mail NOT from a mailing list manager which procmail doesn't know
# 5. Does the subject NOT have any text indicating some kind of automatic
#    reply mechanism has already taken place?
# 6. Is this NOT a message we generated (a bounce, maybe)?
# 7. Is the message NOT from anyone on our "noack" list?

:0ch
* $ ^TO($USER|$MY_ADDR|$MY_NAMES)
* ? test -f $ACKMSG -o -f $VACAMSG
* ! ^FROM_DAEMON
* !$ $FROM(Majordomo|Listserv)
* ! ^Subject: .*(\[(ack(nowledge?ment)?|on vacation)\]|\
		auto(matic)[- ]reply|\
		away from mail|\
		out of town|\
		can ?not (reply|answer)|\
		(on |via )vacation( program)?)
* !$ ^X-Loop: $MY_ADDR
* !$ $FROM($NOACKS)$POST_ADDR_SPAN
{
    # Okay -- we're donig to do the auto-ack or vacation mail
    #
    # We're forking for the auto-ack, shut up comsat, and assume that,
    # in this process, the mail is delivered
    COMSAT=off
    DELIVERED=yes

    # Don't output logfile info; the user can query $ACKS to see which
    # users have been acknowledged.  This only affects the child
    # process.
    LOGABSTRACT=no

    # Check the mail to see if we have replied recently, and if so, if
    # we should reply again
    DATE=`date +'%D'`

    # Get the from address by having formail generate a reply address
    FROMADDR=`formail -rzx To:`

    # Get the subject sans "Re:" and replacing double-quotes
    SUBJ=`formail -zx Subject: | sed -e 's/^Re: *//g' -e 's/["~]/_/g'`

    # Get which file: "vacation.msg" has precedence over "ackmsg"
    ACKFILE=`if [ -f $VACAMSG ]; then echo $VACAMSG ; else echo $ACKMSG ; fi`

    # Get either the string "on vacation" or "acknowledgement" 
    ACKM="`if [ -f $VACAMSG ]; then echo 'on vacation' ; else echo acknowledgment ; fi`"

    # Check the cache for a recent ack
    :0:$ACKS.$LOCKEXT
    * !? fgrep -s "$FROMADDR $DATE" $ACKS
    | ( fgrep -v "$FROMADDR" $ACKS ; echo "$FROMADDR $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 [$ACKM]" \
		 -I"X-Loop:     $MY_ADDR" \
		 -I"References:" ; \
	sed -e "s~\$SUBJECT~$SUBJ~" $ACKFILE ) \
      | $SENDMAIL -oi -t
}