#!/usr/bin/perl ######################################################################## # # sendmail_mail_stats.pl # # Perl script to report some stats from sendmail maillog log files. # It will report how many messages recieved and sent, and how much # bandwidth they consumed, and estimated figures for a full month # of traffic. # # Copyrite (C) 2002 Purified Data dot Net, llc. (support@purifieddata.net) # # This program may be distributed under the terms of the GNU General # Public License, Version 2, or (at your option) any later version. # # $Id: sendmail_mail_stats.pl,v 1.6 2002/10/27 08:41:46 jmiller Exp $ ######################################################################## use strict; use Time::Local; unless (-r $ARGV[0]) { print "Usage: $0 [/var/log/yourmaillogfile] You can also pass it a gzip'd logfile if you have gzcat in your path, and the file ends in \".gz\". Examples: $0 /var/log/maillog will read from current logfile. $0 /var/log/maillog.0.gz will read from \"gzcat /var/log/maillog.0.gz\"\n"; exit; } my $logfile = $ARGV[0]; my %month = ( Jan => 0, Feb => 1, Mar => 2, Apr => 3, May => 4, Jun => 5, Jul => 6, Aug => 7, Sep => 8, Oct => 9, Nov => 10, Dec => 11 ); my $thisyear = (localtime)[5]; my $openstr; if ($logfile =~ /\.gz$/i) { $openstr = "gzcat $logfile |"; } else { $openstr = "< $logfile"; } open(ML,"$openstr") || die "Unable to open logfile [$logfile]: $!\n"; my ($begin_timestamp,$end_timestamp); my ($sent_msgs,$recieved_msgs,$recieved_size,%rcpt_msgid,%from_msgid); while() { if (/^(\S+)\s+(\d+)\s+(\d+):(\d+):\d+\s\S+\s\S+\[\d+\]:\s+(\S+):\s+from=([^,]+),\s+size=(\d+),\s.+?relay=.*?\[(\d+\.\d+\.\d+\.\d+)\]/) { # mail from my ($mon,$day,$hr,$min,$msgid,$from,$size,$relayaddr) = ($1,$2,$3,$4,$5,$6,$7,$8); my $thisstamp = timelocal(0,$min,$hr,$day,$month{$mon},$thisyear); $begin_timestamp = $thisstamp if ( ($begin_timestamp > $thisstamp) || (! $begin_timestamp) ); $end_timestamp = $thisstamp if ( ($end_timestamp < $thisstamp) || (! $end_timestamp) ); $recieved_msgs++; $recieved_size += $size; $from_msgid{$msgid} = $size; } elsif (/^(\S+)\s+(\d+)\s+(\d+):(\d+):\d+\s\S+\s\S+\[\d+\]:\s+(\S+):\s+to=([^,]+),\s.+?stat=(\S+)/) { # mail to my ($mon,$day,$hr,$min,$msgid,$to,$stat) = ($1,$2,$3,$4,$5,$6,$7); # don't count defered/etc/non-sent msgs (thanks to Steve Thomas) next unless ($stat =~ /^sent/i); my $thisstamp = timelocal(0,$min,$hr,$day,$month{$mon},$thisyear); $begin_timestamp = $thisstamp if ( ($begin_timestamp > $thisstamp) || (! $begin_timestamp) ); $end_timestamp = $thisstamp if ( ($end_timestamp < $thisstamp) || (! $end_timestamp) ); $sent_msgs++; $rcpt_msgid{$msgid}++; } } my $sent_size; foreach my $msgid (keys %from_msgid) { $sent_size += ($from_msgid{$msgid} * $rcpt_msgid{$msgid}) if $rcpt_msgid{$msgid}; } my $readable_sent_size = &get_readable_size($sent_size); my $readable_recieved_size = &get_readable_size($recieved_size); my $month_of_seconds = (30*24*60*60); # days*hrs*min*sec my $this_log_period = $end_timestamp - $begin_timestamp; my $percent_of_month = $month_of_seconds / $this_log_period; my $month_recieved_msgs = int($recieved_msgs * $percent_of_month); my $month_sent_msgs = int($sent_msgs * $percent_of_month); my $month_readable_recieved_size = &get_readable_size( int($recieved_size * $percent_of_month) ); my $month_readable_sent_size = &get_readable_size( int($sent_size * $percent_of_month) ); print " This maillog [$logfile] logged: $recieved_msgs messages recieved ($readable_recieved_size) $sent_msgs messages sent ($readable_sent_size) Earliest Timestamp: " . localtime($begin_timestamp) . " Last Timestamp: " . localtime($end_timestamp) . " Estimated figures for one month of traffic: $month_recieved_msgs messages recieved ($month_readable_recieved_size) $month_sent_msgs messages sent ($month_readable_sent_size) "; close(ML); sub get_readable_size { my $bytes = shift; my $readable; if ($bytes > (1024*1024*2)) { # return mB if > 2 m byte $readable = int( ($bytes / (1024*1024)) ); $readable .= "." . substr(int( ($bytes % (1024*1024)) ), 0, 1); $readable .= " total megabytes"; } elsif ($bytes > (1024*5)) { # return kB if > 5 k byte $readable = int( ($bytes / 1024) ); $readable .= "." . substr(int( ($bytes % 1024) ), 0, 1); $readable .= " total kilobytes"; } else { $readable = $bytes . " total bytes"; } return $readable; }