[comp.unix.admin] Tracking the volume of Mail

rekna@megatest.UUCP (Randy Bias) (06/06/91)

Hola.

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).  :)

Thanks for your replys,

--Randy Bias				(sun!megatest!rbias)
System Administrator
Megatest Corporation

wolf@grasp1.univ-lyon1.fr (Christophe Wolfhugel) (06/07/91)

In article <18798@megatest.UUCP> rekna@megatest.UUCP (Randy Bias) writes:
>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.

On some Unixes there is a statistics files that indicates the mail
usage in number of kilobytes & messages.

Mail is accounted as long as the file exist.
Try creating it: touch /usr/lib/sendmail.st, being root.

To check if this is really implemented, search for a file (don't remember
if it's a script or exec) named 'mailstats', not necessarily in the
standard path.

If yes, then probably you'll have stats... I use it on AIX & SysV.

-- 
Christophe Wolfhugel    | Email: wolf@grasp1.univ-lyon1.fr
INSA - Dpt Informatique | "Le progres ne vaut que s'il est partage par tous,"
Lyon, France            | "les greves aussi. Hassan Cehef: c'est penible!"

Tom Christiansen <tchrist@convex.COM> (06/07/91)

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

It's not perfect: notice that strike@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@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@convex.com	convex!tchrist
	    "Perl is to sed as C is to assembly language."  -me