#! /usr/local/bin/perl
# $Id: sm.logger,v 1.3 92/08/25 16:00:34 drich Exp Locker: drich $
# $Id: sm.logger,v 1.4 8th Feb 2002 sins Exp Locker:  sins $
#
# Original Copyright (C) 1992  Daniel Rich
# Copyright (C) 2002  Sinclair InterNetworking Services
#
# Author: Daniel Rich (drich@lerc.nasa.gov)
# Author: Sinclair InterNetworking Services (andrew@sins.com.au)
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 1, or (at your option)
# any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# A copy of the GNU General Public License can be obtained from this
# program's author (send electronic mail to ange@hplb.hpl.hp.com) or from
# the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA
# 02139, USA.
#
# sm.logger - parse the sendmail log and produce a summary
#
# $Log: sm.logger,v $
# Revision 1.4  02/02/07 sins
# Add new log formats to handle sendmail 9.11.6 on Suns and Cobalt RAQ4
# Change column formatting for easier Excel Imports
#
# Revision 1.3  92/08/25  16:00:34  drich
# Fixed divide by zero error if no mail either delivered or sent.
# 
# Revision 1.2  92/08/05  14:03:14  drich
# Replaced '=' with '-' in output report
# 
# Revision 1.1  92/07/22  16:36:54  drich
# Logfile processor for sendmail
#
#
# Written by Dan Rich - drich@lerc.nasa.gov
#     Wed July 22, 1992
#

$debug=shift ;

# Change the following for the appropriate system type.
$systype = "Solaris";           # Valid are Ultrix, Sun, SGI, RS6000, Solaris

# Change the following to the local sendmail domain
$local_domain = "webdata.com.au";

if (! ($MAILLOG = shift)) {
LOOP: {
    if ( $systype eq "SGI")    { $MAILLOG = "/usr/adm/SYSLOG"; 
                                 last LOOP; }
    if ( $systype eq "Ultrix") { $MAILLOG = "/usr/spool/mqueue/syslog";
                                 last LOOP; }
    if ( $systype eq "Sun")    { $MAILLOG = "/var/adm/messages";
                                 last LOOP; }
    if ( $systype eq "Solaris"){ $MAILLOG = "/var/log/syslog" ;
				print "Solaris - /var/log/syslog" ;
                                 last LOOP; }
    if ( $systype eq "RS6000") { $MAILLOG = "/var/adm/messages";
                                 last LOOP; }
    print "This script does not support the system type: $systype"; exit(1);
}
}

sub parse_mail_addr {
    local($addr) = @_;
    # Attempt to parse an address down to an *originating* user and host.
    # Assume the address takes one of the following forms:
    #     user@host.domain
    #     host!host!host!user
    #     host!host!host!user@host.domain
    #     @host.domain:user@host.domain

    $user = "";
    $host = "";
    $domain = "";

    # Get rid of <> in address
    $addr =~ s/\<//g;
    $addr =~ s/\>//g;

    # Get rid of (Real Name)
    $addr =~ s/\(.*\)//;

    # Strip spaces
    $addr =~ s/ //g;

    # Split user and host
    if ( $addr =~ /[@!]/ ) {            # If we have and @ or ! address
        if ( (($user,$host) = ($addr =~ /@.*:(.*)@(.*)/ )) || 
             (($user,$host) = ($addr =~ /(.*)@(.*)/ )) ) {
            if ( $user =~ /!/ ) {
                ( $host, $user ) = ( $user =~ /([^!]*)!([^!]*)$/ );
            }
        } else {                        # Ok, it is uucp format
            if ( $addr =~ /!/ ) {
                ( $host, $user ) = ( $addr =~ /([^!]*)!([^!]*)$/ );
            }
        }
    } else {                            # This had better be local...
        $user = $addr;
        $host = "";
        $domain = "";
    }

    # Split host and domain
    if ( $host =~ /\./ ) {
        ($host,$domain) = ( $host =~ /([^.]*)\.(.*)/ );
    }

    return ($user, $host, $domain);
}

sub format_addr {
    local($username, $host, $domain) = @_;

    $addr = "";
    $username =~ tr/A-Z/a-z/;
    $host =~ tr/A-Z/a-z/;
    $domain =~ tr/A-Z/a-z/;

    if ((length($domain) != 0) && ($domain ne $local_domain)) {
        $addr = $username. "@" . $host . "." . $domain;
    } elsif (length($host) != 0 ) {
        $addr = $username. "@" . $host;
    } else {
        $addr = $username;
    }
    return $addr;
}

sub format_host {
    local($host, $domain) = @_;

    $addr = "";
    $host =~ tr/A-Z/a-z/;
    $domain =~ tr/A-Z/a-z/;

    if (($domain eq $local_domain) || 
        (($host . "." . $domain) eq $local_domain) ||
        (length($domain) == 0)) {
        $addr = "local";
    } else {
        $addr = $host . "." . $domain;
    }
    return $addr;
}

open (MAILLOG) || die "failed to open log file: $!\n";

$start_date = "";
$start_time = "";

while ( <MAILLOG> ) {
    $line = "";
    ( $systype eq "SGI" ) && ( /sendmail\[[0-9]*\]:/ && ($line = $_) );
    ( $systype eq "Sun" ) && ( /sendmail\[[0-9]*\]:/ && ($line = $_) );
    ( $systype eq "Solaris" ) && ( /sendmail\[[0-9]*\]:/ && ($line = $_) );
    ( $systype eq "Ultrix") && ( /sendmail:/ && ($line = $_) );
    if ( length($line) == 0 ) {
        next;
    }

    if ( length($start_date) == 0 ) {
        ($start_date, $start_time) = 
            ($line =~ /^([A-Z][a-z]* *[0-9]*) ([0-9][0-9]:[0-9][0-9]:[0-9][0-9])/);
    }
    ($end_date, $end_time) = 
        ($line =~ /^([A-Z][a-z]* *[0-9]*) ([0-9][0-9]:[0-9][0-9]:[0-9][0-9])/);
        
	$counter++;
	if ($debug>9) { print "$counter:\t$line" ; }
	if ($debug) { last if ($counter>50 ); }
    # if (($ID, $addr) = ($line =~/: ([A-Za-z0-9]*): to=(.*), delay/)) {
    # Changed by Andrew 07.02.02 for new format within [ ] section
    # Get the ID(unique) and the to address
    if (($ID2, $ID, $addr) = ($line =~/: \[ID ([0-9]*) mail.info\] ([A-Za-z0-9]*): to=(.*), delay/)) {
	if ($debug>9) { print "####to if\n" ; }
        if ( $line =~ /stat=Sent/ ) {
	if ($debug>9) { print "####Sent if\n" ; }
            foreach $taddr (split(/,/, $addr)) {
                ($username, $host, $domain) = &parse_mail_addr($taddr);
                $user = &format_addr($username, $host, $domain);
                $host = &format_host($host, $domain);
                $userlist{$user} = 1;
                $delivered{$user} .= $ID . ' ';
                $hostlist{$host} = 1;
                $delivered{$host} .= $ID . ' ';
                # Check if it was deferred
                $IDlist = $deferred{$user};
                foreach $tID (split(/ /, $IDlist)) {
                    if ( $tID == $ID ) {
                        $deferred{$user} =~ s/$ID //g;
                    }
                }
                $IDlist = $deferred{$host};
                foreach $tID (split(/ /, $IDlist)) {
                    if ( $tID == $ID ) {
                        $deferred{$host} =~ s/$ID //g;
                    }
                }
            }
        } elsif ( $line =~ /stat=Deferred/ ) {
            foreach $taddr (split(/,/, $addr)) {
                ($username, $host, $domain) = &parse_mail_addr($taddr);
                $user = &format_addr($username, $host, $domain);
                $host = &format_host($host, $domain);
                $userlist{$user} = 1;
                $hostlist{$host} = 1;
                # Check if it was deferred earlier
                $IDlist = $deferred{$user};
                $IDdeferred = 0;
                foreach $tID (split(/ /, $IDlist)) {
                    if ( $tID == $ID ) {
                        $IDdeferred = 1;
                    }
                }
                if ( $IDdeferred == 0 ) {$deferred{$user} .= $ID . ' ';}
                $IDlist = $deferred{$host};
                $IDdeferred = 0;
                foreach $tID (split(/ /, $IDlist)) {
                    if ( $tID == $ID ) {
                        $IDdeferred = 1;
                    }
                }
                if ( $IDdeferred == 0 ) {$deferred{$host} .= $ID . ' ';}
            }
        } else {
	if ($debug>9) { print "####first else\n" ;}
            foreach $taddr (split(/,/, $addr)) {
                ($username, $host, $domain) = &parse_mail_addr($taddr);
                $user = &format_addr($username, $host, $domain);
                $host = &format_host($host, $domain);
                $IDlist = $deferred{$user};
                foreach $tID (split(/ /, $IDlist)) {
                    if ( $tID == $ID ) {
                        $deferred{$user} =~ s/$ID //g;
                        last;
                    }
                }
                $IDlist = $deferred{$host};
                foreach $tID (split(/ /, $IDlist)) {
                    if ( $tID == $ID ) {
                            $deferred{$host} =~ s/$ID //g;
                        last;
                    }
                }
            }
        }
    }
    #if (($ID, $addr, $size) = ($line =~/: ([A-Za-z0-9]*): from=(.*), size=([0-9]*)/)) {
    if (($ID2, $ID, $addr, $size) = ($line =~/: \[ID ([0-9]*) mail.info\] ([A-Za-z0-9]*): from=(.*), size=([0-9]*)/)) {

	if ($debug>9) { print "from if#####\n" ; }
        ($username, $host, $domain) = &parse_mail_addr($addr);
        $user = &format_addr($username, $host, $domain);
        $host = &format_host($host, $domain);
        $userlist{$user} = 1;
        $sent{$user} .= $ID . ' ';
        $hostlist{$host} = 1;
        $sent{$host} .= $ID . ' ';
        $size{$ID} = $size;
    }
}

printf ("\n\n\t\t\tSendmail activity report\n");
printf ("Starting: %s %s\n",$start_date,$start_time);
printf ("Ending: %s %s\n",$end_date,$end_time);

#
# User statistics
$totsent = 0;
$totdelivered = 0;
$totpctsent =0;
$totpctdelivered = 0;
$countsent = 0;
$countdelivered = 0;
$countdeferred = 0;
foreach $user (sort keys(%userlist)) {
    $totsent{$user} = 0;
    $totdelivered{$user} = 0;
    $countsent{$user} = 0;
    $countdelivered{$user} = 0;
    $countdeferred{$user} = 0;

    # Count total messages sent by each user
    $IDlist = $sent{$user};
    foreach $ID (split(/ /, $IDlist)) {
        $totsent{$user} += $size{$ID};
        $countsent{$user}++;
    }
    $totsent += $totsent{$user};
    $countsent += $countsent{$user};

    # Count total messages received by each user
    $IDlist = $delivered{$user};
    foreach $ID (split(/ /, $IDlist)) {
        $totdelivered{$user} += $size{$ID};
        $countdelivered{$user}++;
    }
    $totdelivered += $totdelivered{$user};
    $countdelivered += $countdelivered{$user};

    # Count deferred messages for each user
    $IDlist = $deferred{$user};
    foreach $ID (split(/ /, $IDlist)) {
        $countdeferred{$user}++;
    }
    $countdeferred += $countdeferred{$user};
}

printf ("\n\n");
$REPORTFMT = "%-20s %5s %8s\n";
$REPORTNUM = "%-20s %5d %8d\n";
printf ($REPORTFMT,"Message Status","Total","Size");
printf ("-----------------------------------\n");
printf ($REPORTNUM,"Received",$countsent,$totsent);
printf ($REPORTNUM,"Delivered",$countdelivered,$totdelivered);
printf ($REPORTNUM,"Deferred",$countdeferred);

printf ("\n\nUser Statistics:\n\n");
$REPORTFMT = "%-30s %6s %8s %7s %6s %8s %7s\n";
$REPORTNUM = "%-30s %6d %8d %6.2f%% %6d %8d %6.2f%%\n";
printf ($REPORTFMT,"Username","#from","size","%","#to","size","%");
printf ($REPORTFMT,"---------","------","--------","------","------","--------","------");
foreach $user (sort keys(%userlist)) {
    $percent1 = 0;
    $percent2 = 0;

    $percent1 = ($totsent{$user}/$totsent)*100              if ($totsent != 0);
    $percent2 = ($totdelivered{$user}/$totdelivered)*100    if ($totdelivered != 0);
    printf ($REPORTNUM,substr($user,0,30),
        $countsent{$user},$totsent{$user},$percent1,
        $countdelivered{$user},$totdelivered{$user},$percent2);
    $totpctsent += $percent1;
    $totpctdelivered += $percent2;
}
printf ("------------------------------------------------------------------------------\n");
printf ($REPORTNUM,"Totals",$countsent,$totsent,$totpctsent,$countdelivered,$totdelivered,$totpctdelivered);

# 
# Host statistics
foreach $host (sort keys(%hostlist)) {
    $totsent{$host} = 0;
    $totdelivered{$host} = 0;
    $countsent{$host} = 0;
    $countdelivered{$host} = 0;
    $countdeferred{$host} = 0;

    # Count total messages sent by each host
    $IDlist = $sent{$host};
    foreach $ID (split(/ /, $IDlist)) {
        $totsent{$host} += $size{$ID};
        $countsent{$host}++;
    }

    # Count total messages received by each host
    $IDlist = $delivered{$host};
    foreach $ID (split(/ /, $IDlist)) {
        $totdelivered{$host} += $size{$ID};
        $countdelivered{$host}++;
    }
}

printf ("\n\nHost Statistics:\n\n");
$REPORTFMT = "%-30s %6s %8s %7s %6s %8s %7s\n";
$REPORTNUM = "%-30s %6d %8d %6.2f%% %6d %8d %6.2f%%\n";
printf ($REPORTFMT,"Hostname","#from","size","%","#to","size","%");
printf ($REPORTFMT,"---------","------","--------","------","------","--------","------");
foreach $host (sort keys(%hostlist)) {
    $percent1 = 0;
    $percent2 = 0;

    $percent1 = ($totsent{$host}/$totsent)*100              if ($totsent != 0);
    $percent2 = ($totdelivered{$host}/$totdelivered)*100    if ($totdelivered != 0);
    printf ($REPORTNUM,substr($host,0,30),
        $countsent{$host},$totsent{$host},$percent1,
        $countdelivered{$host},$totdelivered{$host},$percent2);
}
printf ("------------------------------------------------------------------------------\n");
printf ($REPORTNUM,"Totals",$countsent,$totsent,$totpctsent,$countdelivered,$totdelivered,$totpctdelivered);

