diff options
Diffstat (limited to 'contrib/check_email_loop.pl')
-rw-r--r-- | contrib/check_email_loop.pl | 268 |
1 files changed, 268 insertions, 0 deletions
diff --git a/contrib/check_email_loop.pl b/contrib/check_email_loop.pl new file mode 100644 index 00000000..733406da --- /dev/null +++ b/contrib/check_email_loop.pl | |||
@@ -0,0 +1,268 @@ | |||
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 | # | ||
27 | |||
28 | use Net::POP3; | ||
29 | use Net::SMTP; | ||
30 | use strict; | ||
31 | use Getopt::Long; | ||
32 | &Getopt::Long::config('auto_abbrev'); | ||
33 | |||
34 | # ---------------------------------------- | ||
35 | |||
36 | my $TIMEOUT = 120; | ||
37 | my %ERRORS = ('UNKNOWN' , '-1', | ||
38 | 'OK' , '0', | ||
39 | 'WARNING', '1', | ||
40 | 'CRITICAL', '2'); | ||
41 | |||
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); | ||
46 | |||
47 | # Internal Vars | ||
48 | my ($pop,$msgcount,@msglines,$statinfo,@messageids,$newestid); | ||
49 | my ($matchcount,$statfile) = (0,"check_email_loop.stat"); | ||
50 | |||
51 | # Subs declaration | ||
52 | sub usage; | ||
53 | sub messagematchs; | ||
54 | sub nsexit; | ||
55 | |||
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); | ||
62 | |||
63 | |||
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 )); | ||
83 | |||
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 | } | ||
90 | |||
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 | } | ||
95 | |||
96 | # Ok - check if it's time to release another mail | ||
97 | |||
98 | # ... | ||
99 | |||
100 | # creating new serial id | ||
101 | my $serial = time(); | ||
102 | $serial = "ID#" . $serial . "#$$"; | ||
103 | |||
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'); | ||
117 | |||
118 | # no the interessting part: let's if they are receiving ;-) | ||
119 | |||
120 | $pop = Net::POP3->new( $pophost, | ||
121 | Timeout=>$poptimeout) | ||
122 | || nsexit("POP3 connect timeout (>$poptimeout s, host: $pophost)",'CRITICAL'); | ||
123 | |||
124 | $msgcount=$pop->login($popuser,$poppasswd); | ||
125 | |||
126 | $statinfo="$msgcount mails on POP3"; | ||
127 | |||
128 | nsexit("POP3 login failed (user:$popuser)",'CRITICAL') if (!defined($msgcount)); | ||
129 | |||
130 | # Count messages, that we are looking 4: | ||
131 | while ($msgcount > 0) { | ||
132 | @msglines = @{$pop->get($msgcount)}; | ||
133 | |||
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 | } | ||
144 | |||
145 | $msgcount--; | ||
146 | } | ||
147 | |||
148 | $pop->quit(); # necessary for pop3 deletion! | ||
149 | |||
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 | } | ||
162 | } | ||
163 | |||
164 | # Write list to id-Database | ||
165 | foreach my $id (@messageids) { | ||
166 | print STATF "$id\n"; | ||
167 | } | ||
168 | print STATF "$serial\n"; # remember send mail of this session | ||
169 | close STATF; | ||
170 | |||
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; | ||
176 | |||
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'; } | ||
182 | |||
183 | if ((defined $pendwarn || defined $pendcrit || defined $lostwarn | ||
184 | || defined $lostcrit) && ($state eq 'UNKNOWN')) {$state='OK';} | ||
185 | |||
186 | |||
187 | # Append Status info | ||
188 | $statinfo = $statinfo . ", $matchcount mail(s) came back,". | ||
189 | " $pendingm pending, $lostm lost."; | ||
190 | |||
191 | # Exit in a Nagios-compliant way | ||
192 | nsexit($statinfo); | ||
193 | |||
194 | # ---------------------------------------------------------------------- | ||
195 | |||
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"}; | ||
230 | } | ||
231 | |||
232 | # --------------------------------------------------------------------- | ||
233 | |||
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}; | ||
239 | } | ||
240 | |||
241 | # --------------------------------------------------------------------- | ||
242 | |||
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; } | ||
254 | |||
255 | # Sender: | ||
256 | # @tmp = grep /^From:\s+/, @$mailref; | ||
257 | # if (@tmp && $sender ne "") | ||
258 | # { $match = $match && ($tmp[0]=~/$sender/); } | ||
259 | |||
260 | # Receiver: | ||
261 | # @tmp = grep /^To: /, @$mailref; | ||
262 | # if (@tmp && $receiver ne "") | ||
263 | # { $match = $match && ($tmp[0]=~/$receiver/); } | ||
264 | |||
265 | return $match; | ||
266 | } | ||
267 | |||
268 | # --------------------------------------------------------------------- | ||