<span class="gmail_quote"></span><span class="gmail_quote"></span><div><div></div><div><span class="q">I was just experiencing some strange problems, fixed it and wanted to submit<br>it to the community.<br></span></div><div>
nagios 2.2 (now 2.3)<br>nagios-plugins 1.4.2</div><div><span class="e" id="q_10beca5ecf1e4150_3"><br><br>the script is actually trying to do doing this:
<br>- send mail number 1<br>- queue mail 1 for delivery on mailserver
<br>- retrive mails from mailbox looking for mail number 0 (previously sent)<br>- delete old unrecognised mails.<br>- retain in mind (stat file) mail 1 was sent for next check<br><br>problem:<br>if your mailserver is quick enough, here is what will happen:
<br>- send mail 1<br>- deliver mail 1 to mailbox directly without queuing<br>- retrieve mails looking for mail 0 (including mail 1)<br>- delete mail 1 as if it is not yet recognised as sent<br>- retain mail 1 was sent (and never find it)
<br><br>so the solution was that simple:<br>- retrieve mail 0<br>- send mail 1<br>- retain mail 1 was sent for future retrieval<br><br>I ve seen in the mailing some other people are experiencing the same, but<br>did not find someone who posted an updated version of the script.
<br>So here is the updated version that is running well for me.<br><br>cheers,<br><br>Man</span><span class="e" id="q_10beca5ecf1e4150_3">u<br><br><br>

</span>------------------------------ start of check_email_loop-pl -------------------------------------------<span class="e" id="q_10beca5ecf1e4150_3"><br><br>#!/usr/bin/perl -w<br>#<br># (c)2000 Benjamin Schmid, <a href="mailto:blueshift@gmx.net">
blueshift@gmx.net</a><br># Copyleft by GNU GPL<br>#<br>#<br># check_email_loop Nagios Plugin<br>#<br># This script sends a mail with a specific id in the subject via<br># an given smtp-server to a given email-adress. When the script
<br># is run again, it checks for this Email (with its unique id) on<br># a given pop3 account and send another mail.<br># <br>#<br># Example: check_email_loop.pl -poph=mypop -popu=user -pa=password<br>#        -smtph=mailer -from=
<a href="mailto:returnadress@yoursite.com">returnadress@yoursite.com</a><br>#       -to=<a href="mailto:remaileradress@friend.com">remaileradress@friend.com</a> -pendc=2 -lostc=0<br>#<br># This example will send each time this check is executed a new
<br># mail to <a href="mailto:remaileradress@friend.com">remaileradress@friend.com</a> using the SMTP-Host mailer.<br># Then it looks for any back-forwarded mails in the POP3 host<br># mypop. In this Configuration CRITICAL state will be reached if  
<br># more than 2 Mails are pending (meaning that they did not came <br># back till now) or if a mails got lost (meaning a mail, that was<br># send later came back prior to another mail).<br># <br># Michael Markstaller, <a href="mailto:mm@elabnet.de">
mm@elabnet.de</a> various changes/additions<br># MM 021003: fixed some unquoted strings<br># MM 021116: fixed/added pendwarn/lostwarn<br># MM 030515: added deleting of orphaned check-emails <br># changed to use "top" instead of get to minimize traffic (required changing match-string from "Subject: Email-ping [" to "Email-Ping ["
<br>#<br># Emmanuel Kedaj (<a href="mailto:Emmanuel.kedaj@gmail.com">Emmanuel.kedaj@gmail.com</a>)<br># Added some debug messages<br># retrieving POP3 mails before sending actual test mail<br># as mentionned by Dave Ewall <dave_at_email.domain.hidden> on 19 Jul 2005 on Nagios-users mailing list
<br># <a href="https://lists.sourceforge.net/lists/listinfo/nagios-users">https://lists.sourceforge.net/lists/listinfo/nagios-users</a><br>#<br><br>use Net::POP3;<br>use Net::SMTP;<br>use strict;<br>use Getopt::Long;<br>&Getopt::Long::config('auto_abbrev');
<br><br># ----------------------------------------<br><br>my $TIMEOUT = 120;<br>my %ERRORS = ('UNKNOWN' , '-1',<br>              'OK' , '0',<br>              'WARNING', '1',<br>              'CRITICAL', '2');<br><br>my $state = "UNKNOWN";
<br>my ($sender,$receiver, $pophost, $popuser, $poppasswd, $smtphost,$keeporphaned);<br>my ($poptimeout,$smtptimeout,$pinginterval,$maxmsg)=(60,60,5,50);<br>my ($lostwarn, $lostcrit,$pendwarn, $pendcrit,$debug);<br><br>$debug=0;
<br><br># Internal Vars<br>my ($pop,$msgcount,@msglines,$statinfo,@messageids,$newestid);<br>my (%other_smtp_opts);<br>my ($matchcount,$statfile) = (0,"check_email_loop.stat");<br><br># Subs declaration<br>sub usage;
<br>sub messagematchs;<br>sub nsexit;<br><br># Just in case of problems, let's not hang Nagios<br>$SIG{'ALRM'} = sub {<br>     print ("ERROR: $0 Time-Out $TIMEOUT s \n");<br>     exit $ERRORS{"UNKNOWN"};
<br>};<br>alarm($TIMEOUT);<br><br><br># Evaluate Command Line Parameters<br>my $status = GetOptions(<br>                "from=s",\$sender,<br>            "to=s",\$receiver,<br>                        "debug", \$debug,
<br>                        "pophost=s",\$pophost,<br>                        "popuser=s",\$popuser,<br>            "passwd=s",\$poppasswd,<br>            "poptimeout=i",\$poptimeout,
<br>            "smtphost=s",\$smtphost,<br>            "smtptimeout=i",\$smtptimeout,<br>            "statfile=s",\$statfile,<br>            "interval=i",\$pinginterval,<br>            "lostwarn=i",\$lostwarn,
<br>            "lostcrit=i",\$lostcrit,<br>            "pendwarn=i",\$pendwarn,<br>            "pendcrit=i",\$pendcrit,<br>            "maxmsg=i",\$maxmsg,<br>            "keeporphaned=s",\$keeporphaned,
<br>            );<br>usage() if ($status == 0 || ! ($pophost && $popuser && $poppasswd &&<br>    $smtphost && $receiver && $sender ));<br><br># Try to read the ids of the last send emails out of statfile
<br>if (open STATF, "$statfile") {<br>  @messageids = <STATF>;<br>  chomp @messageids;<br>  close STATF;<br>}<br><br># Try to open statfile for writing <br>if (!open STATF, ">$statfile") {<br>
  nsexit("Failed to open mail-ID database $statfile for writing",'CRITICAL');<br>}<br><br>if ( $debug == 1  ) {<br>     print ("----------------------------------------------------------------------\n");
<br>     print ("----------------------------------------------------------------------\n");<br>     print ("-------------------- Checking POP3 Mails -----------------------------\n");<br>     print ("----------------------------------------------------------------------\n");
<br>     print ("----------------------------------------------------------------------\n");<br>     print ("Retrieving POP mails from $pophost using user: $popuser and password $poppasswd\n");<br>}<br>
<br># the interessting part: let's see if mails are receiving ;-)<br><br>$pop = Net::POP3->new( $pophost, <br>         Timeout=>$poptimeout) <br>       || nsexit("POP3 connect timeout (>$poptimeout s, host: $pophost)",'CRITICAL');
<br><br>$msgcount=$pop->login($popuser,$poppasswd);<br><br>$statinfo="$msgcount mails on POP3";<br>if ( $debug == 1  ) {<br>     print ("Found $statinfo\n");<br>}<br><br>nsexit("POP3 login failed (user:$popuser)",'CRITICAL') if (!defined($msgcount));
<br><br># Check if more than maxmsg mails in pop3-box<br>nsexit(">$maxmsg Mails ($msgcount Mails on POP3); Please delete !",'WARNING') if ($msgcount > $maxmsg);<br><br># Count messages, that we are looking 4:
<br>while ($msgcount > 0) {<br>  @msglines = @{$pop->top($msgcount,1)};<br>  for (my $i=0; $i < scalar @messageids; $i++) {<br>    if (messagematchsid(\@msglines,$messageids[$i])) { <br>      $matchcount++;<br>    if ( $debug == 1  ) {
<br>             print ("Messages are matching\n");<br>    }<br>      # newest received mail than the others, ok remember id.<br>      if(!defined $newestid) {<br>        $newestid = $messageids[$i] <br>      } elsif ($messageids[$i] > $newestid) {
<br>        $newestid = $messageids[$i];<br>      }<br>    my @msgsubject = grep /^Subject/, @msglines;<br>    if ( $debug == 1  ) {<br>             print ("Deleted retrieved mail $msgcount with subject $msgsubject[0]\n");
<br>    }<br>      $pop->delete($msgcount);  # remove E-Mail from POP3 server<br>      splice @messageids, $i, 1;# remove id from List<br>      last;                     # stop looking in list<br>    }<br>  } <br>    # Delete orphaned Email-ping msg
<br>    my @msgsubject = grep /^Subject/, @msglines;<br>    chomp @msgsubject;<br>    # Scan Subject if email is an Email-Ping. In fact we match and delete also successfully retrieved messages here again.<br>    if (!defined $keeporphaned && $msgsubject[0] =~ /E-Mail Ping \[/) {
<br>        $pop->delete($msgcount);  # remove E-Mail from POP3 server<br>        if ( $debug == 1  ) {<br>                 print ("Deleted orphaned mail $msgcount with subject $msgsubject[0]\n");<br>        }
<br>    }<br><br>    $msgcount--;<br>}<br><br>$pop->quit();  # necessary for pop3 deletion!<br><br># traverse through the message list and mark the lost mails<br># that mean mails that are older than the last received mail.
<br>if (defined $newestid) {<br>  $newestid =~ /\#(\d+)\#/;<br>  $newestid = $1;<br>  for (my $i=0; $i < scalar @messageids; $i++) {<br>    $messageids[$i] =~ /\#(\d+)\#/;<br>    my $akid = $1;<br>    if ($akid < $newestid) {
<br>      $messageids[$i] =~ s/^ID/LI/; # mark lost<br>        if ( $debug == 1  ) {<br>                 print ("MAIL $messageids[$i] MARKED AS LOST\n");<br>        }<br>    }<br>  }<br>}<br><br># Write list to id-Database
<br>foreach my $id (@messageids) {<br>  print STATF  "$id\n";<br>}<br><br># creating new serial id<br>my $serial = time();<br>$serial = "ID#" . $serial . "#$$";<br><br>if ( $debug == 1  ) {<br>
     print ("----------------------------------------------------------------------\n");<br>     print ("----------------------------------------------------------------------\n");<br>     print ("-------------------- SENDING MAIL: $serial -----------------\n");
<br>     print ("----------------------------------------------------------------------\n");<br>     print ("----------------------------------------------------------------------\n");<br>}<br><br># sending new ping email
<br>#%other_smtp_opts={};<br>if ( $debug == 1  ) {<br>    $other_smtp_opts{'Debug'} = 1;<br>}<br>my $smtp = Net::SMTP->new($smtphost,Timeout=>$smtptimeout, %other_smtp_opts) <br>  || nsexit("SMTP connect timeout ($smtptimeout s)",'CRITICAL');
<br>($smtp->mail($sender) &&<br> $smtp->to($receiver) &&<br> $smtp->data() &&<br> $smtp->datasend("To: $receiver\nSubject: E-Mail Ping [$serial]\n\n".<br>         "This is a automatically sended E-Mail.\n".
<br>         "It ist not intended for human reader.\n\n".<br>         "Serial No: $serial\n") &&<br> $smtp->dataend() &&<br> $smtp->quit<br> ) || nsexit("Error delivering message",'CRITICAL');
<br><br>print STATF "$serial\n";     # remember send mail of this session<br>close STATF;<br><br># ok - count lost and pending mails;<br>my @tmp = grep /^ID/, @messageids;<br>my $pendingm = scalar @tmp;<br>@tmp = grep /^LI/, @messageids;
<br>my $lostm = scalar @tmp; <br><br># Evaluate the Warnin/Crit-Levels<br>if (defined $pendwarn && $pendingm > $pendwarn) { $state = 'WARNING'; }<br>if (defined $lostwarn && $lostm > $lostwarn) { $state = 'WARNING'; }
<br>if (defined $pendcrit && $pendingm > $pendcrit) { $state = 'CRITICAL'; }<br>if (defined $lostcrit && $lostm > $lostcrit) { $state = 'CRITICAL'; }<br><br>if ((defined $pendwarn || defined $pendcrit || defined $lostwarn 
<br>     || defined $lostcrit) && ($state eq 'UNKNOWN')) {$state='OK';}<br><br><br><br>  if ( $debug == 1  ) {<br>    print ("STATUS:\n");<br>    print ("Found    : $statinfo\n");<br>    print ("Matching : $matchcount\n");
<br>    print ("Pending  : $pendingm\n");<br>    print ("Lost     : $lostm\n");<br>    print ("Mail $serial remembered as sent\n");<br>     print ("----------------------------------------------------------------------\n");
<br>     print ("----------------------------------------------------------------------\n");<br>     print ("-------------------------- END DEBUG INFO ----------------------------\n");<br>     print ("----------------------------------------------------------------------\n");
<br>     print ("----------------------------------------------------------------------\n");<br>  }<br><br># Append Status info<br>$statinfo = $statinfo . ", $matchcount mail(s) came back,".<br>            " $pendingm pending, $lostm lost.";
<br><br># Exit in a Nagios-compliant way<br>nsexit($statinfo);<br><br># ----------------------------------------------------------------------<br><br>sub usage {<br>  print "check_email_loop 1.1 Nagios Plugin - Real check of a E-Mail system\n";
<br>  print "=" x 75,"\nERROR: Missing or wrong arguments!\n","=" x 75,"\n";<br>  print "This script sends a mail with a specific id in the subject via an given\n";<br>  print "smtp-server to a given email-adress. When the script is run again, it checks\n";
<br>  print "for this Email (with its unique id) on a given pop3 account and sends \n";<br>  print "another mail.\n";<br>  print "\nThe following options are available:\n";<br>  print    "   -from=text         email adress of send (for mail returnr on errors)\n";
<br>  print    "   -to=text           email adress to which the mails should send to\n";<br>  print "   -pophost=text      IP or name of the POP3-host to be checked\n";<br>  print "   -popuser=text      Username of the POP3-account\n";
<br>  print    "   -passwd=text       Password for the POP3-user\n";<br>  print    "   -poptimeout=num    Timeout in seconds for the POP3-server\n";<br>  print "   -smtphost=text     IP oder name of the SMTP host\n";
<br>  print "   -smtptimeout=num   Timeout in seconds for the SMTP-server\n";<br>  print "   -statfile=text     File to save ids of messages ($statfile)\n";<br>  print "   -interval=num      Time (in minutes) that must pass by before sending\n";
<br>  print "                      another Ping-mail (gibe a new try);\n"; <br>  print "   -lostwarn=num      WARNING-state if more than num lost emails\n";<br>  print "   -lostcrit=num      CRITICAL \n";
<br>  print "   -pendwarn=num      WARNING-state if more than num pending emails\n";<br>  print "   -pendcrit=num      CRITICAL \n";<br>  print "   -maxmsg=num        WARNING if more than num emails on POP3 (default 50)\n";
<br>  print "   -keeporphaned      Set this to NOT delete orphaned E-Mail Ping msg from POP3\n";<br>  print "   -debug             send SMTP tranaction info to stderr\n\n";<br>  print " Options may abbreviated!\n";
<br>  print " LOST mails are mails, being sent before the last mail arrived back.\n";<br>  print " PENDING mails are those, which are not. (supposed to be on the way)\n";<br>  print "\nExample: \n";
<br>  print " $0 -poph=host -pa=pw -popu=popts -smtph=host -from=root\@me.com\n ";<br>  print "      -to=<a href="mailto:remailer\@testxy.com">remailer\@testxy.com</a> -lostc=0 -pendc=2\n";<br>  print "\nCopyleft 
19.10.2000, Benjamin Schmid / 2003 Michael Markstaller, mm\@elabnet.de\n";<br>  print "This script comes with ABSOLUTELY NO WARRANTY\n";<br>  print "This programm is licensed under the terms of the ";
<br>  print "GNU General Public License\n\n";<br>  exit $ERRORS{"UNKNOWN"};<br>}<br><br># ---------------------------------------------------------------------<br><br>sub nsexit {<br>  my ($msg,$code) = @_;
<br>  $code=$state if (!defined $code);<br>  print "$code: $msg\n" if (defined $msg);<br>  exit $ERRORS{$code};<br>}<br><br># ---------------------------------------------------------------------<br><br>sub messagematchsid {
<br>  my ($mailref,$id) = (@_);<br>  my (@tmp);<br>  my $match = 0;<br> <br>  # ID<br>  $id =~ s/^LI/ID/;    # evtl. remove lost mail mark<br>  @tmp = grep /E-Mail Ping \[/, @$mailref;<br>  chomp @tmp;<br>  if ( $debug == 1  ) {
<br>    print ("Comparing Mail content $tmp[0] with Mail ID $id:\n");<br>  }<br>  if (($tmp[0] =~ /$id/)) <br>    { $match = 1; }<br><br>  # Sender:<br>#  @tmp = grep /^From:\s+/, @$mailref;<br>#  if (@tmp && $sender ne "") 
<br>#    { $match = $match && ($tmp[0]=~/$sender/); }<br><br>  # Receiver:<br>#  @tmp = grep /^To: /, @$mailref;<br>#  if (@tmp && $receiver ne "") <br>#    { $match = $match && ($tmp[0]=~/$receiver/); }
<br><br>  return $match;<br>}<br><br># ---------------------------------------------------------------------<br><br><br>

</span>------------------------------ end of check_email_loop-pl -------------------------------------------</div>

</div><br clear="all">