#!/usr/bin/perl

#
# Author: Matt Judge
#   Date: 03/09/08
#   Desc: Nagios plugin to check the mail queue length (with specific domain checks)
#

use strict;

use Getopt::Long;
use lib "/usr/lib64/nagios/plugins";
use utils qw (%ERRORS &print_revision &support);

my $MAILQ      = "/usr/bin/mailq";

my $PROGNAME   = "check_mailq";

#
# Domains we should especially look out for
#
my %my_domains = ('informa.com' => 0,
                  'tandf.co.uk' => 0);

#
# Place to store the reason a message is in the queue still
#
my %errors     = ();

#
# Get any options passed via the command line
#
my ($opt_w, $opt_c, $opt_v, $opt_h, $opt_lc, $opt_lw);
Getopt::Long::Configure('bundling');
GetOptions ( "W=f" => \$opt_lw, "local-warn"      => \$opt_lw,
             "C=f" => \$opt_lc, "local-critical"  => \$opt_lc,
             "h"   => \$opt_h,  "help"            => \$opt_h,
             "v"   => \$opt_v,  "verbose"         => \$opt_v,
             "w=f" => \$opt_w,  "warning-count"   => \$opt_w,
             "c=f" => \$opt_c,  "critical-count"  => \$opt_c);
 
#
# Set the defaults (if not defined already)
#
$opt_w  = 2000 unless defined ($opt_w);
$opt_c  = 5000 unless defined ($opt_c);
$opt_lw = 300 unless defined ($opt_lw);
$opt_lc = 500 unless defined ($opt_lc);

if ( defined $opt_h )
{
  print "\nUsage:\n";
  print " $PROGNAME: [-w <warning threshold>] [-c <critical threshold>]\n";
  print " $PROGNAME: [-h | --help]    (what you are reading now)\n";
  print " $PROGNAME: [-v | --verbose] (provides a summary of error messages)\n\n";

  exit $ERRORS{'OK'};
}

#
# Count the messages in the queue
#
my $count = 0;
my $cmd   = $MAILQ;
open INP, "$cmd |";
while ( <INP> )
{
  #0F804A12BB     5571 Tue Sep  2 09:27:31  alerts@informaworld.com
  #(host mail2.ulsop.ac.uk[194.66.95.40] said: 450 4.1.1 Authentication process failed. (in reply to RCPT TO command))
  #                                         paulo.santos@ulsop.ac.uk

  next if /^$/;

  if ( /\S+\s+\d+\s+\S+\s+\S+\s+\d+\s+\d\d:\d\d:\d\d\s+\S+/ )
  {
    # Start of entry (recipient to)
    if ( defined $my_domains{$1} )
    {
      # One of our domains has been found in the run queue.
      $my_domains{$1}++;
    }
    $count++;
  }
  elsif ( /\S+\@(\S+)/ )
  {
    # End of entry (mail from)
  }
  elsif ( /: ([^:]*)\)$/ )
  {
    if ( defined $errors{$1} )
    {
      $errors{$1}++;
    }
    else
    {
      $errors{$1} = 1;
    }
  }
}

#
# If they requested verbosity, then show them the reasons why messages are stuck in the queue.
#
if ( defined $opt_v )
{
  sub hashValueDescendingNum
  {
    $errors{$b} <=> $errors{$a};
  }

  foreach my $key ( sort hashValueDescendingNum (keys(%errors)) )
  {
    printf "%d\t%s\n", $errors{$key}, $key;
  }
}

#
# Define everything as being OK.
#
my $result = "OK";
my $mesg   = "";

#
# Check our domains are not clogged.
#
foreach my $key ( keys(%my_domains) )
{
  if ( $my_domains{$key} > $opt_lc )
  {
    $result = "CRITICAL";
    $mesg  .= $my_domains{$key} . " messages" . (($my_domains{$key} == 1 ) ? "" : "s") . " in the queue for $key. ";
  }
  elsif ( $my_domains{$key} > $opt_lw )
  {
    $result = "WARNING";
    $mesg  .= $my_domains{$key} . " messages" . (($my_domains{$key} == 1 ) ? "" : "s") . " in the queue for $key. ";
  }
}

#
# Do some processing of the data
#
if ( $count > $opt_c )
{
  $result = "CRITICAL";
}
elsif ( $count > $opt_w )
{
  $result = "WARNING" unless $ERRORS{$result} > $ERRORS{'WARNING'};
}

print "MAIL $result: $count message" . (($count == 1 ) ? "" : "s") . " in the mail queue.\n";
exit $ERRORS{$result};


