1 2######################################################## 3# Please file all bug reports, patches, and feature 4# requests under: 5# https://sourceforge.net/p/logwatch/_list/tickets 6# Help requests and discusion can be filed under: 7# https://sourceforge.net/p/logwatch/discussion/ 8######################################################## 9 10######################################################## 11# Originally written by: 12# Dariusz Nierada <dnierada@kat.supermedia.pl> 13######################################################## 14 15######################################################## 16# Default Detail Levels: 17# 0: Prints MisFormatted log lines (should never happen) 18# Virus/Malware blocks (if AntiVirus configured) 19# Prints protocol violations (by category) 20# Prints address verification rejections 21# Prints administrative rejections (by category) 22# Prints Refused Relay count 23# 24# 5: Prints Queue Run count 25# Prints server Stop/Start 26# 27# 10: Prints Refused Relay (individual lines) 28# Prints Per Message Tracking 29######################################################## 30 31######################################################## 32## Copyright (c) 2008 Gary Allen Vollink 33## Covered under the included MIT/X-Consortium License: 34## http://www.opensource.org/licenses/mit-license.php 35## All modifications and contributions by other persons to 36## this script are assumed to have been donated to the 37## Logwatch project and thus assume the above copyright 38## and licensing terms. If you want to make contributions 39## under your own copyright or a different license this 40## must be explicitly stated in the contribution an the 41## Logwatch project reserves the right to not accept such 42## contributions. If you have made significant 43## contributions to this script and want to claim 44## copyright please contact logwatch-devel@lists.sourceforge.net. 45######################################################### 46 47use Logwatch ':dates'; 48use warnings; 49 50$Detail = $ENV{'LOGWATCH_DETAIL_LEVEL'} || 0; 51 52$LvlBadFormat = $ENV{'exim_misformat'} || 0; 53$LvlRestarts = $ENV{'exim_restart'} || 5; 54$LvlVirus = $ENV{'exim_virus'} || 0; 55$LvlProtocol = $ENV{'exim_protocol'} || 0; 56$LvlProtocolLines = $ENV{'exim_protocol_lines'}|| 5; 57$LvlDontAccept = $ENV{'exim_dontaccept'} || 0; 58$LvlDontAcceptLines = $ENV{'exim_dontaccept_lines'} || 0; 59$LvlVerify = $ENV{'exim_verify'} || 0; 60$LvlVerifyLines = $ENV{'exim_verify_lines'} || 5; 61$LvlRuns = $ENV{'exim_runs'} || 5; 62$LvlRelay = $ENV{'exim_relay'} || 0; 63$LvlRelayLines = $ENV{'exim_relay_lines'} || 10; 64$LvlMsgs = $ENV{'exim_mesgs'} || 10; 65 66# procedura sortujaca tak jak ja chce (bo tamta sotrowala po ASCII) 67# procedure to compare numbers at the beginning of submitted strings. 68# .. Which in this case is the message count for a given message ID. 69sub wedlug_liczb { 70 ($aa) = ($a =~ /^(\d+).+/); 71 ($bb) = ($b =~ /^(\d+).+/); 72 $aa <=> $bb; 73} 74 75# START 76 77my $SearchDate = TimeFilter("%Y-%m-%d %H:%M:%S"); 78$StartQueue = 0; 79$EndQueue = 0; 80 81# Regex to match IPv4 addresses and IPv6 addresses 82# IPv6 part could be made more strict 83my $IPAddress = qr/\d+\.\d+\.\d+\.\d+|[a-fA-F0-9]*:[a-fA-F0-9:]+/; 84 85my $MatchedDate = 0; 86 87while (defined($ThisLine = <STDIN>)) { 88 chomp($ThisLine); 89 # pobierz dzisiejsza date z 2002-03-31 22:13:48 ... 90 # Collect this line's date, e.g. 2002-03-31 22:13:48 ... 91 do { 92 if ( $ThisLine =~ /^ Suggested action: use keep_environment./ ) { 93 $KeepEnv++ if $MatchedDate; 94 next; 95 } 96 $BadFormat{$ThisLine}++; 97 next; 98 } unless ($year1,$month1,$day1,$h1,$m1,$s1) = ($ThisLine =~ /^(\d+)\-(\d+)\-(\d+)\s(\d+):(\d+):(\d+)\s.+/); 99 100 unless ($ThisLine =~ /^$SearchDate /o) { 101 $MatchedDate = 0; 102 next; 103 } 104 $MatchedDate = 1; 105 106 if ( $ThisLine =~ /End queue run\:/ ) { 107 $EndQueue++; 108 } 109 elsif ( $ThisLine =~ /Start queue run\:/ ) { 110 $StartQueue++; 111 } 112 elsif ( $ThisLine =~ /sender verify defer/ ) { 113 # ignore this; it's temporary 114 } 115 elsif ( $ThisLine =~ /unknown variable name/ ) { 116 # ignore this temporarily 117 } 118 elsif ( $ThisLine =~ /ignoring AUTH=.*? \(client not authenticated\)/ ) { 119 # ignore this; it is a warning. 120 } 121 elsif ( $ThisLine =~ /cwd=.*? \d args: / ) { 122 # ignore this; it is exim (or an Exim sub-command) starting. 123 } 124 elsif ( $ThisLine =~ /[Rr]ecipient verify fail/ ) { 125 $RecipVerify{$ThisLine}++; 126 } 127 elsif ( $ThisLine =~ /[Ss]ender verify fail/ ) { 128 $SendVerify{$ThisLine}++; 129 } 130 elsif ( $ThisLine =~ /Warning: purging the environment./ ) { 131 $Purging++; 132 } 133 elsif ( $ThisLine =~ /fragments administratively prohib/ ) { 134 $DontAccept{$ThisLine}++; 135 } 136 elsif ( $ThisLine =~ /unqualified (sender|recipient) rejected/ ) { 137 $DontAccept{$ThisLine}++; 138 } 139 elsif ( $ThisLine =~ /do not accept mail / ) { 140 $DontAccept{$ThisLine}++; 141 } 142 elsif ( $ThisLine =~ /rejected connection in .connect. ACL/ ) { 143 # Likely policy rejections 144 $DontAccept{$ThisLine}++; 145 } 146 elsif ( $ThisLine =~ /believed to be spam/ ) { 147 $DontAccept{$ThisLine}++; 148 } 149 elsif ( $ThisLine =~ /[Ww]arning: dnsbl\.sorbs\.net/ ) { 150 $DontAccept{$ThisLine}++; 151 } 152 elsif ( $ThisLine =~ /mail not permitted from/ ) { 153 $DontAccept{$ThisLine}++; 154 } 155 elsif ( $ThisLine =~ /file, which is blacklisted/ ) { 156 $DontAccept{$ThisLine}++; 157 } 158 elsif ( $ThisLine =~ /not accept Windows executables/ ) { 159 $DontAccept{$ThisLine}++; 160 } 161 elsif ( $ThisLine =~ /remote host address is the local host/ ) { 162 $DontAccept{$ThisLine}++; 163 } 164 elsif ( $ThisLine =~ /message contains malware/ ) { 165 # Exim <= 4.44 with ExiScan-ACL Patch (Running AntiVirus Software) 166 $Virus{$ThisLine}++; 167 } 168 elsif ( $ThisLine =~ /message contains a [vV]irus/ ) { 169 # Exim >= 4.50 compiled with WITH_CONTENT_SCAN=yes (Running AntiVirus Software) 170 $Virus{$ThisLine}++; 171 } 172 elsif ( $ThisLine =~ /SMTP connection from/ ) { 173 # Common error from SPAM hosts. 174 $Proto{$ThisLine}++; 175 } 176 elsif ( $ThisLine =~ /SMTP syntax error in/ ) { 177 # Common error from SPAM hosts. 178 $Proto{$ThisLine}++; 179 } 180 elsif ( $ThisLine =~ /remote host used my name in HELO/ ) { 181 # Common error from SPAM hosts. 182 $Proto{$ThisLine}++; 183 } 184 elsif ( $ThisLine =~ /remote host used IP address in HELO/ ) { 185 # Common error from SPAM hosts. 186 $Proto{$ThisLine}++; 187 } 188 elsif ( $ThisLine =~ /unexpected disconnection while reading SMTP command/ ) { 189 # Common error from SPAM hosts. 190 $Proto{$ThisLine}++; 191 } 192 elsif ( $ThisLine =~ /SMTP protocol violation/ ) { 193 # Common error from SPAM hosts. 194 $Proto{$ThisLine}++; 195 } 196 elsif ( $ThisLine =~ /SMTP command timeout/ ) { 197 # Common error from SPAM hosts. 198 $Proto{$ThisLine}++; 199 } 200 elsif ( $ThisLine =~ /SMTP data timeout/ ) { 201 # Common error from SPAM hosts. 202 $Proto{$ThisLine}++; 203 } 204 elsif ( $ThisLine =~ /incomplete transaction \(([\s\w]+)\) from/ ) { 205 # Common error from SPAM hosts (after recipient reject/callout). 206 $Proto{$ThisLine}++; 207 } 208 elsif ( $ThisLine =~ /SMTP protocol synchronization error \(([\s\w:]+)\):/ ) { 209 # Spammer who does not wait before sending crap 210 $Proto{$ThisLine}++; 211 } 212 elsif ( $ThisLine =~ /dropped: too many nonmail commands/ ) { 213 # Often someone who tries lots of transactions 214 $Proto{$ThisLine}++; 215 } 216 elsif ( $ThisLine =~ /dropped: too many syntax or protocol errors/ ) { 217 # Often someone who tries lots of transactions 218 $Proto{$ThisLine}++; 219 } 220 elsif ( $ThisLine =~ /SMTP protocol error in \"[^\"]+\"/ ) { 221 # Some hosts ask for TLS even when not offered (generalised to all cmds) 222 $Proto{$ThisLine}++; 223 } 224 elsif ( $ThisLine =~ /TLS error on connection from (\S+) \(([^)]*)\) \[(\S+)\]:(\d+) I=\[(\S+)\]:(\d+) \(send\): Error in the push function\./ ) { 225 # Ignore this, office 365 connector early disconnect. 226 } 227 elsif ( $ThisLine =~ /authenticator failed for/ ) { 228 $Proto{$ThisLine}++; 229 } 230 elsif ( $ThisLine =~ /Connection from .* too many connections from that IP address/ ) { 231 # Some hosts make lots of simultaneous connections 232 # this is an extra error message when logging is high 233 # and since another message duplicates it, we can just ignore this 234 } 235 elsif ( $ThisLine =~ /rejected [HE][EH]LO from\s/ ) { 236 # Typically due to underscores _ in the HELO line 237 # (a common protocol violation) 238 # Also can be due to odd escape sequences 239 # (never seen from a valid MX) 240 $Proto{$ThisLine}++; 241 } 242 elsif ( $ThisLine =~ /SIGHUP received\: re-exec/ ) { 243 push @Restart, "$year1-$month1-$day1 $h1:$m1:$s1 (stop)"; 244 } 245 elsif ( $ThisLine =~ /daemon started\:/ ) { 246 push @Restart, "$year1-$month1-$day1 $h1:$m1:$s1 (start)"; 247 } 248 elsif ( $ThisLine =~ /rejected RCPT.*greylist/) { 249 $Greylist++; 250 push @GreylistH, $ThisLine; 251 } 252 elsif ( $ThisLine =~ /refused relay/ || $ThisLine =~ /rejected RCPT/ ) { 253 $Relay++; 254 push @RelayH, $ThisLine; 255 } 256 elsif ( $ThisLine =~ /no host name found for IP address/ ) { 257 $ReverseLookup++; 258 push @ReverseLookupH, $ThisLine; 259 } 260 elsif ( $ThisLine =~ /no IP address found for host/ ) { 261 $Lookup++; 262 push @LookupH, $ThisLine; 263 } 264 elsif ( $ThisLine =~ /DKIM: .* \[verification succeeded\]/ ) { 265 # Ignore successful DKIM verification reports 266 # http://www.exim.org/exim-html-current/doc/html/spec_html/ch-support_for_dkim_domainkeys_identified_mail.html 267 } 268 elsif ( $ThisLine =~ /^\d+\-\d+\-\d+\s\d+\:\d+\:\d+\s(\+\d+\s)?\w+\-\w+\-\w+\s/ ) { # inne wiadomosci przesylane przez EXIMA 269 # Collect Message ID specific notes... 270 ($mdate,$mtime,$mid,$mrest) = ($ThisLine =~ /^(\d+\-\d+\-\d+)\s(\d+\:\d+\:\d+)\s(?:\+\d+\s)?(\w+\-\w+\-\w+)(.+)/); 271 # Count of individual Message Lines, used for sort 272 $licze++; # Dodaje taki licznik aby potem przy wypisaniu posortowac po nim, bo wypisywal nie po kolei 273 $mmsg{$mid}{$licze.$mrest} = "$mdate $mtime"; 274 275 } 276 else 277 { 278 $OtherList{$ThisLine}++; 279 } 280} #end while 281 282# Print MisFormatted log lines (should never happen) 283if ($Detail >= $LvlBadFormat) { 284 if (%BadFormat) { 285 print "\n***** BAD FORMAT (Possible data corruption or Exim bug) *****\n"; 286 foreach $ThisOne (keys %BadFormat) { 287 print "$ThisOne\n"; 288 } 289 } 290} 291 292# Print server Stops/Starts 293if ($Detail >= $LvlRestarts) { 294 if (@Restart) { 295 print "\n--- Exim Restarted ---\n"; 296 foreach $ThisOne (sort @Restart) { 297 print " $ThisOne\n"; 298 } 299 } 300} 301 302if ($Purging) { 303 print " Warning: purging the environment. : $Purging Time(s)\n"; 304} 305if ($KeepEnv) { 306 print " ... Suggested action: use keep_environment. : $KeepEnv Time(s)\n"; 307} 308 309if ($Detail >= $LvlRuns) { 310 if (($StartQueue >0 ) or ($EndQueue > 0)) { 311 print "\n--- Queue Runners ---\n"; 312 # Start Queue 313 $StartQueue and print " Start queue run: $StartQueue Time(s)\n"; 314 # End Queue 315 $EndQueue and print " End queue run: $EndQueue Time(s)\n"; 316 } 317} 318 319if ($Detail >= $LvlVerify) { 320 if ((@SendVerify) and (@RecipVerify)) { 321 print "\n--- Address Verification ---\n"; 322 } 323 if (@SendVerify) { 324 # Sender Verifies 325 $SendVerify and print "\nSender Verify failures: $SendVerify Time(s)\n"; 326 327 if ($Detail >= $LvlVerifyLines) { 328 foreach $ThisOne (@SendVerify) { 329 print " $ThisOne\n"; 330 } 331 } 332 } 333 if (@RecipVerify) { 334 # Recip Verifies 335 $RecipVerify and print "Recipient Verify failures: $RecipVerify Time(s)\n"; 336 337 if ($Detail >= $LvlVerifyLines) { 338 foreach $ThisOne (@RecipVerify) { 339 print " $ThisOne\n"; 340 } 341 } 342 } 343} 344 345if ($Detail >= $LvlRelay) { 346 if (@GreylistH) { 347 348 print "\n--- Greylisted $Greylist times\n"; 349 350 if ( $Detail >= $LvlRelayLines ) { 351 print "--- Lines follow:\n\n"; 352 353 foreach $ThisOne (@GreylistH) { 354 print "$ThisOne\n"; 355 } 356 } 357 } 358 if (@RelayH) { 359 360 print "\n--- Refused Relays $Relay times\n"; 361 362 if ( $Detail >= $LvlRelayLines ) { 363 print "--- Lines follow:\n\n"; 364 365 foreach $ThisOne (@RelayH) { 366 print "$ThisOne\n"; 367 } 368 } 369 } 370} 371 372if ($Detail >= $LvlVirus) { 373 # Print Blocked Viruses/Malware 374 if (%Virus) { 375 my (%vir); 376 print "\n--- Virus/Malware Blocked ---\n"; 377 foreach $ThisOne (sort(keys %Virus)) { 378 # Need mid empty... 379 $mid = ""; 380 # Virus name holder... 381 $cc = ""; 382 # Extract exim date and time string... 383 ($mdate, $mtime) = ($ThisOne =~ m/^(\d+-\d+-\d+)\s(\d+\:\d+\:\d+)\s/); 384 # Link date and time (looks cleaner)... 385 $aa = "$mdate $mtime"; 386 # Extract the REAL IP address... 387 ($bb) = ($ThisOne =~ m/\s\[($IPAddress)\][\s:]/); 388 # Exim >= 4.50 compiled with, WITH_CONTENT_SCAN=yes 389 # Default warning looks like this... 390 # rejected after DATA: This message contains a [vV]irus (%s). 391 if ($ThisOne =~ m/virus \((.*?)\)/) { 392 $cc = $1; 393 } 394 # Exim <= 4.44 with ExiScan-ACL patch 395 # rejected after DATA: This message contains malware (%s) 396 elsif ($ThisOne =~ m/malware \((.*?)\)/) { 397 $cc = $1; 398 } 399 # There is probably a more graceful way to do this... 400 if (defined( $vir{$cc} )) { 401 # Assign current value to temporary (mid) 402 $mid = $vir{$cc}; 403 } 404 # Set current value to (old value)+new value+',' 405 $vir{$cc} = "$mid$aa : IP:$bb,"; 406 } 407 # Print the results... 408 foreach $ThisOne (sort(keys %vir)) { 409 print "Virus: [$ThisOne]\n"; 410 foreach $aa ( sort( split /,/, $vir{$ThisOne} )) { 411 print " $aa\n"; 412 } 413 } 414 } 415} 416 417if ($Detail >= $LvlDontAccept) { 418 # Print Administrative Prohibitions 419 if (%DontAccept) { 420 my (%spam, %detail); 421 my (@errList); 422 423 # Probable SPAM hosts... 424 print "\n--- Admin Policy Blocking ---\n"; 425 foreach $ThisOne (sort(keys %DontAccept)) { 426 # We need this blank. 427 $mid = ""; 428 # IP address/current issue holder. 429 $bb = ""; 430 # Extract exim date and time string... 431 ($mdate, $mtime) = ($ThisOne =~ m/^(\d+-\d+-\d+)\s(\d+\:\d+\:\d+)\s/); 432 # Link date and time (looks cleaner)... 433 $aa = "$mdate $mtime"; 434 435 if ( $ThisOne =~ m/do not accept mail from ([\w\*-._]+)@([\w.-_]+)/ ) { 436 $cc = "Blocked Email Domain"; 437 $bb = "$1\@$2"; 438 } 439 elsif ( $ThisOne =~ m/rejected connection in .connect. ACL/ ) { 440 $cc = "Blocked Host"; 441 ( $bb ) = ($ThisOne =~ m/\[(\d+\.\d+\.\d+\.\d+)\]/); 442 } 443 elsif ( $ThisOne =~ m/mail not permitted from sender ([\w\*-_.]+)@([\w.-_]+)/ ) { 444 $cc = "Blocked Email Address"; 445 $bb = "$1\@$2"; 446 } 447 elsif ( $ThisOne =~ m/contains attached ".(.*)" file, which is blacklisted/ ) { 448 $cc = "Blocked Attachment"; 449 ( $bb ) = ($ThisOne =~ m/\[($IPAddress)\]/); 450 } 451 elsif ( $ThisOne =~ /believed to be spam/ ) { 452 $cc = "Blocked Fragmented Message"; 453 ( $bb ) = ($ThisOne =~ m/\[($IPAddress)\]/); 454 } 455 elsif ( $ThisOne =~ /[Ww]arning: dnsbl\.sorbs\.net/ ) { 456 $cc = "Blocked by DNSBL (SORBS)"; 457 ( $bb ) = ($ThisOne =~ m/\[($IPAddress)\]/); 458 } 459 elsif ( $ThisOne =~ /fragments administratively prohibited/ ) { 460 $cc = "Blocked Fragmented Message"; 461 ( $bb ) = ($ThisOne =~ m/\[($IPAddress)\]/); 462 } 463 elsif ( $ThisOne =~ m/unqualified sender rejected: <(.*)>/ ) { 464 $cc = "Unqualified Sender"; 465 $bb = "$1"; 466 } 467 elsif ( $ThisOne =~ m/unqualified recipient rejected: <(.*)>/ ) { 468 $cc = "Unqualified Receipient"; 469 $bb = "$1"; 470 } 471 elsif ( $ThisOne =~ m/not accept Windows executables/ ) { 472 $cc = "Blocked Attachment"; 473 ( $bb ) = ($ThisOne =~ m/\[($IPAddress)\]/); 474 } 475 elsif ( $ThisOne =~ m/remote host address is the local host/ ) { 476 $cc = "Invalid local domain"; 477 ( $bb ) = ($ThisOne =~ m/\@[^>]+/); 478 } 479 else { 480 # If we picked up a malfunction but didn't collect it here, 481 # no need to make the user suffer with superfluous error 482 # messages. 483 #next; 484 print "Didn't Summarize: $ThisOne\n"; 485 } 486 if ($cc =~ m/Blocked/ ) { 487 # hash of blocked things 488 my $h = {}; 489 if (!defined($detail{$cc})) { 490 # debug print "add type $cc\n" ; 491 $detail{$cc} = $h; 492 } 493 $h = $detail{$cc}; 494 495 if (defined($h{$bb})) { 496 # debug print "add $bb to ".$h{$bb}."\n" ; 497 $h{$bb} = $h{$bb} + 1; 498 } 499 else { 500 $h{$bb} = 1; 501 # debug print "start $bb at ".$h{$bb}."\n" ; 502 } 503 # marker 504 $spam{$cc} = ""; 505 } 506 else { 507 508 if (defined( $spam{$cc} )) { 509 $mid = $spam{$cc}; 510 } 511 $spam{$cc} = "$mid$aa : $bb,"; 512 513 } 514 } 515 foreach $ThisOne (sort(keys %spam)) { 516 if ($Detail >= $LvlDontAcceptLines) { 517 if ($spam{$cc} eq "") { 518 print " $ThisOne\n"; 519 my $h = $detail{$ThisOne}; 520 foreach $aa (sort(keys %h) ) { 521 print " $aa : ".$h{$aa}." times\n"; 522 } 523 } 524 else { 525 print " $ThisOne\n"; 526 foreach $aa ( sort( split /,/, $spam{$ThisOne} )) { 527 print " $aa\n"; 528 } 529 } 530 } 531 else { 532 @errList = split /,/, $spam{$ThisOne}; 533 print " $ThisOne ".scalar @errList." times\n"; 534 } 535 } 536 } 537} 538 539if ($Detail >= $LvlProtocol) { 540# Print Protocol Violations 541 if (%Proto) { 542 my (%spam); 543 544 # Probable SPAM hosts... 545 print "\n--- Bad Hosts ---\n"; 546 foreach $ThisOne (sort(keys %Proto)) { 547 # We need this blank. 548 $mid = ""; 549 # IP address/current issue holder. 550 $bb = ""; 551 $cc = ""; 552 # Extract exim date and time string... 553 ($mdate, $mtime) = ($ThisOne =~ m/^(\d+-\d+-\d+)\s(\d+\:\d+\:\d+)\s/); 554 # Link date and time (looks cleaner)... 555 $aa = "$mdate $mtime"; 556 557 if ( $ThisOne =~ m/SMTP protocol violation\:\s(.*?\(.*?\))\:/ ) { 558 $cc = $1; 559 ( $bb ) = ($ThisOne =~ m/\[($IPAddress)\]/); 560 } 561 elsif ( $ThisOne =~ /unexpected disconnection while reading SMTP command/ ) { 562 $cc = "Sudden disconnect while expecting remote input"; 563 ( $bb ) = ($ThisOne =~ m/\[($IPAddress)\]/); 564 } 565 elsif ( $ThisOne =~ m/rejected ([HE][EH])LO from \[($IPAddress)\]\:\s(.*?):\s(.*?)$/ ) { 566 $cc = "Rejected HELO/EHLO: $3"; 567 $bb = "$2 ($1LO $4)"; 568 } 569 elsif ( $ThisOne =~ /SMTP data timeout \(message abandoned\) on connection from/ ) { 570 $cc = "SMTP Timeout errors"; 571 ( $bb ) = ($ThisOne =~ m/\[($IPAddress)\]/); 572 } 573 elsif ( $ThisOne =~ /SMTP command timeout on connection from/ ) { 574 $cc = "SMTP Timeout errors"; 575 ( $bb ) = ($ThisOne =~ m/\[($IPAddress)\]/); 576 } 577 elsif ( $ThisOne =~ /syntactically invalid argument/ ) { 578 $cc = "SMTP Syntax errors"; 579 ( $bb ) = ($ThisOne =~ m/\[($IPAddress)\]/); 580 } 581 elsif ( $ThisOne =~ /SMTP syntax error in/ ) { 582 $cc = "SMTP Syntax errors"; 583 ( $bb ) = ($ThisOne =~ m/\[($IPAddress)\]/); 584 } 585 elsif ( $ThisOne =~ /remote host used my name in HELO/ ) { 586 $cc = "My name in HELO"; 587 ( $bb ) = ($ThisOne =~ m/\[($IPAddress)\]/); 588 } 589 elsif ( $ThisOne =~ /remote host used IP address in HELO/ ) { 590 $cc = "IP address in HELO"; 591 ( $bb ) = ($ThisOne =~ m/\[($IPAddress)\]/); 592 } 593 elsif ( $ThisOne =~ /incomplete transaction (\(.*\))/ ) { 594 $bb = "SMTP transaction cut short $1"; 595 $SmtpConnection{$bb}++; 596 } 597 elsif ( $ThisOne =~ /SMTP protocol synchronization error/ ) { 598 $bb = "SMTP protocol synchronization error"; 599 $SmtpConnection{$bb}++; 600 } 601 elsif ( $ThisOne =~ /dropped: too many nonmail commands/ ) { 602 $bb = "Connection dropped after too many nonmail SMTP commands"; 603 $SmtpConnection{$bb}++; 604 } 605 elsif ( $ThisOne =~ /dropped: too many syntax or protocol errors/ ) { 606 $bb = "Connection dropped after too many syntax/protocol errors"; 607 $SmtpConnection{$bb}++; 608 } 609 elsif ( $ThisOne =~ /(SMTP protocol error in \"\w+\")/ ) { 610 $bb = $1; 611 $SmtpConnection{$bb}++; 612 } 613 elsif ( $ThisOne =~ /authenticator failed for \([^)]*\) \[($IPAddress)\]:\d+ I=\[$IPAddress\]:\d+: (.*) \(/ ) { 614 $bb = $1; 615 $SmtpConnection{$bb}++; 616 } 617 elsif ( $ThisOne =~ /SMTP connection from/ ) { 618 if ( $ThisOne =~ /lost while reading message data/ ) { 619 $bb = "SMTP connection lost while reading message data"; 620 } 621 elsif ( $ThisOne =~ /Connection reset by peer/ ) { 622 $bb = "SMTP connection lost when connection reset by peer "; 623 } 624 elsif ( $ThisOne =~ /lost/ ) { 625 $bb = "SMTP connection lost (non-specific)"; 626 } 627 elsif ( $ThisOne =~ /closed by QUIT/ ) { 628 $bb = "SMTP connection closed by QUIT"; 629 } 630 elsif ( $ThisOne =~ /closed after SIGTERM/ ) { 631 $bb = "SMTP connection closed after SIGTERM"; 632 } 633 elsif ( $ThisOne =~ /TCP\/IP connection count/ ) { 634 $bb = "SMTP connection TCP/IP connection count (warning)"; 635 } 636 if ( $bb ne "" ) { 637 $SmtpConnection{$bb}++; 638 } 639 } 640 else { 641 # If we picked up a malfunction but didn't collect it here, 642 # no need to make the user suffer with superfluous error 643 # messages. 644 #next; 645 print "Didn't Summarize: $ThisOne\n"; 646 } 647 if (defined( $spam{$cc} )) { 648 $mid = $spam{$cc}; 649 } 650 # We're picking things up in this larger block that do not 651 # ... fit into this mold, so - let's make sure that this is valid 652 # ... before we set it: 653 if (( $cc ne '' ) && ( $bb ne '' )) { 654 $spam{$cc} = "$mid$aa : IP:$bb,"; 655 } 656 } 657 foreach $ThisOne (sort(keys %spam)) { 658 if ($Detail >= $LvlProtocolLines) { 659 print " $ThisOne:\n"; 660 foreach $aa ( sort( split /,/, $spam{$ThisOne} )) { 661 print " $aa\n"; 662 } 663 } 664 else { 665 @errList = split /,/, $spam{$ThisOne}; 666 print " $ThisOne ".scalar @errList." times\n"; 667 } 668 } 669 670 if ( %SmtpConnection ) { 671 print "\n--- SMTP Connection Issues \n"; 672 foreach $ThisOne (keys %SmtpConnection) { 673 $bb = $SmtpConnection{$ThisOne}; 674 print " $ThisOne: $bb Time(s)\n"; 675 } 676 } 677 678 if (@ReverseLookupH) { 679 print "\n--- Failed Reverse Lookups \n"; 680 print "--- $ReverseLookup Time(s)\n\n"; 681 682 if ($Detail >= $LvlProtocolLines) { 683 foreach $ThisOne (@ReverseLookupH) { 684 print " $ThisOne\n"; 685 } 686 } 687 } 688 689 if (@LookupH) { 690 print "\n--- Failed Reverse Lookups \n"; 691 print "--- (eg. spam try): $Lookup Time(s)\n\n"; 692 693 if ($Detail >= $LvlProtocolLines) { 694 foreach $ThisOne (@LookupH) { 695 print "$ThisOne\n"; 696 } 697 } 698 } 699 } 700} 701 702if ($Detail >= $LvlMsgs) { 703 # Messages by ID 704 if (keys %mmsg ) { 705 my $tmsgcount=0; 706 my $tmsgrcpts=0; 707 print "\n--- Messages history ---\n\n"; 708 # mmsg is hashed by message id, which is sorted by time 709 foreach $tmsg (sort keys %mmsg) { 710 my @tmsgkeys = sort {wedlug_liczb} keys %{$mmsg{$tmsg}}; 711 my $immed_deliv = 1; 712 $immed_deliv = 0 unless $tmsgkeys[0] =~ /^\d+ <=/; 713 foreach my $key (@tmsgkeys[1..$#tmsgkeys-1]) { 714 $immed_deliv = 0 unless $key =~ /^\d+ [-=]>/; 715 } 716 $immed_deliv = 0 unless $tmsgkeys[$#tmsgkeys] =~ /^\d+ Completed/; 717 my $qttmsgcount = 0; 718 my $oldqttmsg = ''; 719 if (!$immed_deliv) { 720 print "\-MsgID: $tmsg\: \n"; 721 foreach $ttmsg (@tmsgkeys) { 722 $qttmsg = $ttmsg; 723 $qttmsg =~ s/^\d+//; # wywal licznik na poczatku (te od sortowania) 724 $qttmsg =~ s/P\=e*smtp S.+//; # wywal koncowki typu: P=smtp S=372023 id= 725 if ($oldqttmsg eq $qttmsg) { 726 $qttmsgcount++; 727 } else { 728 $oldqttmsg = $qttmsg; 729 if ($qttmsgcount > 0) { 730 print "\tlast message repeated $qttmsgcount times\n"; 731 $qttmsgcount = 0; 732 } 733 print "\t$mmsg{$tmsg}{$ttmsg}$qttmsg\n"; 734 } 735 } 736 if ($qttmsgcount > 0) { 737 print "\tlast message repeated $qttmsgcount times\n"; 738 } 739 } else { 740 $tmsgcount++; 741 $tmsgrcpts+=$#tmsgkeys-1; 742 } 743 } 744 print "$tmsgcount messages delivered immediately "; 745 print "to $tmsgrcpts total recipients\n"; 746 } 747} 748 749# INNE Badziewia 750if (keys %OtherList) { 751 print "\n**Unmatched Entries**\n"; 752 foreach $line (sort {$a cmp $b} keys %OtherList) { 753 print "$line: $OtherList{$line} Time(s)\n"; 754 } 755} 756 757exit(0); 758 759# vi: shiftwidth=3 tabstop=3 syntax=perl et 760# Local Variables: 761# mode: perl 762# perl-indent-level: 3 763# indent-tabs-mode: nil 764# End: 765