#!/usr/bin/perl # works with perl 4 # sendmail_stats Version 0.05 # (c) 2000 Jeremy C. Reed # this is free, but use at your own risk ## still needs a lot of work; it is probably only 10 percent finished ## and about 90 percent of this code needs to be rewritten. # use like in your crontab: #30 5 * * * nobody /usr/contrib/bin/gunzip -c /var/log/maillog.0.gz |\ # /usr/local/bin/sendmail_stats | /usr/bin/mail -s "sendmail stats" postmaster #CHANGES #31/Aug/2000 # Added output in megabytes for total bytes transferred and received # Added log start and end times needed for reference! #31/May/2000 # Fixed problem where it didn't find (match) all data # also show stats for multi-users per "to=" and for programs (like procmail) # Fix scaling for dots #10/Mar/2000 # Changed scale for dots #8/Mar/2000 # Fixed bug where the dots wrapped around screen #7/Mar/2000 # Fixed bug where only 10 am and later hours showed stats #for appending "@" and host name $default_hostname = 'EDIT-THIS-default-domain.net'; $top_amt = 20; ## MAIN routine while ($line = <>) { # sample data #Mar 6 20:34:53 mail sendmail[25508]: UAA25508: from=, size=1394, class=-60, pri=139394, nrcpts=1, msgid=<01BF87B2.98738820.alan@alan.net>, proto=SMTP, relay=qmailr@[209.19.164.76] #Mar 6 20:34:53 mail sendmail[25512]: UAA25508: to=, delay=00:00:01, xdelay=00:00:00, mailer=local, stat=Sent #May 31 05:01:32 mail sendmail[9663]: FAB09663: to="|/usr/bin/procmail -d lwn", ctladdr=:include: /etc/mail/mis.list (0/0), delay=00:00:00, xdelay=00:00: 00, mailer=prog, stat=Sent #if ($line =~ /proc.*ctladd/) { print "**HERE $line\n"; } if ($line =~ /^(\w+)\s+(\d+)\s(\d+):(\d+:\d+)\s+(\w+)\s+(\w+)\[(\d+)\]:\s(\w+\d+):\s(.+)$/) { $month = $1; $day = $2; $hour = $3; $min_sec = $4; $user = $5; $daemon = $6; $pid = $7; $id = $8; $data = $9; # get log start time if (! $log_start_time) { $log_start_time = "$month $day $hour $min_sec"; } if ($daemon eq 'sendmail') { #if ($data =~ /proc/) { print "HERE $data\n"; } if ($data =~ /from\=\<(.+)\>\,\ssize\=/) { $from = $1; $senders{$from}++; if ($data =~ /size\=(\d+)\,\s/) { $size = $1; $sizes{$id} += $size; $total_size += $size; } if ($data =~ /relay\=(.+)[$:]/) { $relay = $1; if ($relay =~ /may be/) { $relay =~ s/(.*) \(may be/$1/; } $sending_hosts{$relay}++; } } # elsif ($data =~ /to\=[<"](.+)[>"]\,\s/) { ## needs to also match no quotes or no angle brackets # elsif ($data =~ /to\=(.*)\,\s[dc][et]la/) { # elsif ($data =~ /to\=(.+)\, [ctladdr]|[delay]=/) { elsif (($data =~ /to\=(.+)\, ctladdr=.*, delay=/) || ($data =~ /to\=(.+)\, delay=/)) { # elsif ($data =~ /to\=(.+)\, ctladdr=/) { $to = $1; #if ($data =~ /ctla/) { print "here -- $to\n"; } #May 31 14:05:36 mail sendmail[2441]: OAB02441: to=plm,jbh,mmg,cpj, delay=00:00:01, xdelay=00:00:01, mailer=local, stat=Sent #May 31 14:05:36 mail sendmail[2441]: OAB02441: to="|/usr/bin/procmail -d jcr", ctladdr=:include: /etc/mail/mis.list (0/0), delay=00:00:01, xdelay=00:00:00, mailer=prog, stat=Sent if ($data =~ /mailer\=(.+)\,\s/) { $mailer = $1; if ($mailer eq "local" || $mailer eq "prog") { if ($to =~ /ctladd/) { print "2a -- $data\n2b -- $to\n"; } $local_size += $sizes{$id}; delete ($sizes{$id}); $received_messages++; $to =~ s/[<"](.+)[>"]/$1/; if ($to =~ /\,/) { foreach $username (split (/\,/, $to)) { $username = $username . '@' . $default_hostname; $local_deliveries{$username}++; } } else { $local_deliveries{$to}++; #if ($to =~ /proc/) { print "3a -- $data\n3b -- $to\n"; } } } elsif ($mailer =~ /smtp/i) { $delivered_messages++; if ($data =~ /relay\=(.+)\,\sstat\=/) { $relay = $1; $destination_hosts{$relay}++; } } } } $months{$month}++; $days{$day}++; $hours{$hour}++; # $total++; } } } # get log start time $log_end_time = "$month $day $hour $min_sec"; ## 1048576 is one meg $total_size_mb = sprintf ("%.1f", ($total_size/1048576)); $local_size_mb = sprintf ("%.1f", ($local_size/1048576)); #$delivered_messages_k = sprintf ("%.1f", ($delivered_messages/1024)); #$received_messages_k = sprintf ("%.1f", ($received_messages/1024)); print < $max) { $max = $hours{$i}; } } $scale = int($max/50); $scale = 1 if $scale == 0; print "Messages per hour (each dot is $scale messages)\n________________\n"; for ($c = 0; $c < 24; $c++) { if ($c < 10) { $i = "0$c"; } else { $i = $c; } printf("%3d: %6d %s\n", $i, $hours{$i}, "." x int($hours{$i}/$scale)); } &show_sending_hosts; &show_destination_hosts; &show_local_deliveries; &show_senders; print "\n"; ## end sub show_sending_hosts { $count = 0; print "\nTop $top_amt Sending Hosts\n____________________\n"; foreach $key (sort { $sending_hosts{$b} <=> $sending_hosts{$a} } keys %sending_hosts) { $count++; if ($count <= $top_amt) { print "$sending_hosts{$key}\t$key\n"; } $total_sending_hosts++; $total_sending_host_messages += $sending_hosts{$key}; } print "\n$total_sending_hosts sending hosts attempted $total_sending_host_messages messages\n"; } # show_sending_hosts sub show_destination_hosts { $count = 0; print "\nTop $top_amt Destination Hosts\n________________________\n"; foreach $key (sort { $destination_hosts{$b} <=> $destination_hosts{$a} } keys %destination_hosts) { $count++; if ($count <= $top_amt) { print "$destination_hosts{$key}\t$key\n"; } $total_destination_hosts++; $total_destination_host_messages += $destination_hosts{$key}; } print "\n$total_destination_hosts destination hosts received $total_destination_host_messages messages\n"; } # show_destination_hosts sub show_local_deliveries { $count = 0; print "\nTop $top_amt Local Deliveries\n_______________________\n"; foreach $key (sort { $local_deliveries{$b} <=> $local_deliveries{$a} } keys %local_deliveries) { $count++; if ($count <= $top_amt) { print "$local_deliveries{$key}\t$key\n"; } $local_accounts++; } print "\n$local_accounts local accounts received mail ($received_messages messages combined).\n"; } # show_local_deliveries sub show_senders { $count = 0; print "\nTop $top_amt Senders\n______________\n"; foreach $key (sort { $senders{$b} <=> $senders{$a} } keys %senders) { $count++; if ($count <= $top_amt) { print "$senders{$key}\t$key\n"; } $total_senders++; $total_senders_messages += $senders{$key}; } print "\n$total_senders senders sent a combined $total_senders_messages messages.\n"; } # show_senders sub show_data { print <