#!/usr/bin/perl
# nagios: -epn
# Don't run this plugin in the embedded perl interpreter
# It hasn't been tested this way.
#
# This plugin connects to a specified IMAP server, logs in, and
# gets the number of messages in the specified mailbox
#
############################## sgichk_imap_inboxcount ##############
my $Version='1.0';
# Date : Jun 25 2010
# Author  : Brent Bice
# Licence : GPL - http://www.fsf.org/licenses/gpl.txt
# TODO : 
#################################################################
#
# Help : ./sgichk_imap_inboxcount.pl -h
#

use IO::Socket;
use strict;
use Getopt::Long;

#my $host = "ebptmail";
#my $user = "wfmuat";
#my $pass = "Welcome1";

#my $host = "bryce";
#my $user = "sgipost";
#my $pass = "USA4ever";

my %ERRORS=('OK'=>0,'WARNING'=>1,'CRITICAL'=>2,'UNKNOWN'=>3,'DEPENDENT'=>4);

# Standard options
my $retstr = "OK";
my $perfstr = "\|";
my $retval = $ERRORS{'OK'};

my $o_host = 		undef; 	# hostname
my $o_port = 		143; 	# port
my $o_user = 		undef; 	# user
my $o_pass = 		undef; 	# password
my $o_mailbox =		"INBOX"; 	# mailbox to check
my $o_help=		undef; 	# wan't some help ?
my $o_verb=		undef;	# verbose mode
my $o_version=		undef;	# print version
my $o_warn=		undef;  # Number of messages for WARNING
my $o_crit=		undef;  # Number of messages for CRITICAL

my $o_timeout=  5; 		# Timeout (Default 5)

# functions

sub p_version { print "sgichk_imap_inboxcount version : $Version\n"; }

sub print_usage {
    print "Usage: $0 [-v] -H <host> -u <username> -p <password> [-P <port>] [ -m <mailbox> ] [-w <warn_count>] [-c <crit_count>][-t <timeout>] [-V]\n";
}

sub isnnum { # Return true if arg is not a number
  my $num = shift;
  if ( $num =~ /^(\d+\.?\d*)|(^\.\d+)$/ ) { return 0 ;}
  return 1;
}

sub help {
   print "\nSNMP Network Interface Monitor for Nagios version ",$Version,"\n";
   print_usage();
   print <<EOT;
-v, --verbose
   print extra debugging information
-h, --help
   print this help message
-H, --hostname=HOST
   name or IP address of host to check
-u, --user=username
   IMAP username
-p, --passwd=password
   IMAP password
-P, --port=PORT
   IMAP port (Default 143)
-m, --mailbox=mailbox
   Which mailbox to check (Default is INBOX)
-w, --warn=INTEGER
   Warning number of messages threshold
-c, --crit=INTEGER
   Critical number of messages threshold
-t, --timeout=INTEGER
   timeout in seconds (Default: 5)   
-V, --version
   prints version number
EOT
}

# For verbose output
sub verb { my $t=shift; print $t,"\n" if defined($o_verb) ; }

sub check_options {
    Getopt::Long::Configure ("bundling");
	GetOptions(
   	'v'	=> \$o_verb,		'verbose'	=> \$o_verb,
        'h'     => \$o_help,    	'help'        	=> \$o_help,
        'H:s'   => \$o_host,		'hostname:s'	=> \$o_host,
        'u:s'   => \$o_user,		'user:s'	=> \$o_user,
        'p:s'   => \$o_pass,		'passwd:s'	=> \$o_pass,
        'm:s'   => \$o_mailbox,		'mailbox:s'	=> \$o_mailbox,
        'w:i'   => \$o_warn,   		'warn:i'	=> \$o_warn,
        'c:i'   => \$o_crit,   		'crit:i'	=> \$o_crit,
        'P:i'   => \$o_port,   		'port:i'	=> \$o_port
    );
    if (defined ($o_help) ) { help(); exit $ERRORS{"UNKNOWN"}};
    if (defined($o_version)) { p_version(); exit $ERRORS{"UNKNOWN"}};
    if ( ! defined($o_host) ) # check host
	{ print_usage(); exit $ERRORS{"UNKNOWN"}}
    if ( ! defined($o_user) ) # check user
	{ print_usage(); exit $ERRORS{"UNKNOWN"}}
    if ( ! defined($o_pass) ) # check pass
	{ print_usage(); exit $ERRORS{"UNKNOWN"}}
}
    
########## MAIN #######

check_options();

# Check gobal timeout if snmp screws up
verb("Setting timeout: $o_timeout + 10");
alarm ($o_timeout+10);

$SIG{'ALRM'} = sub {
 print "UNKNOWN: No answer from host\n";
 exit $ERRORS{"UNKNOWN"};
};

my ($sock, @ans);

$sock = IO::Socket::INET->new(PeerAddr => $o_host,
				PeerPort => $o_port,
				Proto => "tcp",
                                Blocking => 0,
                                Type => SOCK_STREAM)
   or die "Couldn't open IMAP\n";

# Looking for
#* OK [CAPABILITY IMAP4REV1 LOGIN-REFERRALS AUTH=LOGIN] ...
my $foundLogin = 0;
while ($foundLogin == 0) {
   while (<$sock>) {
      verb ("$_\n");
      if (/OK.*CAPABILITY/) {
         $foundLogin = 1;
         last;  # Break out of loop reading from socket
      }
   }
}

verb ("");
verb ("Logging in...");
print $sock "a01 login $o_user $o_pass\n";

# looking for   a01 OK
my $foundStr = 0;
my $loginOK = 0;
while ($foundStr == 0) {
   while (<$sock>) {
      verb ("$_");
      if (/^a01 OK/) {
         $foundStr = 1;
         $loginOK = 1;
         last;
      } elsif (/^a01 NO/) {
         $foundStr = 1;
         last;
      }
   }
}

verb ("");
if ($loginOK == 1) {
   verb ("Login successful");

   my $exists = -1;
   my $recent = -1;

   # Open the Inbox and look for new messages using STATUS
   # we could specify (recent) or (unseen) instead...
   print $sock "a03 STATUS $o_mailbox (messages)\n";
   $foundStr = 0;
   while ($foundStr == 0) {
      while (<$sock>) {
         if (/MESSAGES ([0-9]+)/) {
            $exists = $1;
         } elsif (/^a03 OK/) {
            $foundStr = 1;
            last;
         }
      }
   }

   verb ("");
   verb ("Message Exists = $exists");

   if ($exists == -1) {
      $retstr = "UNKNOWN: Couldn't get message count";
      $retval = $ERRORS{'UNKNOWN'};
   } else {
      $retstr = "OK: $exists messages";
      $perfstr .= " messages=$exists\%;$o_warn;$o_crit";
   }
   if (defined ($o_warn)) {
      if ($exists > $o_warn) {
         $retstr = "WARNING: $exists messages";
         $retval = $ERRORS{'WARNING'};
      }
   }
   if (defined ($o_crit)) {
      if ($exists > $o_crit) {
         $retstr = "CRITICAL: $exists messages";
         $retval = $ERRORS{'CRITICAL'};
      }
   }

   # Now log out
   print $sock "a01 logout\n";
   $foundStr = 0;
   while ($foundStr == 0) {
      while (<$sock>) {
         if (/^a01 OK/) {
            $foundStr = 1;
            last;
         };
      }
   }
} else {
   $retstr = "UNKNOWN: Couldn't log in";
   $retval = $ERRORS{'UNKNOWN'};
}
close ($sock);

alarm(0);

print "$retstr $perfstr\n";
exit ($retval);