Create a mail ping with procmail

From braindump
Revision as of 21:49, 14 December 2013 by Uroesch (talk | contribs) (→‎Commands)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search


There was a time when as my job included checking if outbound mail was working as part of a morning check routine. After doing it a few times sending mail to an external address and then sending it back again. After a few times doing it I used my gray cells and came up with this procmail recipe cutting. With the time I saved I could now take a longer coffee break :).

Prerequisites

  • procmail
  • formail
  • MTA (postfix or sendmail to name but 2)

Howto

For this example we assume mail is sent from an address of *@foobar.office to ping@foobar.outside. In order to prevent the whole world from using your server as ping host the recipe should sport a From filter.

Recipe

PONG_FORMAT="
-------------------------------------------------------------------
pong %s
-------------------------------------------------------------------
full pong %s %s %s %s
-------------------------------------------------------------------
epoch-nano pong %s
-------------------------------------------------------------------

-------------------------------------------------------------------
Original Received Headers:
-------------------------------------------------------------------
%s
-------------------------------------------------------------------
Notice: This is an automated messages and will only work from the
foobar.office domain
-------------------------------------------------------------------
"

## ----------------------------------------------------------------------------
## morning check
## ----------------------------------------------------------------------------
:0:
* ^To:.*ping@foobar.outside
{

  RECEIVED=`formail -X 'Received'`
  PONG_TIME=`date "+%H%M %F %T %z (%Z) %s.%N"`
  :0:
  * ^From:.*@foobar.office
  | (formail -r; printf "$PONG_FORMAT" $PONG_TIME "$RECEIVED";) | \
    $SENDMAIL -oi -t -f 'ping@foobar.outside'

  # Send to the bit bucket if no match
  :0:
  /dev/null
}

Explanation

Variables

PONG_FORMAT
Holds the message to in a format usable by the printf unix command. When modifiying this message the printf arguments must be modified to reflect the number of placeholders.
RECEIVED
Holds the header of the incoming mail. This is great to find out how many hops the mail took and how long it took at each hop.
PONG_TIME
Hold the time when the mail was first processed by the procmail rule. The receiving server should be in the same time zone as the sender. If they differ the command can be prefixed with TZ=<zone> date ....
SENDMAIL
Automatically assigned by procmail. Holds the full path to the sendmail binary.

Commands

formail -r
Generate an auto-reply header. Will throw away all the existing headers. Hence the formail -X command further up in the script!
printf
Print the new message body based on the PONG_FORMAT template.
sendmail
Send the message straight back to the sender.

The command formail -r and printf are executed in a subshell so the message is concatenated before handed to sendmail.

Sample reply

Variable content in green.

-------------------------------------------------------------------
pong 2149 
-------------------------------------------------------------------
full pong 2013-12-14 21:49:52 +0100 (CET)
-------------------------------------------------------------------
epoch-nano pong 1387054192.776386000
-------------------------------------------------------------------

-------------------------------------------------------------------
Original Received Headers:
-------------------------------------------------------------------
Received: from mxout.foobar.office (mxout.foobar.office [IPv6:XXXX::XXXX])
	by mail.foobar.outside (Postfix) with ESMTPS id EA6F7C8D901B
	for <ping@foobar.outside>; Sat, 14 Dec 2013 21:49:49 +0100 (CET)
Received: from [10.3.4.45] (helo=smtp.foobar.office)
	by mxout.foobar.office with esmtp (Exim 4.80.1 (FreeBSD))
	(envelope-from <morning-check@foobar.office>)
	id 1Vrw9k-000JOr-Q3
	for ping@foobar.outside; Sat, 14 Dec 2013 21:49:48 +0100
Received: from [xx.xx.xx.xx] (helo=mail.foobar.office)
	by smtp.foobar.office with esmtpsa (TLSv1:DHE-RSA-AES256-SHA:256)
	(Exim 4.80.1 (FreeBSD))
	(envelope-from <morning-check@foobar.office>)
	id 1Vrw9k-00080q-N2
	for ping@foobar.outside; Sat, 14 Dec 2013 21:49:48 +0100
-------------------------------------------------------------------
Notice: This is an automated messages and will only work from the
foobar.office domain
-------------------------------------------------------------------