# @(#) pm-jadaemon.rc -- Handle DAEMON messages by changing subject
# @(#) $Id: pm-jadaemon.rc,v 2.0 2001/07/27 22:45:50 jaalto Exp $
#
#   File id
#
#	.Copyright (C)	1997-2001 Jari Aalto
#	.$Created:	1997-11 $
#	.$Contactid:	<jari.aalto@poboxes.com> $
#	.$Keywords:	procmail, daemon, subroutine $
#
#       This code is free software in terms of GNU Gen. pub. Lic. v2 or later
#	Refer to http://www.gnu.org/copyleft/gpl.html
#
#   Description
#
#       When you send a message to a address that had delivery troubles,
#       you get a DAEMON message back explaining the error problem. I
#       usually want to save these daemon mesaages to a different folder
#       and check the folder from time to time. A typical daemon message
#       is like this (shortened)
#
#           From: Mail Delivery Subsystem <MAILER-DAEMON@my.domain.com>
#           Subject: Warning: could not send message for past 4 hours
#
#           The original message was received at...
#           ----- Transcript of session follows -----
#           Deferred: Connection timed out
#           ----- Original message follows -----
#           [YOUR MESSAGE AS YOU SENT IT WITH HEADERS]
#
#       Well, when I read the subjects, I do not like the standard error
#       messages, but I also like to know to which address the delivery
#       failed and what was the original subject. This small recipe changes
#       the daemon message's Subject to
#
#           Subject BRIEF-ERROR-REASON, SENT-TO-ADDRESS, ORIGINAL-SUBJECT
#
#       and from that you can immediately tell if you should be worried Eg.
#       if SENT-TO-ADDRESS was your friend's, then you want to take actions
#       immediately, but if it were your complaint to UBE message to
#       postmaster, you don't want to bother reading that daemon message.
#       Here are some real examples:
#
#           fatal errors,postmaster,ABUSE (Was: Super Cool Site!)
#           Host unknown,postmaster,ABUSE (Was: A-Credit Information)
#           undeliverable,postmaster,Could you investigate this spam
#           Warning-Returned,friend,Have you looked at this
#
#   Required settings
#
#	PMSRC must point to source direcry of procmail code. This subroutine
#       needs scrips
#
#       o   pm-javar.rc
#
#   Call arguments (variables to set before calling)
#
#       o   JA_DAEMON_REGEXP,   which messages to trigger
#
#   Return values
#
#       o   Variable ERROR will be set to "yes" if daemon message was handled
#           otherwise; value is "no"
#
#   Usage example
#
#	Just add this recipe somewhere in your .procmailrc. The place where
#       you would put this daemon message trapper subroutine is crucial:
#       think carefylly how you order your recipes. One suggested order
#       could be: backup important messages, cron-subroutine,
#       handle duplicates, DAEMON MESSAGES, plus addressed message,
#       server message (file server, ping responder...), MAILING LISTS,
#       send possible vacation  replies only after all above, apply
#       kill file, detect mime, save private messages and las FILTER UBE.
#
#
#	    PMSRC           = $HOME/pm
#	    RC_DAEMON       = $PMSRC/pm-jadaemon.rc
#	    DAEMON_MBOX     = $HOME/Mail/junk.daemon.mbox
#
#           ...
#
#           INCLUDERC       = $RC_DAEMON
#
#           :0 :            # If that was a daemon message, put it to folder
#           * ERROR ?? yes
#           $DAEMON_MBOX
#
#   Change Log: (none)

# .................................................... &initialising ...


id    = "pm-jadaemon.rc"
dummy = "
========================================================================
$id: init:
"

:0
* !  WSPC ?? ( )
{
    INCLUDERC = $PMSRC/pm-javar.rc
}

# ........................................................... &input ...

JA_DAEMON_REGEXP = ${JA_DAEMON_REGEXP:-"\
From.*(MAILER-DAEMON|abuse@|postmaster@|daemon@)"}

# ..................................................... &output-vars ...
# output variables

ERROR = "no"

# ........................................................... &do-it ...

dummy   = "$NL$id: start: Daemon message trigger $NL"

errTo   = ""
charset = "[^ @(){}<>]"

#   If you wonder why ()\/ is used: It is only for logging purposes
#   so that you can look from log file what the regexp matched.

:0
*$ ()\/$JA_DAEMON_REGEXP.*
{

    errText     # Kill variable

    # Read the reason from MAIL DAEMON (subject field)

    :0 B
    * THIS IS A WARNING MESSAGE
    {
        errText = "Warn-Returned,"

	#   ----- The following addresses had transient non-fatal errors -----
	#   <foo@d255f016.mch.sni.de>

	:0 B
	* The following addresses.*($)\/.*@
	{
	    match = $MATCH
	}
    }

    # ......................................... sendmail-error-codes ...

    :0 E B
    * ()\/550.*User unknown
    {
	errText = "Err-Unknown,"
	match   = $MATCH
    }


    :0 E B
    *  ()\/554.*Mail loop detected
    {
	errText = "Err-Loop,"
	match   = $MATCH
    }

    #   TO: foo@bar [552 Requested mail
    #   operation aborted: Cannot be routed.]

    :0 E B
    *  ()\/.*552 .*mail operation.*
    {
	errText = "Err-Unknown,"
	match   = $MATCH
    }


    :0 E B
    * following addresses have delivery notifications
    {
	errText = "Warn-Delivery,"
    }

    :0 E B
    * ()\/(not.*delivered.*($).*after.*hours\
          |still undelivered after.*(hours|days)\
          ).*
    {
        errText = "Warn-Returned,"
    }

    # ...................................................... unknown ...


    :0 E
    *$ $SUPREME^0 H ?? ^Subject:.*(could not send|returned)
    *$ $SUPREME^0 B ?? ()\/(message.*undeliverable\
                    |could not be delivered\
                    |no longer a valid address\
                    |addresses had permanent fatal errors\
                    | User unknown\
                    ).*
    {
        #   The message that you sent was undeliverable to the following:
        #	    postmaster (user not found)

        # This e-mail address, `abc', is no longer a valid address.  You can
        # reach Mr Foo at his new email address:
        #
        #   foo@bar.com
        #
        #   <ORIGINAL MESSAGE FOLLOWS>

        #   Subject:  Returned mail: Cannot send message
        #   The following addresses had permanent fatal errors

	errText = "err-Unknown,"
    }

    # ........................................................ other ...

    :0 E
    * ^Subject:.*\/Host unknown
    {
	errText = "$MATCH,"

	:0
	* B ?? THIS IS A WARNING
	{
	    errText = "Warn-$errText"
	}
    }


    :0 E
    * ^Subject:.*\/Too many hops
    {
	errText = "MaxHops,"
    }

    :0 E B
    * Connection to.*failed
    {
	errText = "Err-connection,"
    }

    # ........................................................ qmail ...


    #   Hi. This is the qmail-send program at master.debian.org.
    #   I'm afraid I wasn't able to deliver your message to the ...
    #   This is a permanent error; I've given up. Sorry it didn't work out.
    #
    #   <address>:
    #   Sorry, no mailbox here by that name. (#5.1.1)


    :0 E
    * B ?? wasn't able to deliver your message to.*addresse
    {
        errText = "err-Unknown,"

        :0
        * B ?? it didn't work out.($)+\/.*
        {
            match = $MATCH
        }

    }

    # .................................... daemon message known now? ...
    #   If the previous recipes didn't set errText,
    #   then this message was from a postmaster that sent it to
    #   the spam-l or to some other mailing list where it's okay
    #   to post copies of UBE.

    :0
    * ! errText ?? ^^^^
    {
        #  Read the old subject from body of original message

        :0 B
        *$  $SUPREME^0 ^Subject: \/.*
        *$  $SUPREME^0 The subject of the message is: \/.*
        {
            errSubj = $MATCH
        }

        #   To whom we tried to mail the message. Find it out
        #
        #       login@site.com
        #       |
        #       This part will be derived, there must be leading space

	:0
        *  errTo ?? ^^^^
        {

            :0
            *$ match ?? [<]()\/$charset+
            {
                errTo   = "$MATCH,"
            }


            :0 E B
            *$ ^To:.*\/$charset+@
            *$  MATCH ?? ()\/$charset+
            *$  MATCH ?? ^^\/[^@]+
            {
                errTo = "$MATCH,"
            }

            :0 E B
            *$ ()\/$charset+@
            *$  MATCH ?? ^^\/[^@]+
            {
                errTo = "$MATCH,"
            }
        }

        dummy = "$NL$id: recognized message: errText? $NL "


        # Now make new, combined, subject:
        # --> short error reason + original subject

        :0 fhw
        | $FORMAIL -I"Subject: ${errText}${errTo}${errSubj}"

        ERROR = "yes"       # Raise the flag
    }
}

dummy = "$id: end: (DAEMON detect status = $ERROR)"

# end of file pm-jadaemon.rc
