Operating System - HP-UX
1748119 Members
3317 Online
108758 Solutions
New Discussion

Route emails in a perl script

 
allanm77
Frequent Advisor

Route emails in a perl script

HI All,

 

Have a perl script which parses a file (FILE1 has a list of alerts) and sends an email in certain format.

Only thing I need is that for VIPS/hosts having the word test in it should send the email to test@foobar.com
and VIP/host having the word dev (eg. dev.corp.foobar.com) in it  to dev@foobar.com
and VIPs having the name prod in it to prod@foobar.com. The subject needs to be different for each one.

FILE1:

***** Alert *****

Notification Type: PROBLEM

Service: Appsname_2333_env1_region
Host: vip-scv.corp.foobar.com
Address: x.x.x.x
State: CRITICAL

Date/Time: Mon Aug 8 15:50:02 EDT 2011

Additional Info:

CRITICAL - Socket timeout after 3 seconds

Console http://foobar.com/nagios/index.php
 ***** Alert *****

Notification Type: PROBLEM

Service: DiffAppsname_8552_env2_region2
Host: vip2-scv.corp.foobar.com
Address: x.x.x.x
State: CRITICAL

Date/Time: Mon Aug 8 15:50:02 EDT 2011

Additional Info:

CRITICAL - Socket timeout after 3 seconds

Console http://foobar.com/nagios/index.php

 




PERL SCRIPT:


#!/usr/bin/perl -w

use strict;

my ($apps,$email,$host);
open(HM,"<","/var/tmp/email") or die "Fail- $!\n";
open(WM,">","/var/tmp/email_text") or die "Fail- $!\n";

while(<HM>) {
        chomp;
        $apps = $1 if /Service:(.*)/;
        $host = $1 if /^Host:(.*)/;
        if (/Date\/Time:(.*)/) {
                printf WM "%s:%s:%s\n",$apps,$host,$1;  
        }
}
seek HM,0,0;
print WM <HM>;

$email='mail -s "alerts from past 4 mins" user@foobar.com < /var/tmp/email_text 2>/var/tmp/email_err';
system($email);

if ( $? ne 0 ) {
         die "Failure - while sending email. Please check file /tmp/email_err \n";
}

close(WM);
close(HM);

unlink "/tmp/email" or warn "Could not unlink email: $!";;
unlink "/tmp/email_text" or warn "Could not unlink email_text: $!";;

 

Thanks,

Allan.

10 REPLIES 10
Hein van den Heuvel
Honored Contributor

Re: Route emails in a perl script

I would add an associative array to the perl script to map hosts to email addresses.

As you process a host, start with a generic Email address.

Replace by a specific one,  if it matches a key in the array. 

Glue the selected email address in the email command.

 

Untested example below.

Hope it works...

Hein

 

#!/usr/bin/perl -w
use strict;
my %email_map = (dev => 'dev@foobar.com', test => 'test@foobar.com', prod=> 'prod@foobar.com');

my ($apps,$email,$host, $email_address);

open(HM,"<","/var/tmp/email") or die "Fail- $!\n";

open(WM,">","/var/tmp/email_text") or die "Fail- $!\n";

 

while(<HM>) {        

chomp;

       $apps = $1 if /Service:(.*)/;

        $host = $1 if /^Host:(.*)/; 

       if (/Date\/Time:(.*)/) {

                printf WM "%s:%s:%s\n",$apps,$host,$1;

         }

}

seek HM,0,0;print WM <HM>;
$email_address = 'user@foobar.com';

for (keys %email_map) { $email_adress = $email_map{$_} if $host =~ /^\s*$_/;

$email='mail -s "alerts from past 4 mins" ' . $email_adress . ' < /var/tmp/email_text 2>/var/tmp/email_err';system($email);

 

if ( $? ne 0 ) {

       die "Failure - while sending email. Please check file /tmp/email_err \n";

}

close(WM);

close(HM);
unlink "/tmp/email" or warn "Could not unlink email: $!";;

unlink "/tmp/email_text" or warn "Could not unlink email_text: $!";;

H.Merijn Brand (procura
Honored Contributor

Re: Route emails in a perl script

OK, I'll bite ...

 

use strict;
use warnings;
use Mail::Sendmail;

my $alerts = do { local ($/, @ARGV) = (undef, "alerts.txt"); <> };
my @alerts = split m/\s*\Q***** Alert *****\E\s*/ => $alerts;

my ($from, $to) = ('reporter@my.site.com', 'user@foobar.com');

my @summ;
for (@alerts) {
    my %tag = (m/^\s*(\S+)\s*:\s*(.*?)\s*$/gm) or next;
    push @summ, "$tag{Service}:$tag{Host}:$tag{'Date/Time'}\n";
    $tag{Host} =~ m/\b test \b/ix	and $to =~ s/user/test/;
    $tag{Host} =~ m/\b dev  \b/ix	and $to =~ s/user/dev/;
    $tag{Host} =~ m/\b prod \b/ix	and $to =~ s/user/prod/;
    }

sendmail ({
    To      => $to,
    From    => $from,
    Subject => "Alerts from past 4 mins",
    Message => join "\n", @summ, $alerts,
    }) or die $Mail::Sendmail::error;

 This is about what I deduced from your code. I'll leave it up to you to make the change to the subject based on the recipient.

 

What I did was

1. Read the complete alerts file. (you parsed it twice)

2. Split the alerts into chuncks

3. create a summary line for each chunk

mail the summary and the complete body to the recipient. The recipient is default 'user' and is changed on the first host that matches any of the threee criteria you asked for. 


 

Enjoy, Have FUN! H.Merijn
allanm77
Frequent Advisor

Re: Route emails in a perl script

Thanks Hein,

 

Can the subject append the word dev, test & prod to the subject line?

 

Its currently not sending the alerts to specific email ids but rather to the default one.

 

It would be great if it can.

 

Regards,

Allan.

Hein van den Heuvel
Honored Contributor

Re: Route emails in a perl script

Sure...

 

Again untested...

 

 

my $subject = 'alerts from past 4 mins';

$email_address = 'user@foobar.com';

for (keys %email_map) {

      if ( $host =~ /^\s*$_/ ) {

            $email_adress = $email_map{$_}; 

            $subject .= " from $_";

}


$email = "mail -s  \"$subject \"  $email_adress . < /var/tmp/email_text 2>/var/tmp/email_err";

system($email);

 

fwiw,

Hein

allanm77
Frequent Advisor

Re: Route emails in a perl script

Thanks again!

Not getting any emails now :(

Earlier I got the same email four times to the default user.

Can you test out at your end and see what the problem could be... I have given the sample file above.

Thanks,
Allan.
James R. Ferguson
Acclaimed Contributor

Re: Route emails in a perl script

Hi:

 

Hein's original post(s) mis-spelled "$email_address" [ which the 'strict' pragma would have told you ] and as an untested post, lacked a closing brace.  HIS SCRIPT should (likely) be:

 

#!/usr/bin/perl
use strict;
use warnings;
my %email_map = (dev => 'dev@foobar.com', test => 'test@foobar.com', prod=> 'prod@foobar.com');

my ($apps,$email,$host, $email_address);
open(HM,"<","/var/tmp/email") or die "Fail- $!\n";
open(WM,">","/var/tmp/email_text") or die "Fail- $!\n";

while(<HM>) {
    chomp;
    $apps = $1 if /Service:(.*)/;
    $host = $1 if /^Host:(.*)/;
    if (/Date\/Time:(.*)/) {
        printf WM "%s:%s:%s\n",$apps,$host,$1;
    }
}
seek HM,0,0;print WM <HM>;
my $subject = 'alerts from past 4 mins';
$email_address = 'user@foobar.com';
for (keys %email_map) {
     if ( $host =~ /^\s*$_/ ) {
         $email_address = $email_map{$_};
         $subject .= " from $_";
     }
     $email='mail -s "alerts from past 4 mins" ' . $email_address . ' < /var/tmp/email_text 2>/var/tmp/email_err';system($email);

    if ( $? ne 0 ) {
           die "Failure - while sending email. Please check file /tmp/email_err \n";
    }
}

close(WM);
close(HM);
unlink "/tmp/email" or warn "Could not unlink email: $!";
unlink "/tmp/email_text" or warn "Could not unlink email_text: $!";

 Regards!

 

...JRF...

allanm77
Frequent Advisor

Re: Route emails in a perl script

Thanks JRF!

Some of it I had figured, also I am a little concerned about the unlinks down below, that it deletes the files even though the program is successful or not.

Regards,
Allan.
James R. Ferguson
Acclaimed Contributor

Re: Route emails in a perl script


@allanm77 wrote:
I am a little concerned about the unlinks down below, that it deletes the files even though the program is successful or not.

Hi Alan:

 

First, thank Hein.  I just fixed up some of his untested syntax.  As for the unlink()'s, you don't know that the mail will ever be delivered or not, so everything is on-faith.  Because the files in question live in '/var/tmp', the inference is that they aren't critical to anything but this process.

 

If, for whatever reason, you feel that removing them isn't what you want to do, you could simply rename() them, leaving their eventual cleanup to a routine purge (with 'find') of '/var/tmp' .

 

In fact, you actually have used to different paths in your script!  You 'open()' in '/var/tmp' but 'unlink()' from '/tmp'.   A better way to avoid this is to declare variables (or constants) with the file names.  Then, by example, you could do this to rename the file or files you want to keep:

 

my $HM_name = '/var/tmp/email';
my $WM_name = '/var/tmp/email_text';

#...

my ($mon,$mday,$year) = (localtime)[4,3,5];
my $suffix = sprintf "_%02d%02d%04d", $mon+1, $mday, $year+1900;

rename $HM_name, $HM_name . $suffix;
1;

 Regards!

 

...JRF...

 

allanm77
Frequent Advisor

Re: Route emails in a perl script

Thanks Hein & JRF!

Have another question about the original perl script (from above), I want to use that on three to four different files -

/var/tmp/email & /var/tmp/email_new & /var/tmp/email_newer

with same logic and probably send to different userids with different subjects.

I tried to keep that in the same script but struggled with die statements which used to close the program if it couldn't find the one of the file.

Thanks,
Allan.