<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">