Blame scripts/services/spamassassin

Packit 57988d
#!/usr/bin/perl
Packit 57988d
##########################################################################
Packit 57988d
# $Id$
Packit 57988d
##########################################################################
Packit 57988d
# $Log: spamassassin,v $
Packit 57988d
# Revision 1.2  2008/06/30 20:47:20  kirk
Packit 57988d
# fixed copyright holders for files where I know who they should be
Packit 57988d
#
Packit 57988d
# Revision 1.1  2008/05/11 22:00:41  mike
Packit 57988d
# Inital check in of spamassassin files -mgt
Packit 57988d
#
Packit 57988d
# Revision 1.3  2007/10/10 16:41:27  whb
Packit 57988d
# Yes, Win does get over 10000 spam messages PER DAY
Packit 57988d
#
Packit 57988d
# Revision 1.2  2007/01/20 17:13:56  whb
Packit 57988d
# Lump together child-related errors
Packit 57988d
# - We're experiencing periods of high loads, causing many fork errors
Packit 57988d
#
Packit 57988d
# Revision 1.1  2006/09/16 20:02:01  whb
Packit 57988d
# Initial revision
Packit 57988d
#
Packit 57988d
#
Packit 57988d
#######################################################
Packit 57988d
### Copyright (c) 2008 Win Bent <whb@haus.org>
Packit 57988d
### Covered under the included MIT/X-Consortium License:
Packit 57988d
###    http://www.opensource.org/licenses/mit-license.php
Packit 57988d
### All modifications and contributions by other persons to
Packit 57988d
### this script are assumed to have been donated to the
Packit 57988d
### Logwatch project and thus assume the above copyright
Packit 57988d
### and licensing terms.  If you want to make contributions
Packit 57988d
### under your own copyright or a different license this
Packit 57988d
### must be explicitly stated in the contribution an the
Packit 57988d
### Logwatch project reserves the right to not accept such
Packit 57988d
### contributions.  If you have made significant
Packit 57988d
### contributions to this script and want to claim
Packit 57988d
### copyright please contact logwatch-devel@lists.sourceforge.net.
Packit 57988d
##########################################################
Packit 57988d
##########################################################################
Packit 57988d
Packit 57988d
use Logwatch ':sort';
Packit 57988d
Packit 57988d
my $Detail = $ENV{'LOGWATCH_DETAIL_LEVEL'} || 0;
Packit 57988d
my $Debug = $ENV{'LOGWATCH_DEBUG'} || 0;
Packit 57988d
my $Ignore_connections = $ENV{'ignore_connections'};
Packit 57988d
Packit 57988d
$StillRoot = 0;
Packit 57988d
$CleanTotal = 0;
Packit 57988d
$SpamTotal = 0;
Packit 57988d
$PyzorTerminated = 0;
Packit 57988d
Packit 57988d
my %Child;
Packit 57988d
my %Clean;
Packit 57988d
my %Spam;
Packit 57988d
my %Users;
Packit 57988d
my %Connections;
Packit 57988d
Packit 57988d
#Todo
Packit 57988d
#    meta test DIGEST_MULTIPLE has undefined dependency 'DCC_CHECK' : 2 Time(s)
Packit 57988d
#    server started on port 783/tcp (running version 3.1.9) : 2 Time(s)
Packit 57988d
#    meta test DIGEST_MULTIPLE has undefined dependency 'RAZOR2_CHECK' : 2 Time(s)
Packit 57988d
#    server hit by SIGHUP, restarting : 1 Time(s)
Packit 57988d
#    server killed by SIGTERM, shutting down : 1 Time(s)
Packit 57988d
#    meta test DIGEST_MULTIPLE has undefined dependency 'PYZOR_CHECK' : 1 Time(s)
Packit 57988d
#    meta test SARE_SPEC_PROLEO_M2a has dependency 'MIME_QP_LONG_LINE' with a zero score : 1 Time(s)
Packit 57988d
Packit 57988d
while (defined($ThisLine = <STDIN>)) {
Packit 57988d
   if ( # We don't care about these
Packit 57988d
      # Note that we DO care about "connection from" non-localhost
Packit 57988d
      ( $ThisLine =~ m/connection from localhost / ) or
Packit 57988d
      ( $ThisLine =~ m/setuid to / ) or
Packit 57988d
      ( $ThisLine =~ m/processing message / ) or
Packit 57988d
      ( $ThisLine =~ m/^spamd: result: .*,mid=\(unknown\)/ ) or
Packit 57988d
      ( $ThisLine =~ m/^prefork: child states: / ) or
Packit 57988d
      ( $ThisLine =~ m/^spamd: alarm *$/ ) or
Packit 57988d
      ( $ThisLine =~ m/^spamd: handled cleanup of child / ) or
Packit 57988d
      ( $ThisLine =~ m/^spamd: server successfully spawned child process, / ) or
Packit 57988d
      ( $ThisLine =~ m/^logger: removing stderr method/ ) or
Packit 57988d
      ( $ThisLine =~ m/^spamd: server pid:/ ) or
Packit 57988d
      ( $ThisLine =~ m/^prefork: adjust: \d+ idle children (less|more) than \d+ (min|max)imum idle children/ ) or
Packit 57988d
      # Sendmail messages to ignore
Packit 57988d
      ( $ThisLine =~ m/^AUTH=/ ) or
Packit 57988d
      ( $ThisLine =~ m/^STARTTLS/ ) or
Packit 57988d
      ( $ThisLine =~ m/^starting daemon \(/ ) or
Packit 57988d
      ( $ThisLine =~ m/^ruleset=trust_auth/ ) or
Packit 57988d
      ( $ThisLine =~ m/^ruleset=check_relay/ ) or
Packit 57988d
      0  # Always last in the list, so all above can say "or" at the end
Packit 57988d
   ) {
Packit 57988d
      ; # We don't care about these
Packit 57988d
   } elsif ( ($User) = ($ThisLine =~ m/clean message .* for (.+?):\d+ / )) {
Packit 57988d
      $Clean{ $User}++;
Packit 57988d
      $Users{ $User}++;
Packit 57988d
   } elsif ( ($User) = ($ThisLine =~ m/identified spam .* for (.+?):\d+ / )) {
Packit 57988d
      $Spam{ $User}++;
Packit 57988d
      $Users{ $User}++;
Packit 57988d
   } elsif ( $ThisLine =~ m/still running as root: / ) {
Packit 57988d
      $StillRoot++;
Packit 57988d
   } elsif ( $ThisLine =~ m/^spamd: connection from (.*) at port / ) {
Packit 57988d
      $Connections{$1}++;
Packit 57988d
   # These are caused by pyzor taking too long and being terminated
Packit 57988d
   } elsif ( $ThisLine =~ m/^pyzor:.* error: TERMINATED, signal 15/ ) {
Packit 57988d
      $PyzorTerminated++;
Packit 57988d
   } elsif ( $ThisLine =~ m/\bchild\b/ ) {
Packit 57988d
      chomp($ThisLine);
Packit 57988d
      # Many perl errors report pseudo-line-numbers, e.g.
Packit 57988d
      #   ... at /usr/bin/spamd line 1085, <GEN5490> line 212
Packit 57988d
      $ThisLine =~ s/\d+/___/g;  # Make all numbers "generic"
Packit 57988d
      $Child{ $ThisLine }++;        # ...and count generic error types
Packit 57988d
   } elsif ( ($spam, $score, $msgid) = ($ThisLine =~ m/^spamd: result: (.) (-?\d+).*,mid=<(.*)>/) ) {
Packit 57988d
      # Only record the first scan
Packit 57988d
      if (!defined($msg{$msgid}->{"score"}) and $spam eq "Y") {
Packit 57988d
         $msg{$msgid}->{"score"} = $score;
Packit 57988d
         $SpamRelay{$msg{$msgid}->{"relay"}}++;
Packit 57988d
      }
Packit 57988d
   } elsif ( $ThisLine =~ m/^\w+:/ ) {
Packit 57988d
      # Sendmail lines for statistics
Packit 57988d
      if ( ($from, $msgid, $relay) = ($ThisLine =~ m/^\w+: from=<(.*)>, .*, msgid=<(.*)>, .*, relay=(.*)/) ) {
Packit 57988d
         $msg{$msgid}->{"from"} = $from;
Packit 57988d
         $msg{$msgid}->{"relay"} = $relay;
Packit 57988d
      }
Packit 57988d
Packit 57988d
   # EVERYTHING ELSE, or, Incentive to identify all "We don't care" lines
Packit 57988d
   # We on-purpose allow warnings about --max-children to go here
Packit 57988d
   } else {
Packit 57988d
      chomp($ThisLine);
Packit 57988d
      # Report any unmatched entries...
Packit 57988d
      $OtherList{$ThisLine}++;
Packit 57988d
   }
Packit 57988d
}
Packit 57988d
Packit 57988d
#######################################################
Packit 57988d
Packit 57988d
#XX print "# Detail:${Detail}\n"; #XX debugging
Packit 57988d
Packit 57988d
if ( keys %Users ) {
Packit 57988d
   my ($u, $cl, $sp);
Packit 57988d
   print "\nMail Recipients:\n";
Packit 57988d
   # Some might want to limit this output based on $Detail, but we want it all!
Packit 57988d
   foreach $u (sort {$a cmp $b} keys %Users) {
Packit 57988d
      $cl = 0 + $Clean{$u};   # Avoid "undefined" error
Packit 57988d
      $sp = 0 + $Spam{$u};    # Avoid "undefined" error
Packit 57988d
      $CleanTotal += $cl;
Packit 57988d
      $SpamTotal += $sp;
Packit 57988d
      #OLD: If one user gets over 9999 messages, you have our sympathies
Packit 57988d
      #NOW: If one user gets over 99999 messages, you have our sympathies
Packit 57988d
      printf "   %-8s : %4d clean, %5d spam\n", $u, $cl, $sp;
Packit 57988d
   }
Packit 57988d
}
Packit 57988d
Packit 57988d
if ( $CleanTotal || $SpamTotal ) {
Packit 57988d
   my $ttotal = $CleanTotal + $SpamTotal;
Packit 57988d
   print "\nSummary:\n";
Packit 57988d
   printf "\tTotal Clean: %5d (%3d%%)\n", $CleanTotal,
Packit 57988d
      int ((100.0 * $CleanTotal / $ttotal) + 0.5);
Packit 57988d
   printf "\tTotal Spam:  %5d (%3d%%)\n", $SpamTotal,
Packit 57988d
      int ((100.0 * $SpamTotal / $ttotal) + 0.5);
Packit 57988d
}
Packit 57988d
Packit 57988d
if (keys %SpamRelay) {
Packit 57988d
   print "\nTop 10 Spam Relays:\n";
Packit 57988d
   $i = 0;
Packit 57988d
   foreach $relay (sort {$SpamRelay{$b}<=>$SpamRelay{$a} } keys %SpamRelay) {
Packit 57988d
      print "   $relay: $SpamRelay{$relay} Time(s)\n";
Packit 57988d
      last if ++$i == 10;
Packit 57988d
   }
Packit 57988d
}
Packit 57988d
   
Packit 57988d
if ( $StillRoot ) {
Packit 57988d
   print qq{\n"still running as root" error: $StillRoot time(s)\n};
Packit 57988d
}
Packit 57988d
Packit 57988d
if (keys %Child) {
Packit 57988d
   print "\nChild-related errors\n";
Packit 57988d
   foreach $line (sort {$Child{$b}<=>$Child{$a} } keys %Child) {
Packit 57988d
      print "   $line: $Child{$line} Time(s)\n";
Packit 57988d
   }
Packit 57988d
}
Packit 57988d
Packit 57988d
if (keys %Connections) {
Packit 57988d
   my $header_printed = 0;
Packit 57988d
   foreach my $connection ( sort {$a cmp $b} keys %Connections ) {
Packit 57988d
      if ($Ignore_connections && $connection =~ /$Ignore_connections/) { next; }
Packit 57988d
      if (!$header_printed) {
Packit 57988d
         print "\nConnections from:\n";
Packit 57988d
         $header_printed = 1;
Packit 57988d
      }
Packit 57988d
      print "   $connection : $Connections{$connection} Time(s)\n";
Packit 57988d
   }
Packit 57988d
}
Packit 57988d
Packit 57988d
if ( $PyzorTerminated) {
Packit 57988d
   print "\nPyzor TERMINATED errors: $PyzorTerminated time(s)\n";
Packit 57988d
}
Packit 57988d
Packit 57988d
if (keys %OtherList) {
Packit 57988d
   print "\n**Unmatched Entries**\n";
Packit 57988d
   foreach $line (sort {$OtherList{$b}<=>$OtherList{$a} } keys %OtherList) {
Packit 57988d
      print "   $line: $OtherList{$line} Time(s)\n";
Packit 57988d
   }
Packit 57988d
}
Packit 57988d
Packit 57988d
exit(0);
Packit 57988d
Packit 57988d
# vi: shiftwidth=3 tabstop=3 syntax=perl et
Packit 57988d
# Local Variables:
Packit 57988d
# mode: perl
Packit 57988d
# perl-indent-level: 3
Packit 57988d
# indent-tabs-mode: nil
Packit 57988d
# End: