#!/usr/bin/env python

#
# check-pop.py - 2006.05.05 Yann Grossel
#
# python2.4 ./check-pop.py  -s 212.43.194.89 -l 'check-nagios@sri.fr.clara.net' -p 'aeh3tCj3zI' -c 'nn!/@UirKixO%,YXM?_zIT=%dZWb770f'
#
# Usage :
#
#	check-pop.py [--ssl] [--port port] -s ip -l login -p password -c pattern
#
#	There must be at least one message in the mailbox, and it must contain "pattern" on a single line.
#
#	Errors are sent to syslog.
#

# Nagios states

STATE_OK				= 0
STATE_WARNING		= 1
STATE_CRITICAL		= 2
STATE_UNKNOWN		= 3
STATE_DEPENDENT	= 4

#

import os, sys, poplib, signal, syslog, time

use_ssl		= False
port			= None
server_ip	= None
login			= None
password		= None
pattern		= None
error_msg	= ''

def get_arg(s):

	if not len(sys.argv):
		print "Missing argument after %s" % (s)
		sys.exit(STATE_UNKNOWN)

	arg, sys.argv = sys.argv[0], sys.argv[1:]

	return arg

def parse_args():

	global use_ssl, port, server_ip, login, password, pattern

	if not len(sys.argv): sys.exit(STATE_UNKNOWN)

	sys.argv = sys.argv[1:]

	while len(sys.argv) > 0:

		arg, sys.argv = sys.argv[0], sys.argv[1:]

		if arg == '--port':

			arg = get_arg(('--port'))

			try: port = int(arg)
			except:
				print "Bad port:", arg
				sys.exit(STATE_UNKNOWN)

			if port < 1 or port > 65535:
				print "Bad port:", arg
				sys.exit(STATE_UNKNOWN)

		elif arg == '--ssl':		use_ssl = True
		elif arg == '-l':			login = get_arg('-l')
		elif arg == '-p':			password = get_arg('-p')
		elif arg == '-s':			server_ip = get_arg('-s')
		elif arg == '-c':			pattern = get_arg('-c')
		else:
			print "Unknown argument '%s'" % (arg)
			sys.exit(STATE_UNKNOWN)

	if not server_ip:
		print "server_ip not specified"
		sys.exit(STATE_UNKNOWN)

	if not login:
		print "login not specified"
		sys.exit(STATE_UNKNOWN)

	if not password:
		print "password not specified"
		sys.exit(STATE_UNKNOWN)

	if not pattern:
		print "pattern not specified"
		sys.exit(STATE_UNKNOWN)

def timeout_callback(signum, frame):
	global error_msg
	error_msg = ' (timeout)'

def log_error(command, error):
	if error_msg != '': return
	msg = "pop3 server %s: %s: %s\n" % (server_ip, command, str(error))
	syslog.syslog(syslog.LOG_WARNING, msg)
	if sys.stderr.isatty(): sys.stderr.write("%s\n" % (msg))

# Main program.

parse_args()

if use_ssl and getattr(poplib, 'POP3_SSL', None) == None:
	print "Your python has no support for POP3 over SSL !"
	sys.exit(STATE_UNKNOWN)

if port == None:
	if use_ssl:	port = 995
	else:			port = 110

if use_ssl:	popclass = poplib.POP3_SSL
else:			popclass = poplib.POP3

syslog.openlog("check-pop.py", 0, syslog.LOG_USER)

signal.signal(signal.SIGALRM, timeout_callback)

start = time.time()

# Connect to the server.

signal.alarm(3)

try: server = popclass(server_ip, port)
except Exception, e:
	signal.alarm(0)
	print "Unable to connect to pop3 server%s !" % (error_msg)
	log_error("connect", e)
	sys.exit(STATE_CRITICAL)

# Send APOP to the server.

signal.alarm(5)

try: server.apop(login, password)
except Exception, e:
	signal.alarm(0)
	print "Unable to login to pop3 server%s !" % (error_msg)
	log_error("APOP", e)
	sys.exit(STATE_CRITICAL)

# STAT the mailbox.

signal.alarm(5)

try:	messages, size = server.stat()
except Exception, e:
	signal.alarm(0)
	print "STAT failed%s !" % (error_msg)
	log_error("STAT", e)
	sys.exit(STATE_CRITICAL)

signal.alarm(0)

if messages < 1:
	# No message in mailbox !
	print "Mailbox is empty !"
	sys.exit(STATE_WARNING)

# At least a message. RETR it.

signal.alarm(5)

try: response, lines, octets = server.retr(1)
except Exception, e:
	signal.alarm(0)
	print "RETR failed%s !" % (error_msg)
	log_error("RETR", e)
	sys.exit(STATE_CRITICAL)

# Try to QUIT nicely.

signal.alarm(5)

try: server.quit()
except Exception, e:
	signal.alarm(0)
	print "QUIT failed%s !" % (error_msg)
	log_error("QUIT", e)
	sys.exit(STATE_CRITICAL)

signal.alarm(0)

# Check wether the message contains the requested pattern.

found = False

for line in lines:
	if line.count(pattern) != 0:
		found = True
		break

if not found:
	print "Pattern not found in message !"
	sys.exit(STATE_WARNING)

# No problem detected.

end = time.time()

if use_ssl: print "SSL POP3 transaction OK (%.3f seconds)" % (end - start)
else:			print "POP3 transaction OK (%.3f seconds)" % (end - start)

sys.exit(STATE_OK)

# vim: set ts=3 sw=3:
