#!/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 or # 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: # 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