Code

convert PROGANE from a define to a const char
[nagiosplug.git] / contrib / check_email_loop.pl
1 #!/usr/bin/perl 
2 #
3 # (c)2000 Benjamin Schmid, blueshift@gmx.net (emergency use only ;-)
4 # Copyleft by GNU GPL
5 #
6 #
7 # check_email_loop Nagios Plugin
8 #
9 # This script sends a mail with a specific id in the subject via
10 # an given smtp-server to a given email-adress. When the script
11 # is run again, it checks for this Email (with its unique id) on
12 # a given pop3 account and send another mail.
13
14 #
15 # Example: check_email_loop.pl -poph=mypop -popu=user -pa=password
16 #          -smtph=mailer -from=returnadress@yoursite.com
17 #          -to=remaileradress@friend.com -pendc=2 -lostc=0
18 #
19 # This example will send eacht time this check is executed a new
20 # mail to remaileradress@friend.com using the SMTP-Host mailer.
21 # Then it looks for any back-forwarded mails in the POP3 host
22 # mypop. In this Configuration CRITICAL state will be reached if  
23 # more than 2 Mails are pending (meaning that they did not came 
24 # back till now) or if a mails got lost (meaning a mail, that was
25 # send later came back prior to another mail).
26
28 use Net::POP3;
29 use Net::SMTP;
30 use strict;
31 use Getopt::Long;
32 &Getopt::Long::config('auto_abbrev');
34 # ----------------------------------------
36 my $TIMEOUT = 120;
37 my %ERRORS = ('UNKNOWN' , '-1',
38               'OK' , '0',
39               'WARNING', '1',
40               'CRITICAL', '2');
42 my $state = "UNKNOWN";
43 my ($sender,$receiver, $pophost, $popuser, $poppasswd, $smtphost);
44 my ($poptimeout,$smtptimeout,$pinginterval)=(60,60,5);
45 my ($lostwarn, $lostcrit,$pendwarn, $pendcrit);
47 # Internal Vars
48 my ($pop,$msgcount,@msglines,$statinfo,@messageids,$newestid);
49 my ($matchcount,$statfile) = (0,"check_email_loop.stat");
51 # Subs declaration
52 sub usage;
53 sub messagematchs;
54 sub nsexit;
56 # Just in case of problems, let's not hang Nagios
57 $SIG{'ALRM'} = sub {
58      print ("ERROR: $0 Time-Out $TIMEOUT s \n");
59      exit $ERRORS{"UNKNOWN"};
60 };
61 alarm($TIMEOUT);
64 # Evaluate Command Line Parameters
65 my $status = GetOptions(
66                         "from=s",\$sender,
67                         "to=s",\$receiver,
68                         "pophost=s",\$pophost,
69                         "popuser=s",\$popuser,
70                         "passwd=s",\$poppasswd,
71                         "poptimeout=i",\$poptimeout,
72                         "smtphost=s",\$smtphost,
73                         "smtptimeout=i",\$smtptimeout,
74                         "statfile=s",\$statfile,
75                         "interval=i",\$pinginterval,
76                         "lostwarr=i",\$lostwarn,
77                         "lostcrit=i",\$lostcrit,
78                         "pendwarn=i",\$pendwarn,
79                         "pendcrit=i",\$pendcrit,
80                         );
81 usage() if ($status == 0 || ! ($pophost && $popuser && $poppasswd &&
82         $smtphost && $receiver && $sender ));
84 # Try to read the ids of the last send emails out of statfile
85 if (open STATF, "$statfile") {
86   @messageids = <STATF>;
87   chomp @messageids;
88   close STATF;
89 }
91 # Try to open statfile for writing 
92 if (!open STATF, ">$statfile") {
93   nsexit("Failed to open mail-ID database $statfile for writing",'CRITICAL');
94 }
96 # Ok - check if it's time to release another mail
98 # ...
100 # creating new serial id
101 my $serial = time();
102 $serial = "ID#" . $serial . "#$$";
104 # sending new ping email
105 my $smtp = Net::SMTP->new($smtphost,Timeout=>$smtptimeout) 
106   || nsexit("SMTP connect timeout ($smtptimeout s)",'CRITICAL');
107 ($smtp->mail($sender) &&
108  $smtp->to($receiver) &&
109  $smtp->data() &&
110  $smtp->datasend("To: $receiver\nSubject: E-Mail Ping [$serial]\n\n".
111                  "This is a automatically sended E-Mail.\n".
112                  "It ist not intended for human reader.\n\n".
113                  "Serial No: $serial\n") &&
114  $smtp->dataend() &&
115  $smtp->quit
116  ) || nsexit("Error delivering message",'CRITICAL');
118 # no the interessting part: let's if they are receiving ;-)
120 $pop = Net::POP3->new( $pophost, 
121                  Timeout=>$poptimeout) 
122        || nsexit("POP3 connect timeout (>$poptimeout s, host: $pophost)",'CRITICAL');
124 $msgcount=$pop->login($popuser,$poppasswd);
126 $statinfo="$msgcount mails on POP3";
128 nsexit("POP3 login failed (user:$popuser)",'CRITICAL') if (!defined($msgcount));
130 # Count messages, that we are looking 4:
131 while ($msgcount > 0) {
132   @msglines = @{$pop->get($msgcount)};
134   for (my $i=0; $i < scalar @messageids; $i++) {
135     if (messagematchsid(\@msglines,$messageids[$i])) { 
136       $matchcount++;
137       # newest received mail than the others, ok remeber id.
138       $newestid = $messageids[$i] if ($messageids[$i] > $newestid || !defined $newestid);
139       $pop->delete($msgcount);  # remove E-Mail from POP3 server
140       splice @messageids, $i, 1;# remove id from List
141       last;                     # stop looking in list
142     }
143   } 
145   $msgcount--;
148 $pop->quit();  # necessary for pop3 deletion!
150 # traverse through the message list and mark the lost mails
151 # that mean mails that are older than the last received mail.
152 if (defined $newestid) {
153   $newestid =~ /\#(\d+)\#/;
154   $newestid = $1;
155   for (my $i=0; $i < scalar @messageids; $i++) {
156     $messageids[$i] =~ /\#(\d+)\#/;
157     my $akid = $1;
158     if ($akid < $newestid) {
159       $messageids[$i] =~ s/^ID/LI/; # mark lost
160     }
161   }
164 # Write list to id-Database
165 foreach my $id (@messageids) {
166   print STATF  "$id\n";
168 print STATF "$serial\n";     # remember send mail of this session
169 close STATF;
171 # ok - count lost and pending mails;
172 my @tmp = grep /^ID/, @messageids;
173 my $pendingm = scalar @tmp;
174 @tmp = grep /^LI/, @messageids;
175 my $lostm = scalar @tmp; 
177 # Evaluate the Warnin/Crit-Levels
178 if (defined $pendwarn && $pendingm > $pendwarn) { $state = 'WARNING'; }
179 if (defined $lostwarn && $lostm > $lostwarn) { $state = 'WARNING'; }
180 if (defined $pendcrit && $pendingm > $pendcrit) { $state = 'CRITICAL'; }
181 if (defined $lostcrit && $lostm > $lostcrit) { $state = 'CRITICAL'; }
183 if ((defined $pendwarn || defined $pendcrit || defined $lostwarn 
184      || defined $lostcrit) && ($state eq 'UNKNOWN')) {$state='OK';}
187 # Append Status info
188 $statinfo = $statinfo . ", $matchcount mail(s) came back,".
189             " $pendingm pending, $lostm lost.";
191 # Exit in a Nagios-compliant way
192 nsexit($statinfo);
194 # ----------------------------------------------------------------------
196 sub usage {
197   print "check_email_loop 1.0 Nagios Plugin - Real check of a E-Mail system\n";
198   print "=" x 75,"\nERROR: Missing or wrong arguments!\n","=" x 75,"\n";
199   print "This script sends a mail with a specific id in the subject via an given\n";
200   print "smtp-server to a given email-adress. When the script is run again, it checks\n";
201   print "for this Email (with its unique id) on a given pop3 account and sends \n";
202   print "another mail.\n";
203   print "\nThe following options are available:\n";
204   print "   -from=text         email adress of send (for mail returnr on errors)\n";
205   print "   -to=text           email adress to which the mails should send to\n";
206   print "   -pophost=text      IP or name of the POP3-host to be checked\n";
207   print "   -popuser=text      Username of the POP3-account\n";
208   print "   -passwd=text       Password for the POP3-user\n";
209   print "   -poptimeout=num    Timeout in seconds for the POP3-server\n";
210   print "   -smtphost=text     IP oder name of the SMTP host\n";
211   print "   -smtptimeout=num   Timeout in seconds for the SMTP-server\n";
212   print "   -statfile=text     File to save ids of messages ($statfile)\n";
213 #  print "   -interval=num      Time (in minutes) that must pass by before sending\n"
214 #  print "                      another Ping-mail (gibe a new try);\n"; 
215   print "   -lostwarn=num      WARNING-state if more than num lost emails\n";
216   print "   -lostcrit=num      CRITICAL \n";
217   print "   -pendwarn=num      WARNING-state if more than num pending emails\n";
218   print "   -pendcrit=num      CRITICAL \n";
219   print " Options may abbreviated!\n";
220   print " LOST mails are mails, being sent before the last mail arrived back.\n";
221   print " PENDING mails are those, which are not. (supposed to be on the way)\n";
222   print "\nExample: \n";
223   print " $0 -poph=host -pa=pw -popu=popts -smtph=host -from=root\@me.com\n ";
224   print "      -to=remailer\@testxy.com -lostc=0 -pendc=2\n";
225   print "\nCopyleft 19.10.2000, Benjamin Schmid\n";
226   print "This script comes with ABSOLUTELY NO WARRANTY\n";
227   print "This programm is licensed under the terms of the ";
228   print "GNU General Public License\n\n";
229   exit $ERRORS{"UNKNOWN"};
232 # ---------------------------------------------------------------------
234 sub nsexit {
235   my ($msg,$code) = @_;
236   $code=$state if (!defined $code);
237   print "$code: $msg\n" if (defined $msg);
238   exit $ERRORS{$code};
241 # ---------------------------------------------------------------------
243 sub messagematchsid {
244   my ($mailref,$id) = (@_);
245   my (@tmp);
246   my $match = 0;
247  
248   # ID
249   $id =~ s/^LI/ID/;    # evtl. remove lost mail mark
250   @tmp = grep /Subject: E-Mail Ping \[/, @$mailref;
251   chomp @tmp;
252   if (($tmp[0] =~ /$id/)) 
253     { $match = 1; }
255   # Sender:
256 #  @tmp = grep /^From:\s+/, @$mailref;
257 #  if (@tmp && $sender ne "") 
258 #    { $match = $match && ($tmp[0]=~/$sender/); }
260   # Receiver:
261 #  @tmp = grep /^To: /, @$mailref;
262 #  if (@tmp && $receiver ne "") 
263 #    { $match = $match && ($tmp[0]=~/$receiver/); }
265   return $match;
268 # ---------------------------------------------------------------------