Tracking the volume of Mail

Tom Christiansen tchrist at convex.COM
Sat Jun 8 00:41:21 AEST 1991


>From the keyboard of rekna at megatest.UUCP (Randy Bias):
:Recently my boss asked me if there was a way to track incoming and outgoing
:mail messages that flow through our mailhost (both through UUCP and internally
:via smtp).  I was wondering if there is an "easy" way to do this, or if any
:programs/scripts have been written to do this.
:
:BTW, the data will be used to convince our company president how much email
:is used.  He seems to have a hard time understanding the usefulness of it.
:(And I HATE voice mail).  :)

Try this.  It's called "ssl" for summarize sendmail syslog.  It's
weirder looking then normal because I wrote it ages and ages 
ago, and other(s?) have hacked on it since then.  But it may do 
what you want.  Here's an example of partial output from today's
syslog on my machine.  

To: 146
  12 messages    5813 bytes streepy at pixel
   8 messages    7886 bytes tchrist at pixel.convex.com
   8 messages    5639 bytes streepy at pixel.convex.com
   5 messages    6949 bytes mbecker at pixel.convex.com
   5 messages    6949 bytes chiarell at pixel.convex.com
   5 messages    1617 bytes "|/usr/ucb/msgs -s"
   4 messages   10838 bytes tpowell
   4 messages    1920 bytes rmingee at pixel
   1 message       77 bytes plaxco at dhostwo
From: 110
  18 messages    9551 bytes root at concave.convex.com
  10 messages   13898 bytes motif-talk-request at osf.org
   7 messages    8270 bytes tchrist at pixel
   5 messages   19473 bytes strike at pixel
   3 messages   15152 bytes x-mailer at expo.lcs.mit.edu
   3 messages    2198 bytes shaver at orion.convex.com
   3 messages    1994 bytes strike
   3 messages     468 bytes ssimmons

It's not perfect: notice that strike at pixel and strike aren't collapsed.
Someday I may try to "fix" that in some sensible way.

--tom

#!/usr/bin/perl
#
#	original by Tom Christiansen <tchrist at convex.com>
#	1988 sometimes, i think
#
#	Paul O'Neill
#	Coastal Imaging Lab
#	Oregon State University
#
#	18 jun 90
#	fix various bugs
#	add sorted output
#
# summarize sendmail syslog
#
# flags mean:
#
#	-o	outbound mail only
#	-i	inbound  mail only
#	-t	suppress printing of totals
#	-e 	print strange lines to stderr
#	-m	reduce to local mbox is possible

($program = $0) =~ s%.*/%%;


while ($ARGV[0] =~ /^-/) {
    $ARGV[0] =~ s/^-//; 
    foreach $flag ( split (//,$ARGV[0]) ) {
	if ( 'oitem' !~ /$flag/ ) {
	    printf stderr "unknown flag: %s\n", $flag;
	    die "usage: $program [-oitem] [syslog_file ...]\n";
	} 
	die "$0: '$flag' flag already set\n" if ($flags{$flag}++);
    } 
    shift;
}

if ( !$flags{'o'} && !$flags{'i'} && !$flags{'t'}) {
    $flags{'o'}++;
    $flags{'i'}++;
} 

do hash_passwd() if $flags{'m'};

while (<>) {
    if (/: [A-Z][A-Z](\d+): from=(.*), size=(\d+)/) {
#	next unless $flags{'t'} || $flags{'o'};
	($id, $user, $size) = ($1, $2, $3);
	$user =~ s/.*<(.*)>/$1/;		# get rid of <>
	$user =~ tr/A-Z/a-z/;			# canonical lc

	if ($flags{'m'}) {
	    $ouser = $user;
	    $user = do strip($user);
	    $user = $ouser if ! $known{$user};
	}

	$from_user_size{$user} += $size;
	$id_size{$id} = $size;
	$from_user_count{$user}++;
	$total_from++;
    } elsif (/: [A-Z][A-Z](\d+): to=(.*), delay=/) {
#	next unless $flags{'t'} || $flags{'i'};
	$id = $1;
	for (split(/,/, $2)) {
	    s/.*<(.*)>/$1/;
#	    $to = $flags{'m'} ? do strip($_) : $_;
	    $to = $_;
	    if ($flags{'m'}) {
		$oto = $to;
		$to = do strip($to);
		$to = $oto if ! $known{$to};
	    }
	    $to =~ tr/A-Z/a-z/;
#	    printf "adding %d bytes to %s from %s\n",
		$id_size{$id},$to,$user; 
	    if (!$to) {
		die "to no one: $_\n";

	    } 
	    $to_user_size{$to} += $id_size{$id};
	    $to_user_count{$to}++;
	    $total_to++;
	} 
    } else {
	study;
	next if /message-id/;
	next if /locked/;
	next if /alias database (auto|)rebuilt/;
	#next if /aliases/;
	next if /rebuilding alias database/;
	print stderr if $flags{'e'};
	$errors++;
    } 
} 

printf stderr "Error lines: %d\n", $errors if $errors && ($flags{'e'}) && !($flags{'t'});


if ($flags{'i'}) {
    printf "To: %d\n", $total_to unless $flags{'t'};;

    @loop = keys(to_user_size);
    foreach $user (sort tosort @loop) {
	printf "%4d message%s %7d bytes %s\n",
	    $to_user_count{$user}, 
	    $to_user_count{$user} != 1 ? "s" : " ",
	    $to_user_size{$user}, 
	    $user;
    } 
}


if ($flags{'o'}) {
    printf "From: %d\n", $total_from unless $flags{'t'};;

    @loop = keys(from_user_size);
    foreach $user (sort fromsort @loop) {
	printf "%4d message%s %7d bytes %s\n",
	    $from_user_count{$user}, 
	    $from_user_count{$user} != 1 ? "s" : " ",
	    $from_user_size{$user}, 
	    $user;
    } 
}

sub tosort {
    ($to_user_count{$b} - $to_user_count{$a})* 10000000 + $to_user_size{$b} - $to_user_size{$a};
}

sub fromsort {
    ($from_user_count{$b} - $from_user_count{$a}) * 10000000 + $from_user_size{$b} -$from_user_size{$a};
}

sub strip {
    local($foo) = shift(@_);
    
    $foo =~ s/@.*//;
    $foo =~ s/.*!//;
    $foo =~ s/\s*\(.*\)//;
    $foo =~ tr/A-Z/a-z/;

    return $foo;
} 

sub hash_passwd {
    chop($yp = `/bin/domainname`) if -x '/bin/domainname';
    $passwd = $yp ? 'ypcat passwd |' : '/etc/passwd';
    open passwd || die "$program: can't open $passwd: $!\n";
    while (<passwd>) {
	/^(\w+):[^:]+:(\d+):.*/;
	($who,$uid) = ($1, $2);
	$uid = 'zero' if ($uid == 0) && $who;
	$known{$who} = $uid;
    } 
    close passwd;
} 
--
Tom Christiansen		tchrist at convex.com	convex!tchrist
	    "Perl is to sed as C is to assembly language."  -me



More information about the Comp.unix.admin mailing list