HiveBrain v1.2.0
Get Started
← Back to all entries
patternhtmlMinor

Nagios service alert HTML email builder

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
nagiosemailbuilderservicealerthtml

Problem

I have a well functioning Nagios Core system set up. I wanted to make our alerts both easier to read pertinent information quickly as well as provide additional details from custom host and service variables. While I have touched on Perl in the past this is my first real Perl script. The larger portion of CSS and HTML structure com from fm4dd.com. The email logic was taken from the Mail::Sendmail documentation FAQ.

`#!/usr/bin/perl
use strict;
use warnings;
use Getopt::Long;
use Mail::Sendmail;
use MIME::QuotedPrint;
use HTML::Entities;

my $notificationType = '';
my $hostAlias = '';
my $hostAddress = '';
my $serviceDescription = '';
my $serviceState = '';
my $eventDateTime = '';
my $serviceOutput = '';
my $verbose = 0;
my $companyName = 'My Company';
my %ancillaryValues = ();

##############################
# Handle command line options
##############################

GetOptions(
'notificationType=s' => \$notificationType,
'hostAlias=s' => \$hostAlias,
'hostAddress=s' => \$hostAddress,
'serviceDescription=s' => \$serviceDescription,
'serviceState=s' => \$serviceState,
'eventDateTime=s' => \$eventDateTime,
'serviceOutput=s' => \$serviceOutput,
'optional=s' => \%ancillaryValues,
'verbose' => \$verbose
);

##############################
# CSS for mail
##############################

(my $style = qq(
!
! body {text-align: center; font-family: Verdana, sans-serif; font-size: 10pt;}
! img.logo {float: left; margin: 10px 10px 10px; vertical-align: middle}
! img.link {float: right; margin: 0px 1px; vertical-align: middle}
! table.fixed {width: 600px; text-align:center; margin-left: auto; margin-right: auto; border: 1px solid black; table-layout:fixed;}
! th {white-space: nowrap; width: 180px;}
! table.fixed td {word-wrap:break-word;}
! th.even {background-color: #D9D9D9;}
! td.even {background-color: #F2F2F2;}
! th.odd {background-col

Solution

This is mostly about style.

-
Indent and align your code properly. This will save you a lot of time later when you have to go back to change stuff.

my $notificationType   = '';
my $hostAlias          = '';
my $hostAddress        = '';
my $serviceDescription = '';
my $serviceState       = '';
my $eventDateTime      = '';
my $serviceOutput      = '';
my $verbose            = 0;
my $companyName        = 'My Company';
my %ancillaryValues    = ();


This is much easier to read as the zig-zag you have there. The same goes for the GetOptions call (though I think that's just the real tabs confusing SO). If you don't want to do this yourself, take a look at perltidy. It's an auto-indentation tool that does this for you. It's highly configurable and integrates nicely into almost all editors or IDEs.

-
You don't need to escape double quotes "" in strings that you built with qq(). It's horrible to read with all the backslashes. Get rid of them.

(my $serviceHTMLTable = qq(
    !
    !    Nagios Monitoring System Notification


-
You can use say instead of print "\n". It's a built-in that needs to be enabled by use feature 'say'; at the top of your program, with the other pragmas.

say "Time time is: ", time;


Note that you don't need the parenthesis on the time call. Also, print and say take an argument list. You can concatenate all string-parts into one argument with ., but you don't have to. I prefer the comma , notation.

-
The canonical way to name variables and subs in Perl is all lower case, snake case.

my $notification_type   = '';
my $host_alias          = '';

sub build_html_content { ... }


I know GetOptions doesn't do that, but you still should. It's also easier to read.

There really isn't anything wrong with your program. You have verbose names for stuff, you have good comments that not only say what is going on, but often also explain why. Well done.

If you did want to use different modules, I would take a look at a templating system. There are lots of lightweight ones, but it's not really needed. This is so short that it's fine.

For your email, you could go with considerably less code by using Email::Stuffer. It does everything for you with basically the same underlying stuff, just way easier to use.

If you don't intend to change the CSS, you could get rid of that post-processing of the block of CSS, and instead include it already minified. Add a comment on how to create that, and add the raw source plus the code you used to minify in the __END__ section as documentation. That will make the pure code easier to read and save some (negigible) time during execution. That could look like this:

my $style = q(body{text-align:center;fo...); # minified, see below

# ...

__END__
# Use this program to create the minified version. 
# Copy into a new script, alter and run, then replace the minified stuff above.
use strict;
use warnings;
use Foo::CSS::Minifier; # I made that up

Foo::CSS::Minifier->new->minify(<<CSS);
body {text-align: center; fo...
# more css here
CSS

Code Snippets

my $notificationType   = '';
my $hostAlias          = '';
my $hostAddress        = '';
my $serviceDescription = '';
my $serviceState       = '';
my $eventDateTime      = '';
my $serviceOutput      = '';
my $verbose            = 0;
my $companyName        = 'My Company';
my %ancillaryValues    = ();
(my $serviceHTMLTable = qq(
    !<table class="fixed">
    !    <tr><th colspan="2" class="header">Nagios Monitoring System Notification</th></tr>
say "Time time is: ", time;
my $notification_type   = '';
my $host_alias          = '';

sub build_html_content { ... }
my $style = q(body{text-align:center;fo...); # minified, see below

# ...

__END__
# Use this program to create the minified version. 
# Copy into a new script, alter and run, then replace the minified stuff above.
use strict;
use warnings;
use Foo::CSS::Minifier; # I made that up

Foo::CSS::Minifier->new->minify(<<CSS);
body {text-align: center; fo...
# more css here
CSS

Context

StackExchange Code Review Q#148647, answer score: 2

Revisions (0)

No revisions yet.