3
# (c)2000 Benjamin Schmid, blueshift@gmx.net (emergency use only ;-)
7
# check_email_loop Nagios Plugin
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.
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
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).
32
&Getopt::Long::config('auto_abbrev');
34
# ----------------------------------------
37
my %ERRORS = ('UNKNOWN' , '-1',
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);
48
my ($pop,$msgcount,@msglines,$statinfo,@messageids,$newestid);
49
my ($matchcount,$statfile) = (0,"check_email_loop.stat");
56
# Just in case of problems, let's not hang Nagios
58
print ("ERROR: $0 Time-Out $TIMEOUT s \n");
59
exit $ERRORS{"UNKNOWN"};
64
# Evaluate Command Line Parameters
65
my $status = GetOptions(
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,
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>;
91
# Try to open statfile for writing
92
if (!open STATF, ">$statfile") {
93
nsexit("Failed to open mail-ID database $statfile for writing",'CRITICAL');
96
# Ok - check if it's time to release another mail
100
# creating new serial id
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) &&
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") &&
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])) {
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
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+)\#/;
155
for (my $i=0; $i < scalar @messageids; $i++) {
156
$messageids[$i] =~ /\#(\d+)\#/;
158
if ($akid < $newestid) {
159
$messageids[$i] =~ s/^ID/LI/; # mark lost
164
# Write list to id-Database
165
foreach my $id (@messageids) {
168
print STATF "$serial\n"; # remember send mail of this session
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';}
188
$statinfo = $statinfo . ", $matchcount mail(s) came back,".
189
" $pendingm pending, $lostm lost.";
191
# Exit in a Nagios-compliant way
194
# ----------------------------------------------------------------------
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
# ---------------------------------------------------------------------
235
my ($msg,$code) = @_;
236
$code=$state if (!defined $code);
237
print "$code: $msg\n" if (defined $msg);
241
# ---------------------------------------------------------------------
243
sub messagematchsid {
244
my ($mailref,$id) = (@_);
249
$id =~ s/^LI/ID/; # evtl. remove lost mail mark
250
@tmp = grep /Subject: E-Mail Ping \[/, @$mailref;
252
if (($tmp[0] =~ /$id/))
256
# @tmp = grep /^From:\s+/, @$mailref;
257
# if (@tmp && $sender ne "")
258
# { $match = $match && ($tmp[0]=~/$sender/); }
261
# @tmp = grep /^To: /, @$mailref;
262
# if (@tmp && $receiver ne "")
263
# { $match = $match && ($tmp[0]=~/$receiver/); }
268
# ---------------------------------------------------------------------