#!/bin/sh
# -------------------------------------------------------------
#  Copyright (c) 1991 Regents of the University of Michigan.
#  All rights reserved.
#
#  Redistribution and use is permitted provided that this notice 
#  is preserved and that due credit is given to the University of 
#  Michigan. The name of the University may not be used to endorse 
#  or promote products derived from this software without specific 
#  prior written permission. This software is provided "as is" 
#  without express or implied warranty.
#
#  Mail Statistics gatherer
#  Author:  Bryan Beecher
#  Last Modified: 10/17/94
# -------------------------------------------------------------
LOGDIR=/var/log
MAILLOGFILE=maillog
ALIASFILE=/etc/aliases
TEMPFILE=/var/tmp/.mtool.$$
COUNT=20
FROM=/var/tmp/from.$$
VIA=/var/tmp/via.$$
TO=/var/tmp/to.$$
ERRORS=/var/tmp/errors.$$
#ERRORSTO=root@kaybee.gt.ed.net
TESTMODE=0

# -------------------------------------------------------------
#  set things up
# -------------------------------------------------------------
PATH=:/bin:/usr/bin:/usr/ucb:/sbin:/usr/sbin
rm -f $TEMPFILE $FROM $VIA $TO $ERRORS

trap "rm -f $TEMPFILE $FROM $VIA $TO $ERRORS ; exit 0" 0 1 2 3 15

# -------------------------------------------------------------
#  handle arguments
# -------------------------------------------------------------
#	-c count
#	Specify the top-N numbers to show in each section of
#	the report.
#
#       -y
#       Do stats for yesterday, not today
#
#	-t	test mode
# -------------------------------------------------------------
while [ $# != 0 ] ; do
        case "$1" in

		-c)
		COUNT=$2
		shift
		;;

		-t)
		TESTMODE=1
		;;

        esac
        shift
done

# -------------------------------------------------------------
#  Give a header...
# -------------------------------------------------------------
echo
echo "#################### Begin Mail Information ######################"
echo

# -------------------------------------------------------------
#  Dice up the lines the way we want
# -------------------------------------------------------------
cd $LOGDIR
if [ ! -s $MAILLOGFILE ] ; then
	exit 0
fi
cat $MAILLOGFILE | egrep "sendmail" |
	egrep -v "starting daemon|alias database|$ALIASFILE|gethostbyaddr|programs|setsender|return to sender" | 
	egrep -v "SYSERR|User unknown|protocol error|timeout waiting|lost input channel|unexpected close|Unbalanced" |
	egrep -v "Address contained invalid control characters|File exists|grew worklist" |
	tr A-Z a-z  | egrep -v " expn | vrfy " |
	awk '
$6 == "finis," { next; }
$7 == "done" { next; }
$7 == "alias" { next; }
$7 == "clone" { next; }
$7 == "forward" { next; }
$6 == "connect" { next; }
$7 == "aliases," && $8 == "longest" { next; }
$7 == "mail" && substr($8, 1, 5) == "from:" { next; }
$8 == "try" { next; }
$(NF-2) == "user" && $(NF-1) == "address" && $NF == "required" { next; }
$6 == "possible" && $7 == "attack" { next; }
$7 ~ /from=.*/ {
	#
	#  Split up the line using the commas
	#
	n = split($0, part, ",")

	#
	#  Pick off the host that sent this mail
	#  to be used later.
	#
	m = split(part[1], from, " ")
	host = from[m]
	if (substr(from[m], 1, 5) == "from=")
		host = substr(from[m], 6)
	else  {
		host = "user@horribly-mangled-address"
	}

	#
	#  Increment our bytes handled counter.
	#
	bytes += substr(part[2], 7)

	#
	#  Increment our recipients handled counter.
	#
	recipients += substr(part[5], 9)

	#
	#  Record who (directly) sent us this message.
	#  Look for user@localhost form.
	#
	if (substr(part[n], 1, 6) == " relay") {
		viahost = substr(part[n], 8)
		m = split(viahost, relay, " ")
		m = split(relay[1], junk, "@")
		if (m > 1)
			viahost = junk[2]
		else if (relay[1] == "[response]")
			viahost = localhost
		else
			viahost = relay[1]
		if (viahost == "localhost")
			viahost = localhost
		print viahost >f4
	}

	#
	#  Where is this mail from?  Handle the easy cases first, and
	#  then handle the nasty ones.
	#
	if (host == "mailer-daemon") {
		print localhost >f1
		next
	}
	if (viahost == localhost) {
		print localhost >f1
		next
	}
	if ((viahost == "local" || viahost == localhost) && host == "news") {
		print localhost >f1
		next
	}
	#
	#  Can be <blah> or <blah, woof>
	#  We just want blan.
	#
	if (substr(host, 1, 1) == "<")
		host = substr(host, 2)
	if (substr(host, length(host)) == ">")
		host = substr(host, 1, length(host) - 1)

	#
	#  Correct for user@domain(First Last) lines
	#
	i = split(host, tmp, "(")
	if (i > 1)
		host = tmp[1]

	#
	#  Handle from=<>
	#
	if (length(host) == 0) {
		print "NULL sender" >f1
		next
	}

	i = split(host, bangs, "!")
	j = split(host, ats, "@")
	k = split(host, pers, "%")
	l = split(host, routes, ":")

	#
	#  if it contains quotes and a @-sign
	#  we sort of bail out here
	m = split(host, quotes, "\"");
	if ((m > 1) && (j > 1)) {
		print ats[j] >f1
		next
	}
	#
	#  from=foo, but not handled above
	#
	if (i == 1 && j == 1 && k == 1) {
		print viahost >f1
		next
	}

	#
	#  site!...!SITE!user
	#
	if (i > 1 && j == 1 && k == 1 && l == 1) {
		print bangs[i - 1] >f1
		next
	}
	#
	#  some-stuff@DOMAIN
	#
	if (j == 2) {
		print ats[2] >f1
		next
	}
	#
	#  user%DOMAIN...@domain
	#
	if (i == 1 && j == 2 && k >= 2 && l == 1) {
		n = split(ats[1], tmp, "%")
		print tmp[2] >f1
		next
	}
	#
	#  @domain:god-knows-what@DOMAIN
	#
	if (l == 2 && j >= 3) {
		print ats[j] >f1
		next
	}
	#
	#  site!...!user%DOMAIN
	#  site!...!%DOMAIN!user
	#
	if (i >= 2 && j == 1 && k == 2 && l == 1) {
		n = split(pers[2], tmp, "!")
		if (n == 1)
			print pers[2] >f1
		else
			print tmp[1] >f1
		next
	}
	#
	#  foo@foo@DOMAIN
	#
	if (j > 2) {
		print ats[j] >f1
		next
	}
	print "from=" host, "line=", $0 >errors
	next
}

$7 ~ /to=.*/	{
	#
	# Only interested in delivered mail.
	#
	comma_parts = split($0, parts, ",")
	m = split(parts[comma_parts], status, " ")
	if (status[1] != "stat=sent") {
		next
	}
	count++

	#
	#  Pick off the receiving host for later use.
	#
	split($7, part, ",")
	if (part[1] == "to=<") {
		split($8, part, ",")
		host = part[1]
	}
	else
		host = substr(part[1], 4)
	if (substr(host, 1, 1) == "<")
		host = substr(host, 2)
	while (substr(host, 1, 1) == " ")
		host = substr(host, 2)
	if (substr(host, length(host)) == ">")
		host = substr(host, 1, length(host) - 1)

	#
	#  Record delay if delivered.
	#  And count delivered messages.
	#
	for (i = 1; i <= comma_parts; i++) {
		if (substr(parts[i], 1, 5) == " dela") {
			time = substr(parts[i], 8)
			break
		}
	}
	# time = substr(time, 1, length(time) - 1)
	n = split(time, dly, ":")
	delay = (dly[1] * 3600) + (dly[2] * 60) + dly[3]

	i = split(host, bangs, "!")
	j = split(host, ats, "@")
	k = split(host, pers, "%")
	l = split(host, routes, ":")

	#
	#  if it contains quotes and a @-sign
	#  we sort of bail out here
	m = split(host, quotes, "\"");
	if ((m > 1) && (j > 1)) {
		print ats[j] >f2
		next
	}
	#
	#  user [ local mail ]
	#
	if (i == 1 && j == 1 && k == 1 && l == 1) {
		print localhost, delay > f2
		next
	}
	#
	#  site!...!SITE!user
	#
	if (i > 1 && j == 1 && k == 1 && l == 1) {
		print bangs[i - 1], delay >f2
		next
	}
	#
	#  foo@foo@foo[@foo...]
	#
	if (j > 2) {
		print ats[j], delay >f2
		next
	}
	#
	#  stuff@DOMAIN
	#
	if (j == 2) {
		print ats[2], delay >f2
		next
	}
	#
	#  @domain:user@DOMAIN
	#
	if (i == 1 && j == 3 && k == 1 && l == 2) {
		print ats[3], delay >f2
		next
	}
	#
	#  @domain:...%DOMAIN@domain
	#
	if (i >= 1 && j >= 1 && k >= 2 && l == 2) {
		n = split(routes[k], tmp, "@")
		print tmp[1], delay >f2
		next
	}
	#
	#  site!...!user%DOMAIN
	#  site!...!%DOMAIN!user
	#
	if (i > 2 && j == 2 && k == 1 && l == 1) {
		print bangs[i - 2], delay >f2
		next
	}
	#
	#  site!...!user%DOMAIN
	#  site!...!%DOMAIN!user
	#
	if (i >= 2 && j == 1 && k == 2 && l == 1) {
		n = split(pers[2], tmp, "!")
		if (n == 1)
			print pers[2], delay >f2
		else
			print tmp[1], delay >f2
		next
	}
	print "to=" host, "delay=" delay, "line=" $0 >errors
	next
}

{
	#
	#  Did not recognize this
	#
	print "Did not recognize this =>", $0 >errors
}

END {
	if ((count + bytes + recipients) > 0) {
		printf("\n")
		printf("Total messages   handled: %5d\n", count)
		printf("Total recipients handled: %5d\n", recipients)
		printf("Total bytes      handled: ")
		if (bytes > 1000000)
			printf("%5.2fM\n", bytes / 1000000)
		else if (bytes > 1000)
			printf("%5.2fK\n", bytes / 1000)
		else
			printf("%5.2f\n", bytes)
		printf("\n")
	}
}
' localhost=`hostname` min=100 f1=$FROM f2=$TO f4=$VIA errors=$ERRORS -

if [ ! -s $FROM ] ; then
	exit 0
fi

# -------------------------------------------------------------
#  Print out info about who sent us mail
# -------------------------------------------------------------
echo " "
echo "--------------------------------------------------------------"
echo Part I -- Mail relayed from:
echo "--------------------------------------------------------------"
sort $VIA | uniq -c | sort -rn | head -$COUNT

# -------------------------------------------------------------
#  Print out info about who got the mail
# -------------------------------------------------------------
echo " "
echo "--------------------------------------------------------------"
echo Part II -- Mail sent from:
echo "--------------------------------------------------------------"
sort $FROM | uniq -c | sort -rn | head -$COUNT

# -------------------------------------------------------------
#  Print out info about who got mail
# -------------------------------------------------------------
echo " "
echo "--------------------------------------------------------------"
echo "Part III -- Mail sent to:               Avg delay   Max delay"
echo "--------------------------------------------------------------"
sort $TO | awk ' NR == 1 {
	last = $1
	delay += $2
	max = $2
	count = 1
	next
}
{
	#
	#  Each line should be of form:  <host> <delay>
	#  Lines are also ordered by host name, and so
	#  if the previous line began with a different
	#  name, we know we are on a new host.
	#
	if ($1 == last) {
		if ($2 > max)
			max = $2
		delay += $2
		count++
	}
	else {
		#
		#  Print results and reset.
		#
		avg = delay / count
		printf("%5d  %-30s", count, last)
		if (avg >= 3600)
			printf("  %5.2f hrs ", avg / 3600)
		else if (avg >= 60)
			printf("  %5.2f mins", avg / 60)
		else
			printf("  %5.2f secs", avg)
		if (max >= 3600)
			printf("  %5.2f hrs ", max / 3600)
		else if (max >= 60)
			printf("  %5.2f mins", max / 60)
		else
			printf("  %5.2f secs", max)
		printf("\n")

		last = $1
		count = 1
		delay = max = $2
	}
}
END	{ 
	avg = delay / count
	printf("%5d  %-30s", count, last)
	if (avg >= 3600)
		printf("  %5.2f hrs ", avg / 3600)
	else if (avg >= 60)
		printf("  %5.2f mins", avg / 60)
	else
		printf("  %5.2f secs", avg)
	if (max >= 3600)
		printf("  %5.2f hrs ", max / 3600)
	else if (max >= 60)
		printf("  %5.2f mins", max / 60)
	else
		printf("  %5.2f secs", max)
	printf("\n")

}' | sort -rn | head -$COUNT

# -------------------------------------------------------------
#  Mail any errors that were found with this script
# -------------------------------------------------------------
if [ -s $ERRORS ] ; then
	if [ $TESTMODE -eq 1 ] ; then
		echo "Found these errors"
		echo " "
		cat $ERRORS
#	else
#		Mail -s "smtpstats errors" $ERRORSTO < $ERRORS
	fi
fi

# -------------------------------------------------------------
#  Tidy up
# -------------------------------------------------------------
rm -f $TO $VIA $FROM $TEMPFILE $ERRORS
echo
echo "#################### End Mail Information ######################"
echo
