#!/usr/bin/perl -w

use strict;
use lib "/usr/local/nagios/libexec";
use utils qw(%ERRORS $TIMEOUT &print_revision);
use Getopt::Long;


# globals
use vars qw(
  $PROGNAME $VERSION $opt_version $opt_help $opt_host $opt_from $opt_to $opt_pass $opt_user $opt_warn $opt_timeout $opt_mailnbr $sender $opt_verbose $cpt $pb $opt_sleep);

# init options

$PROGNAME       = 'check_mail.pl';
$VERSION        = '0.1';
$opt_version    = undef;
$opt_help       = undef;
$opt_timeout    = 200;
$opt_verbose    = undef;
$opt_host       = undef;
$opt_warn       = undef;
#$opt_crit       = undef;
$opt_from	= undef;
$opt_to		= undef;
$opt_pass	= undef;
$opt_sleep	= undef;

# get options
Getopt::Long::Configure('bundling');
GetOptions(
  'V|version'         => \$opt_version,
  'h|help'            => \$opt_help,
  'T|timeout=i'       => \$opt_timeout,
  'v|verbose+'        => \$opt_verbose,
  'H|host=s'          => \$opt_host,
  'w|warning=s'       => \$opt_warn,
  #'c|critical=s'      => \$opt_crit,
  'n|mailnbr=i'       => \$opt_mailnbr,
  'f|from=s'        => \$opt_from,
  't|to=s'          => \$opt_to,
  'u|user=s'          => \$opt_user,
  'p|pass=s'          => \$opt_pass,
  's|sleep=i'          => \$opt_sleep,

) or do {
  print_usage();
  exit($ERRORS{'UNKNOWN'});
};

if($opt_version) {
  print_version();
  exit($ERRORS{'UNKNOWN'});
}

if($opt_help) {
  print_help();
  exit($ERRORS{'UNKNOWN'});
}

if(!$opt_host) {
  print "Host [Server mail] option not given\n";
  print_usage();
  exit($ERRORS{'UNKNOWN'});
}

if(!$opt_pass) {
  print "POP password option not given\n";
  print_usage();
  exit($ERRORS{'UNKNOWN'});
}


if(!$opt_from) {
  print " Sender address option not given\n";
  print_usage();
  exit($ERRORS{'UNKNOWN'});
}


if(!$opt_to) {
  print "Recipient address option not given\n";
  print_usage();
  exit($ERRORS{'UNKNOWN'});
}

if(!$opt_user) {
  print "User option not given\n";
  print_usage();
  exit($ERRORS{'UNKNOWN'});
}

if(!$opt_warn) {
  print "Warning option not given\n";
  print_usage();
  exit($ERRORS{'UNKNOWN'});
}

if(!$opt_mailnbr) {
  print "Number of mail option not given\n";
  print_usage();
  exit($ERRORS{'UNKNOWN'});
}

if(!$opt_sleep) {
  print "sleep option not given\n";
  print_usage();
  exit($ERRORS{'UNKNOWN'});
}

if($opt_warn > $opt_mailnbr) {
  print " Warning option must be < than Number of mail send\n";
  print_usage();
  exit($ERRORS{'UNKNOWN'});
}

# set alarm in case we hang
$SIG{ALRM} = sub {
  print "CRITICAL - Timeout after $opt_timeout seconds\n";
  exit($ERRORS{'CRITICAL'});
};
alarm($opt_timeout);


######################################################################### 

# we send the mails to the mail server we want to check 

for ($cpt=0; $cpt<$opt_mailnbr; $cpt++) {

use Mail::Sender;

$sender = new Mail::Sender {
                smtp => $opt_host,
                from => $opt_from,
                on_errors => undef,
        }
                or die "Can't create the Mail::Sender object: $Mail::Sender::Error\n";
        $sender->Open({
                to => $opt_to,
                cc => '',
                subject => 'testmail'
        })
                or  die "Can't open the message: $sender->{'error_msg'}\n";
		      
			
        $sender->SendLineEnc("mail check server 1");
        $sender->Close()
                or die "Failed to send the message: $sender->{'error_msg'}\n";
if($opt_verbose) {printf "mail $cpt send\n";}
sleep(1);

}


###################################ON ATTEND################################

sleep($opt_sleep);

##################################RECEPTION MAIL###########################

use warnings;
use strict;

use Net::POP3;

my $subject_width = 50;
my $from_width    = 80;

my $mailserver = $opt_host;
my $username   = $opt_user;
my $password   = $opt_pass;

chomp ($mailserver, $username, $password);

my $pop3    = Net::POP3->new($mailserver)       or die "Failed to connect to $mailserver";
my $tot_msg = $pop3->login($username,$password) or die "Failed to authenticate $username";

if($opt_verbose) {printf "There is (are) $tot_msg mail(s) in the box\n";}

if ($tot_msg > $opt_mailnbr) { 
	my $pb = 1; #Attention : probleme arrive mail tardif (purge necessaire)
	if($opt_verbose) {printf "pb =1\n";}
}

my $nagios = 0;

foreach my $msg_id (1 .. $tot_msg) {
  my $header = $pop3 -> top($msg_id, 0);
  my ($subject, $from, $status) = analyze_header($header);
  my $delete = "";
  if ($subject eq 'testmail') {
    $delete = 'del';
    $pop3->delete($msg_id); # not really deleted until quit is called
    if($opt_verbose) {printf "delete $msg_id \n";}
    $nagios = $nagios + 1;
  } elsif ($pb == 1) {  $delete = 'del';
    			$pop3->delete($msg_id);
			if($opt_verbose) {printf "delete $msg_id dans pb \n";}
			}
sleep (1);
}


  $pop3 -> quit;  # deleted messages are deleted now
  
  if ($nagios == $opt_mailnbr) {
     	print ("Server State OK : all mail sent ($opt_mailnbr), fetched and deleted\n");
	exit $ERRORS{'OK'};
	} 
	elsif ($nagios < $opt_mailnbr && $nagios > $opt_warn) {
		print ('Warning : '.$opt_mailnbr.' sent, '.($opt_mailnbr - $nagios).' lost');
		exit $ERRORS{'WARNING'};
		}
		elsif ($nagios <= $opt_warn) { 
			print ('Server State Critical : '.$opt_mailnbr.' sent, '.($opt_mailnbr - $nagios).' mail lost'); 
			exit $ERRORS{'CRITICAL'}; 
			}
			else { 
				print ('Warning : delayed emails, purge done => Congestion ?? '.($nagios - $opt_mailnbr).' delayed');
				exit $ERRORS{'WARNING'};
			      }
  
	

##################################FONCTIONS###########################

sub analyze_header {
  my $header_array_ref = shift;

  my $header = join "", @$header_array_ref;
  my ($subject) = $header =~ /Subject: (.*)/m;
  my ($from   ) = $header =~ /From: (.*)/m;
  my ($status ) = $header =~ /Status: (.*)/m;


  if (defined $status) {
    $status = "Unread" if $status eq 'O';
    $status = "Read"   if $status eq 'R';
    $status = "Read"   if $status eq 'RO';
    $status = "Ne    $status = "-";w"    if $status eq 'NEW';
    $status = "New"    if $status eq 'U';
  }
  else {
    $status = "-";
  }

  return ($subject, $from, $status);
} 


sub print_usage {
  my $tab = ' ' x length($PROGNAME);
  print <<EOB
Usage:
 $PROGNAME -H host -f addsender -t addrecpt -u user -p poppass -n nbrmail -w warningvalue [-v]
 $PROGNAME --version
 $PROGNAME --help
EOB
}

sub print_version {
  print_revision($PROGNAME, $VERSION);
}

sub print_help {
  print_version();
  print <<EOB;

Send mail to specified server and check them

EOB

  print_usage();
  print <<EOB;

Required Arguments:
 -H, --host=HOST
    	The name or address of the mail server.
 -f, --from 
	The sender address 
 -t, --to 
	The recipient address
 -u, --user
	The user
 -p, --pass
	The pop password
 -w, --warning 
	The warning value < number of mail send
 -n; --mailnbr
	The number of mail send to the server
 -v; --verbose
	Verbose, more informations
 -T; --timeout
	Number of seconds to wait for a response
 -s; --sleep
	Time to sleep between the send and the reception of mail

By BleDi
#bledi51 at hotmail.com
5/7/2007

EOB
}
