#!/usr/bin/perl -w
##########################################################################
# $Id: postfix,v 1.4 2003/11/26 14:36:30 kirk Exp $
##########################################################################
# $Log: postfix,v $
# Revision 1.4  2003/11/26 14:36:30  kirk
# Applied patch from blues@ds.pg.gda.pl
#
# Revision 1.3  2003/11/18 14:04:05  kirk
# More patches from blues@ds.pg.gda.pl
#
# Revision 1.2  2003/11/18 04:02:21  kirk
# Patch from blues@ds.pg.gda.pl
#
# Revision 1.1  2003/11/03 04:49:18  kirk
# Added postfix filter from Sven Conrad <sconrad@receptec.net>
#
# Revision 1.1  2002/03/29 15:32:14  kirk
# Added some filters found in RH's release
#
#
# Revision ???  2000/07/12 Simon Liddington <sjl@zepler.org>
# converted from sendmail to postfix Sven Conrad <scon@gmx.net>
# added unknown users
# added relay denials
# todo:
# add authentication warnings
# add forward errors
# add returns after 4 hours
# ignores alias database building
# ignores daemon start messages
# ignores clone messages
# ignores all to= lines whatever follows stat=
#
#
# Revision 1.1  2003/03/21 21:10  sven
# Initial revision
#
# filters all postfix/<process> messages
#
##########################################################################

########################################################
# This was written and is maintained by:
#    ??? Kenneth Porter <shiva@well.com> ???
#    changed by Sven Conrad <scon@gmx.net>
#
# Please send all comments, suggestions, bug reports,
#    etc, to ?? shiva@well.com.??
#    Sven Conrad <scon@gmx.net>
#
########################################################

$MsgsSent = 0;
$BytesTransferred = 0;
$FourHourReturns = 0;
$ReturnedToSender = 0;

while (defined($ThisLine = <STDIN>)) {
	if ( ( $ThisLine =~ m/^connect/ ) or 
		( $ThisLine =~ m/^disconnect/ ) or 
		( $ThisLine =~ m/^reload configuration/ ) or 
		( $ThisLine =~ m/^[a-zA-Z0-9]+: client/ ) or 
		( $ThisLine =~ m/^[a-zA-Z0-9]+: message-id/ ) or
		( $ThisLine =~ m/^[a-zA-Z0-9]+: skipped, still being delivered/ ) or
		( $ThisLine =~ m/^warning: [\.0-9]+: address not listed for hostname/ ) or
		( $ThisLine =~ m/^[a-zA-Z0-9]+: to\=\<.*>, relay\=.*, delay\=[0-9]+, status\=[sent|deferred]/ ) or
		( $ThisLine =~ m/^warning: [\.0-9]+: hostname .* verification failed: Host not found/ ) or
		( $ThisLine =~ m/^warning: no MX host for .* has a valid A record$/ ) or
		( $ThisLine =~ m/^warning: numeric domain name in resource data of MX record for .*$/ ) or
		( $ThisLine =~ m/^daemon started$/ ) or
		( $ThisLine =~ m/^terminating on signal 15$/ )
	) {
		# We don't care about these
	}
	elsif ( ($Bytes) = ($ThisLine =~ /^[a-zA-Z0-9]+: from=.*size=([0-9]+).*$/) ) {
		$MsgsSent++;
		$BytesTransferred += $Bytes;
    }
    elsif (($User) = ($ThisLine =~ /^[a-zA-Z0-9]+: to\=\<([^ ]*)>, relay\=local, delay\=[0-9]+, status\=bounced \(unknown user/)) {
		# unknown user
		$UnknownUsers{$User}++;
    }
    elsif (($Dest, $Relay, $Msg) = ($ThisLine =~ /^[a-zA-Z0-9]+: to\=\<([^ ]*)>, relay=([^ ]*).*, delay\=[0-9]+, status\=bounced \(([^)]*)/ )) {
		# unknown user
		# $Msg = " hello "
		# print "bounce message from " . $Dest . " msg : " . $Relay . "\n";
		if ($Relay =~ m/^[none|local|avcheck]/) {
			$Temp = "To " . $Dest . " Msg=\"" . $Msg . "\"";
			$LocalBounce{$Temp}++;				
		} else {
			$Temp = "To " . $Dest . " Msg=\"" . $Msg . "\"";
			$ForeignBounce{$Temp}++;
		}
	}
	elsif ( ($Relay,$Dest) = ($ThisLine =~ m/^reject: RCPT from ([^ ]*): 554 <([^ ]*)>.* Relay access denied.* to=([^ ]*)/) ) {
		# print "reject: " . $ThisLine . "\n";
		# print "Relay :" . $Relay . " to " . $Dest . "\n";
		$Temp = "From " . $Relay . " to " . $Dest;
		$RelayDenied{$Temp}++;
    }
    elsif ( ($User,$From) = ($ThisLine =~ /^[a-zA-Z0-9]+: uid=([^ ]*) from=\<([^ ]*)>/)) {
		#Messages sent by user
		$Temp = $From . " (uid=" . $User . "): ";
		$SentBy{$Temp}++;
	}
	elsif ( ($From) = ($ThisLine =~ /^[a-zA-Z0-9]+: from=<([^ ]*)>, status=expired, returned to sender$/)) {
		$ReturnedToSender++;
	}
	elsif ( ($Command,$Host) = ($ThisLine =~ /^lost connection after ([^ ]*) from ([^ ]*)$/)) {
		# Make some better summary with hosts
		$ConnectionLost{$Command}++;
	}
	elsif ( ($Command,$Host) = ($ThisLine =~ /^timeout after ([^ ]*) from ([^ ]*)$/)) {
		# Make some better summary with hosts
		$ConnectionLost{$Command}++;
	}
	elsif ( ($Rejected,undef,undef) = ($ThisLine =~ /^^[a-zA-Z0-9]+: reject: header (.*); from=<([^ ]*)> to=<([^ ]*)>: Message content rejected$/)) {
		$HeaderReject{$Rejected}++;
	}
#    elsif ( ($Warning)  = ($ThisLine =~ /^[a-zA-Z0-9]+: Authentication-Warning: [^ ]+: ([^ ]+ set sender to [^ ]+ using -f)/) ) {
#        $AuthWarns{$Warning}++;
#    }
#    elsif ( ($Forward,$Error) = ($ThisLine =~ /^[a-zA-Z0-9]+: forward ([^ ]*): transient error: (.*)$/) ) {
#        $Temp = $Forward . ": " . $Error;
#        $ForwardErrors{$Temp}++;
#    }
#    elsif ( ($Temp) = ($ThisLine =~ /^[a-zA-Z0-9]+: forward ([^ ]*: Permission denied)/) ) {
#        $ForwardErrors{$Temp}++;
#    }
#    elsif ( $ThisLine =~ m/^[a-zA-Z0-9]+: [a-zA-Z0-9]+: return to sender: Warning: could not send message for past 4 hours/ ) {
#        $FourHourReturns++;
#    }
    else {
	push @OtherList,$ThisLine;
    }
}

if ((@OtherList) or
	($MsgsSent > 0) or
	($FourHourReturns > 0) or
	($ReturnedToSender >0) or
	(keys %UnknownUsers) or
	(keys %RelayDenied) or
	(keys %$HeaderReject) or
	(keys %ForeignBounce) or
	(keys %LocalBounce) or
	(keys %AuthWarns) or
	(keys %ForwardErrors) or
	(keys %SentBy) or
	(keys %ConnectionLost)
) {
	print "\n\n --------------------- postfix Begin ------------------------ ";
	
    if($MsgsSent > 0) {
        print "\n\n" . $BytesTransferred . " bytes transferred";
        print "\n" . $MsgsSent . " messages sent";
    }

    if($FourHourReturns > 0) {
        print "\n\n" . $FourHourReturns . " messages returned after 4 hours";
    }

	if ($ReturnedToSender >0) {
		print "\n\n" . $ReturnedToSender . " messages expired and returned to sender";
	}

	if (keys %SentBy) {
		print "\n\nMessages sent by:\n";
		foreach $ThisOne (keys %SentBy) {
			print "    " . $ThisOne . $SentBy{$ThisOne} . " Times(s)\n";
		}
	}

    if (keys %UnknownUsers) {
		print "\n\nUnknown users:\n";
		foreach $ThisOne (keys %UnknownUsers) {
			print "    " . $ThisOne . ": " . $UnknownUsers{$ThisOne} . " Times(s)\n";
		}
	}

    if (keys %RelayDenied) {
		print "\n\nRelaying denied:\n";
		foreach $ThisOne (keys %RelayDenied) {
			print "    " . $ThisOne . ": " . $RelayDenied{$ThisOne} . " Times(s)\n";
		}
    }

    if (keys %LocalBounce) {
		print "\n\nLocal Bounce:\n";
		foreach $ThisOne (keys %LocalBounce) {
			print "    " . $ThisOne . ": " . $LocalBounce{$ThisOne} . " Times(s)\n";
		}
    }

    if (keys %ForeignBounce) {
		print "\n\nForeign Bounce:\n";
		foreach $ThisOne (keys %ForeignBounce) {
			print "    " . $ThisOne . ": " . $ForeignBounce{$ThisOne} . " Times(s)\n";
		}
    }

	if (keys %HeaderReject) {
		print "\n\nHeader content reject:\n";
		foreach $ThisOne (keys %HeaderReject) {
			print "    " . $ThisOne . ": " . $HeaderReject{$ThisOne} . " Times(s)\n";
		}
	}

    if (keys %AuthWarns) {
		print "\n\nAuthentication warnings:\n";
		foreach $ThisOne (keys %AuthWarns) {
			print "    " . $ThisOne . ": " . $AuthWarns{$ThisOne} . " Times(s)\n";
		}
    }

    if (keys %ForwardErrors) {
		print "\n\nForwarding errors:\n";
		foreach $ThisOne (keys %ForwardErrors) {
			print "    " . $ThisOne . ": " . $ForwardErrors{$ThisOne} . " Times(s)\n";
		}
	}

	if (keys %ConnectionLost) {
		print "\n\nConnections lost:\n";
		foreach $ThisOne (keys %ConnectionLost) {
			print "    Connection lost after command " . $ThisOne . ": " . $ConnectionLost{$ThisOne} . " Times(s)\n";
		}
	}
	
    if ($#OtherList >= 0) {
		print "\n\n**Unmatched Entries**\n\n";
		print @OtherList;
	}
	
    print "\n ---------------------- postfix End ------------------------- \n";

}

exit(0);


# vi: shiftwidth=4 tabstop=4
