#!/usr/bin/perl
#< Script to parse /var/log/maillog or equivalent and provide brief summary of outbound mail

# ToDo: Add hostname in header

use warnings;
use strict;

use Getopt::Long;

our $S_SUCCESS = "0";
our $S_ERROR = "1";

our $C_RESET = 0;
our $C_REFUSED = 0;
our $C_TIMED_OUT = 0;
our $C_OTHER = 0;

our $T_SENT = 0;
our $T_DEFERRED = 0;
our $T_OTHER = 0; 
our $T_LINECOUNT = 0;
our $T_USER = 0;
our $T_OUTSIDE_OTHER = 0;
our $T_TOTAL_OUT = 0;
our $T_SERVICE_UNAVAILABLE = 0;
our $T_HOST_UNKNOWN = 0;
our $T_LARGE_HEADERS = 0;

our $O_DEBUG = 0;
our $O_HELP = 0;
our $O_VERBOSE = 0;
our $O_FILE = "";

our @T_TOP = "";
our @T_BOTTOM = "";


sub display_help {
   my $thisprog = "";
   $thisprog = $0;
   $thisprog =~ s#^.*/##;
   if ( $O_DEBUG > 0 && $O_HELP == 0 ) {
      printf( "--[ DEBUG: thisprog ]--> %s\n", $thisprog );
   }
   printf( "Usage: %s [-dhv] [-f <input_file>]\n", $thisprog );
   printf( "           -d   Print debugging messages\n" );
   printf( "           -f   Specify path to input file\n" );
   printf( "           -h   Print this help message\n" );
   printf( "           -v   Run in verbose mode \n" );
}

sub process_arguments {
   GetOptions ( 'debug' => \$O_DEBUG, 
                'file=s' => \$O_FILE,
                'help' => \$O_HELP,
                'verbose+' => \$O_VERBOSE ) or $O_HELP++;
   if ( $O_HELP > 0 ) {
      display_help();
      exit $S_ERROR;
   }
}

sub process_line { 
   my $current_line = $_;
   my $i = 0;
   my @line_array;
   my $stat_text = "";
   my $dbg;
   if ( $_ =~ /stat=Headers too large/ ) {
      $T_TOTAL_OUT++;
      $T_LARGE_HEADERS++;
   } elsif ( $_ =~ /stat=/ ) {
      $T_TOTAL_OUT++;
      @line_array = split(/=/);
      $stat_text = $line_array[ 8 ];
      if ( $stat_text =~ /Sent/ ) {
         $T_SENT++;
      } elsif ( $stat_text =~ /Deferred/ ) {
         $T_DEFERRED++;
         if ( $stat_text =~ /Connection reset/ ) {
            $C_RESET++;
         } elsif ( $stat_text =~ /Connection refused/ ) {
            $C_REFUSED++;
         } elsif ( $stat_text =~ /Connection timed out/ ) {
            $C_TIMED_OUT++;
         } else {
            $C_OTHER++; 
         }
      } elsif ( $stat_text =~ /User unknown/ ) {
         $T_USER++;
      } elsif ( $stat_text =~ /Host unknown/ ) {
         $T_HOST_UNKNOWN++;
      } elsif ( $stat_text =~ /Service unavailable/ ) {
         $T_SERVICE_UNAVAILABLE++;
      } else {
         $T_OTHER++;
         if ( $O_DEBUG > 0 ) {
            printf( "--[ DEBUG: T_OTHER ]--> %s\n", $stat_text );
         }
      }
   } else {
      $T_OUTSIDE_OTHER++;
   }
}

sub print_summary {
   my $overall_other_total = 0;
   $overall_other_total = $T_OTHER + $T_OUTSIDE_OTHER;
   my $start_time = "";
   my $end_time = "";
   $start_time = sprintf( "%s %s %s", $T_TOP[0], $T_TOP[1], $T_TOP[2] );
   $end_time = sprintf( "%s %s %s", $T_BOTTOM[0], $T_BOTTOM[1], $T_BOTTOM[2] );
   printf( "%s\n", '='x50 );
   printf( "Maillog Report\n" );
   printf( "From: $start_time to $end_time\n" );
   printf( "%s\n\n", '='x50 );
   printf( "%s\n", '-'x50 );
   printf( "Overall Statistics\n" );
   printf( "%s\n\n", '-'x50 );
   printf( "Total Entries Parsed: $T_LINECOUNT\n" );
   printf( "Total Outbound Messages: $T_TOTAL_OUT\n" );
   printf( "Total Messages Sent: $T_SENT\n" );
   printf( "Total Messages Deferred: $T_DEFERRED\n" );
   printf( "Service Unavailable: $T_SERVICE_UNAVAILABLE\n" );
   printf( "Host Unknown: $T_HOST_UNKNOWN\n" );
   printf( "User Unknown: $T_USER\n" );
   printf( "Headers Too Large: $T_LARGE_HEADERS\n" );
   printf( "All Other Outbound Messages: $T_OTHER\n" );
   printf( "%s\n\n", '-'x50 );
   printf( "%s\n", '-'x50 );
   printf( "Deferred Messages\n" );
   printf( "%s\n\n", '-'x50 );
   printf( "Connection Refused: $C_REFUSED\n" );
   printf( "Connection Reset: $C_RESET\n" );
   printf( "Connection Timed Out: $C_TIMED_OUT\n" );
   printf( "Others: $C_OTHER\n" );
   printf( "%s\n\n", '-'x50 );
   printf( "%s\n", '-'x50 );
   printf( "Summary\n" );
   printf( "%s\n\n", '-'x50 );
   my $percentage_sent = 0;
   $percentage_sent = int ( ( $T_SENT / $T_TOTAL_OUT ) * 100 );
   printf( "Percentage of messages successfully sent: %d%%\n", $percentage_sent );
   my $percentage_deferred = 0;
   $percentage_deferred = int ( ( $T_DEFERRED / $T_TOTAL_OUT ) * 100 );
   printf( "Percentage of messages deferred: %d%%\n", $percentage_deferred );
   my $percentage_others = 0;
   $percentage_others = 100 - ( $percentage_sent + $percentage_deferred );
   printf( "Percentage of messages not deferred or sent: %d%%\n", $percentage_others );
   printf( "%s\n\n", '-'x50 );
}

#
# main()
#
process_arguments();
if ( "$O_FILE" eq "" ) {
   $O_FILE = "./maillog.tmp";  
}
if ( ! -e "$O_FILE" ) {
   printf( STDERR "Error: $O_FILE does not exist!\n" );
   exit $S_ERROR;
}
open( INFILE, "< $O_FILE" );
my $tmpline = "";
while( <INFILE> ) {
   process_line( $_ );
   $T_LINECOUNT++;
   $tmpline = $_; 
   if ( $T_LINECOUNT == 1 ) {
      @T_TOP = split( /\ +/, $tmpline );
   }
}
close( INFILE );
@T_BOTTOM = split( /\ +/, $tmpline );

print_summary();

exit $S_SUCCESS;