File send_mail of Package nagios-eventhandlers-send_mail
#!/usr/bin/perl
#
# Copyright (C) 2012 SUSE Linux Products GmbH
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the
# Free Software Foundation, Inc.,
# 51 Franklin Street,
# Fifth Floor,
# Boston, MA 02110-1301,
# USA.
#
use strict;
use warnings;
use Carp;
use Config::IniFiles;
use English qw( -no_match_vars );
use Getopt::Long;
use Net::SMTP;
use Pod::Usage;
use URI::Escape;
our $conf={
VERSION => '0.1.3',
PROGNAME => 'send_mail',
config => '/etc/nagios/send_mail.cfg',
debug => 0,
logfile => '/var/log/nagios/mail.log',
loglevel => 1,
servicealert => 0,
acknowledgement => 0,
mailbody => '',
mailsubject => '',
version => 0,
};
our @config_options=qw(
mailhost
maildomain
mailfrom
mailsubject
mailtimeout
mailuser
mailpassword
logfile
loglevel
debug
);
our @needed=qw(
mailhost
maildomain
mailfrom
mailtimeout
logfile
);
my $print_help=0;
#######################################################################
## Function Area
#######################################################################
sub logfile {
my ($action,$config_ref)=@_;
if (!defined($config_ref->{'loglevel'}) || $config_ref->{'loglevel'} eq ""){
$config_ref->{'loglevel'}=0;
}
if (("$action" eq "open" ) || ("$action" eq "new" )) {
open (my $fh, ">>$config_ref->{'logfile'}") or croak "Couldn't open ".$config_ref->{'logfile'}." !\n";
flock($fh,2) or croak "Can't get lock for $config_ref->{'logfile'} !\n";
return $fh;
} else {
close $config_ref->{'logfile_fh'} or croak("Could not close filehandle $config_ref->{'logfile_fh'}\n");
}
}
sub LOG {
my ($message,$level,$config_ref)=@_;
my $time = localtime(time);
my $fh=$config_ref->{'logfile_fh'};
if ($level <= $config_ref->{'loglevel'}){
print $fh "$time [".$config_ref->{'PROGNAME'}."] : $message\n" or croak("Could not write to logfile\n");
}
print STDERR "DEBUG: $message\n" if ($config_ref->{'debug'});
}
sub check_ini_section($$$){
my ($iniref,$name,$needed_ref)=@_;
foreach my $needed (@$needed_ref){
if (!defined($iniref->val("$name","$needed"))){
return "$needed";
}
}
return 0
}
sub cleanup_and_exit($$){
my ($conf,$exitcode)=@_;
logfile('close',$conf);
exit $exitcode;
}
sub sendmail($$){
my($conf,$ini)=@_;
my $maildomain=$ini->val('global','maildomain');
my $mailtimeout=$ini->val('global','mailtimeout');
my $mailhost=$ini->val('global','mailhost');
my $mailfrom=$ini->val('global','mailfrom');
my $debug=$conf->{'debug'};
my $email=$conf->{'email'};
my $mailsubject=$conf->{'mailsubject'};
my $mailbody=$conf->{'mailbody'};
my $mailuser=$ini->val('global','mailuser') if defined $ini->val('global','mailuser');
my $mailpassword=$ini->val('global','mailpassword') if defined $ini->val('global','mailpassword');
my $smtp = Net::SMTP->new(
$mailhost,
Hello => $maildomain,
Timeout => $mailtimeout,
Debug => $debug,
);
if (defined $mailuser and "$mailuser" ne ''){
$smtp->auth("$mailuser","$mailpassword");
}
$smtp->mail($mailfrom);
$smtp->to($email);
$smtp->data();
$smtp->datasend("To: $email\n");
$smtp->datasend("From: $mailfrom\n");
$smtp->datasend("Subject: $mailsubject\n");
$smtp->datasend("\n");
$smtp->datasend("$mailbody\n");
$smtp->dataend();
$smtp->quit;
}
sub print_version($){
my ($conf)=@_;
print "$conf->{'PROGNAME'} v$conf->{'VERSION'}\n";
print "This script come with ABSOLUTELY NO WARRANTY. You may redistribute\n";
print "copies of the plugins under the terms of the GNU General Public License.\n";
print "For more information about these matters, see the file named COPYING.\n";
}
#######################################################################
## Main Area
#######################################################################
Getopt::Long::Configure('bundling');
GetOptions( "h|help" => \$print_help,
"c|config=s" => \$conf->{'config'},
"d|debug" => \$conf->{'debug'},
"logfile=s" => \$conf->{'logfile'},
"loglevel=i" => \$conf->{'loglevel'},
"v|version" => \$conf->{'version'},
"n|notificationtype=s" => \$conf->{'notificationtype'}, # $NOTIFICATIONTYPE$
"H|hostname=s" => \$conf->{'hostname'}, # $HOSTNAME$
"S|servicename=s" => \$conf->{'servicename'}, # $SERVICEDESC$
"a|authorname=s" => \$conf->{'authorname'}, # $SERVICEACKAUTHORNAME$, $HOSTACKAUTHORNAME$
"c|comment=s" => \$conf->{'comment'}, # $SERVICEACKCOMMENT$, $HOSTACKCOMMENT$
"s|state=s" => \$conf->{'state'}, # $SERVICESTATE$, $HOSTSTATE$
"e|email=s" => \$conf->{'email'}, # $CONTACTEMAIL$
"l|longdatetime=s" => \$conf->{'longdatetime'}, # $LONGDATETIME$
"o|output=s" => \$conf->{'output'}, # $SERVICEOUTPUT$, $HOSTOUTPUT$
"longserviceoutput=s" => \$conf->{'longserviceoutput'}, # $LONGSERVICEOUTPUT$
"m|mailsubject=s" => \$conf->{'mailsubject'}, # Subject of the Email
"u|url=s" => \$conf->{'url'}, # https://$nagioshost/nagios/cgi-bin/extinfo.cgi - rest is magic
) or pod2usage(2);
pod2usage( -exitstatus => 0,
-verbose => 1, # 2 to print full pod
) if $print_help;
if ($conf->{'version'}){
print_version($conf);
exit 0;
}
if ( ! -f "$conf->{'config'}"){
print STDERR "$conf->{'config'} not found or not readable\n";
exit 1;
}
my $ini = new Config::IniFiles( -file => "$conf->{'config'}",
-default => "global",
-allowcontinue => 1);
if( ! $ini ){
croak("Couldn't open $conf->{'config'} : $!\n");
}
$conf->{'logfile'}=$ini->val('global','logfile') if $ini->val('global','logfile');
$conf->{'loglevel'}=$ini->val('global','loglevel') if $ini->val('global','loglevel');
my $logfile_ref=logfile('open',$conf);
$conf->{'logfile_fh'}=$logfile_ref;
foreach my $section ( $ini->Sections() ){
my $res=check_ini_section($ini,$section,\@needed);
if ($res){
LOG("Needed element $res not found in $section from $conf->{'config'} - skipping",2,$conf);
next;
}
}
# first check, if we have the absolute minimum to send out notification mails
if (not defined $conf->{'hostname'} or $conf->{'hostname'} eq ''){
LOG("Option -H (--hostname) not defined",1,$conf);
$conf->{'hostname'}='UNDEFINED';
}
if (not defined $conf->{'notificationtype'} or $conf->{'notificationtype'} eq ''){
LOG("Option -n (--notificationtype) not defined",1,$conf);
$conf->{'notificationtype'}='UNDEFINED';
}
if (not defined $conf->{'email'} or $conf->{'email'} eq ''){
LOG("Option -e (--email) not defined",1,$conf);
$conf->{'email'}='root@localhost';
}
if (not defined $conf->{'state'} or $conf->{'state'} eq ''){
LOG("Option -s (--state) not defined",1,$conf);
$conf->{'state'}='UNDEFINED';
}
if (not defined $conf->{'output'} or $conf->{'output'} eq ''){
LOG("Option -o (--output) not defined",1,$conf);
$conf->{'output'}='UNDEFINED';
}
if (not defined $conf->{'longdatetime'} or $conf->{'longdatetime'} eq ''){
LOG("Option -l (--longdatetime) not defined",1,$conf);
$conf->{'longdatetime'}='UNDEFINED';
}
if (defined $conf->{'servicename'} and $conf->{'servicename'} ne ''){
$conf->{'servicealert'}=1;
}
if (defined $conf->{'authorname'} and $conf->{'authorname'} ne ''){
$conf->{'acknowledgement'}=1;
}
if ($conf->{'notificationtype'} eq 'ACKNOWLEDGEMENT'){
$conf->{'acknowledgement'}=1;
}
if ($conf->{'debug'}){
use Data::Dumper;
print STDERR "Config:\n".Data::Dumper->Dump([$conf])."\n";
print STDERR "Ini:\n".Data::Dumper->Dump([$ini])."\n";
}
if (not defined $conf->{'mailsubject'} or $conf->{'mailsubject'} eq ''){
if ($conf->{'servicealert'}){
$conf->{'mailsubject'}="** $conf->{'notificationtype'} Service Alert: $conf->{'hostname'}/$conf->{'servicename'} is $conf->{'state'} **";
}
elsif ($conf->{'acknowledgement'}){
if ($conf->{'servicealert'}){
$conf->{'mailsubject'}="** $conf->{'notificationtype'} for $conf->{'hostname'}/$conf->{'servicename'} **";
}
else {
$conf->{'mailsubject'}="** $conf->{'notificationtype'} for $conf->{'hostname'} **";
}
}
else {
$conf->{'mailsubject'}="** $conf->{'notificationtype'} Host Alert: $conf->{'hostname'} is $conf->{'state'} **";
}
}
my $url="$conf->{'url'}";
my $host=uri_escape($conf->{'hostname'});
my $standardbody = <<_END_;
Notification: $conf->{'notificationtype'}
Host: $conf->{'hostname'}
State: $conf->{'state'}
Date/Time: $conf->{'longdatetime'}
Info: $conf->{'output'}
_END_
# Acknowledgement of a Host/Service Problem
if ($conf->{'acknowledgement'}){
$conf->{'mailbody'}=<<_END_;
User: $conf->{'authorname'}
AckComment: $conf->{'comment'}
Notification: $conf->{'notificationtype'}
Host: $conf->{'hostname'}
State: $conf->{'state'}
Date/Time: $conf->{'longdatetime'}
_END_
# sometimes, we see a comment in ACKCOMMENT and in OUTPUT - just print out once
if ("$conf->{'output'}" ne "$conf->{'comment'}"){
$conf->{'mailbody'}.="Info: $conf->{'output'}";
}
}
# A Service Problem
elsif ($conf->{'servicealert'} and not $conf->{'acknowledgement'}){
$conf->{'mailbody'}=<<_END_;
$standardbody
Service: $conf->{'servicename'}
_END_
if (defined $conf->{'longserviceoutput'} and $conf->{'longserviceoutput'} ne ''){
$conf->{'mailbody'}.="\nLong Output: $conf->{'longserviceoutput'}";
}
my $service=uri_escape($conf->{'servicename'});
$url.="?type=2&host=".$host."&service=".$service;
}
# A Host Problem
else {
$conf->{'mailbody'}=$standardbody;
$url.="?type=1host=".$host;
}
$conf->{'mailbody'}.="\n\nSee Online: $url\n";
# Everything prepared - start sending Email
LOG("sending mail to ".$conf->{'email'}." with subject ".$conf->{'mailsubject'},2,$conf);
if ($conf->{'debug'}){
print STDERR "subject : $conf->{'mailsubject'}\n";
print STDERR "mailbody: $conf->{'mailbody'}\n";
}
sendmail($conf,$ini);
cleanup_and_exit($conf,0);
__END__
=head1 Send Nagios Email
Commandline tool for sending Nagios notifications via Email.
=head1 SYNOPSIS
./send_email <OPTIONS>
Example of a service problem/acknowledgement:
./send_mail \
--config "/usr/local/etc/nagios/send_mail.cfg" \
--notificationtype "$NOTIFICATIONTYPE$" \
--state "$SERVICESTATE$" \
--hostname "$HOSTNAME$" \
--longdatetime "$LONGDATETIME$" \
--url "https://nagios.example.com/nagios/cgi-bin/extinfo.cgi" \
--output "$SERVICEOUTPUT$" \
--mailsubject "** $NOTIFICATIONTYPE$ Service Alert: $HOSTNAME$/$SERVICEDESC$ is $SERVICESTATE$ **" \
--servicename "$SERVICEDESC$" \
--longserviceoutput "$LONGSERVICEOUTPUT$" \
--email "$CONTACTEMAIL$" \
--authorname "$SERVICEACKAUTHORNAME$" \
--comment "$SERVICEACKCOMMENT$"
Example of a host problem/acknowledgement:
./send_mail \
--config "/usr/local/etc/nagios/send_mail.cfg" \
--notificationtype "$NOTIFICATIONTYPE$" \
--state "$HOSTSTATE$" \
--hostname "$HOSTNAME$" \
--longdatetime "$LONGDATETIME$" \
--url "https://nagios.example.com/nagios/cgi-bin/extinfo.cgi" \
--output "$HOSTOUTPUT$" \
--mailsubject "** $NOTIFICATIONTYPE$ Host Alert: $HOSTNAME$ is $HOSTSTATE$ **" \
--email "$CONTACTEMAIL$" \
--authorname "$HOSTACKAUTHORNAME$" \
--comment "$HOSTACKCOMMENT$"
Options:
-c <file> | --config <file>
-H <host> | --hostname <host>
-S <service> | --servicename <host>
-n <notificationtype> | --notificationtype <notificationtype>
-a <authorname> | --authorname <authorname>
-c <comment> | --comment <comment>
-s <state> | --state <state>
-e <email> | --email <email>
-l <longdatetime> | --longdatetime <longdatetime>
-o <output> | --output <output>
-u <url> | --url <url>
-m <mailsubject> | --mailsubject <mailsubject>
| --longserviceoutput <longserviceoutput>
| --logfile <file>
| --loglevel <int>
-h | --help
-d | --debug
=head1 OPTIONS
=over 8
=item B<--config> F<file>
Use configfile F<file> instead of default F</etc/nagios/send_mail.cfg>. This config file is a standard ini-file and
can contain the following values:
[global]
# please fill in at least these settings:
mailhost=localhost
maildomain=example.com
mailfrom=User for Nagios <nagios@example.com>
mailtimeout=30
# those settings are optional:
logfile=/var/log/nagios/mail.log
mailsubject=** Nagios Notification **
mailuser=mailserver_username
mailpassword=mailserver_password
loglevel=2
debug=0
=item B<--hostname> F<HOST>
Same as $HOSTNAME$ in Nagios.
(Example: "myhost.example.com")
=item B<--servicename> F<SERVICEDESC>
Same as $SERVICEDESC$ in Nagios.
(Example: "MySQL Service")
=item B<--notificationtype> -F<NOTIFICATIONTYPE>
Same as $NOTIFICATIONTYPE$ in Nagios.
(Example: "PROBLEM")
=item B<--authorname> F<author>
Same as $SERVICEACKAUTHORNAME$ resp. $HOSTACKAUTHORNAME$ in Nagios.
(Example: "Nagios Admin")
=item B<--comment> F<comment>
Same as $SERVICEACKCOMMENT$ resp. $HOSTACKCOMMENT$ in Nagios.
(Example: "too late to fix")
=item B<--state> F<state>
Same as $SERVICESTATE$ resp. $HOSTSTATE$ in Nagios.
(Example: "CRITICAL")
=item B<--email> F<email@address>
Same as $CONTACTEMAIL$ in Nagios.
(Receiver of the notification. Example: "foo@bar.com")
=item B<--longdatetime> F<longdatetime>
Same as $LONGDATETIME$ in Nagios.
(Example: "Wed Jan 25 22:00:00 CET 2012")
=item B<--output> F<output>
Same as $SERVICEOUTPUT$ resp. $HOSTOUTPUT$ in Nagios.
(Example: "Cant connect to local MySQL server")
=item B<--longserviceoutput> F<longserviceoutput>
Same as $LONGSERVICEOUTPUT$ in Nagios.
(Example: "Maybe the service died")
=item B<--url> L<https://$nagioshost/nagios/cgi-bin/extinfo.cgi>
URL to extinfo.cgi - the rest will be filled automatically with the given values above.
(Example: "https://nagios.example.com/nagios/cgi-bin/extinfo.cgi")
=item B<--mailsubject> F<mailsubject>
The subject line of the Email.
(Example: "Time to go home")
=back
=head1 DESCRIPTION
Instead of using the standard printf commandline given by Nagios, you can use this script to generate
notification Emails with Nagios.
This script will take care of unset variables and adds the ability to format the output in your way.
=head1 COPYRIGHT
=over 4
=item Copyright 2012 Lars Vogdt <lrupp@suse.de>.
This program is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
=back
=cut