#!/usr/bin/python

import os
import sys
import time
import socket

# The possible names MX will point to get here
#
#  0: all if fine nothing to see
# 31: Mail server permanently refuses to send the message to any recipients. (Not used by qmail-queue, but can be used by programs offering the same interface.)
# 71: Mail server temporarily refuses to send the message to any recipients. (Not used by qmail-queue.)

names = ["mx-secondary.exa-networks.co.uk"]

# http://www.ezmlm.org/man/man8/qmail-queue.8.html

if os.environ.has_key('TCPLOCALHOST'):
	names.append(os.environ['TCPLOCALHOST'])
names = set(names)

# helpers

def log (*param):
	sys.stderr.write('mx: ')
	sys.stderr.write(*param)
	sys.stderr.write('\n')
	sys.stderr.flush()

def out (code,*param):
	log(*param)
	sys.exit(code)

# Get all environment variable

try:
	import DNS
	DNS.timeout = 2
except ImportError:
	out(0,'can not import pydns, failing open')

# Check time and perform according action

dns_check = os.environ.get('BACKUP_MX_DNS',None)

if dns_check is None:
	sys.exit(0)

recipients = os.environ['QMAILRCPTS'].strip().lower().split('\n')
domain = recipients[0].lower().split('@')[-1]

mxs = []
try:
	request = DNS.Request(name=domain, server='127.0.0.1', qtype='MX')
	answers = request.req().answers

	m = []
	for answer in answers:
		if answer.has_key('data'):
			m.extend((answer['data'],))
#		else:
#			request = DNS.Request(name=domain, server='127.0.0.1', qtype='A')
#			answers = request.req().answers
#
#			for answer in answers:
#				if answer.has_key('data'):
#					log('A record is %s' % str(answer))
#					m.extend((9999,answer['data']))
	mxs.append(m)
except DNS.DNSError, e:
	exp = str(e)
	if exp == 'Timeout':
		out(71,'DNS resolution for %s failed.' % domain)
	out(0,'failure during DNS resolution failing open')
except:
	# if something worng happens it mean that we should let it pass (even in case of failure)
	out(0,'failure during DNS resolution failing open')

if not mxs:
	out(71,'DNS resolution for %s does not provide MXs.' % domain)

my_priority = 99999
lowest_priority = 99999
for m in mxs:
	for priority, server in m:
		if server in names:
			my_priority = priority
			continue
		if priority < lowest_priority:
			lowest = priority

# Qmail has a config issue in the first place to let the domain in !
if my_priority == 99999:
	out(31,'I am not listed as an MX record for %s, refusing the mail.' % (", ".join(recipients)))

servers = []
for m in mxs:
	for priority, server in m:
		if priority <= my_priority and server not in names:
			servers.append(server)

if servers == []:
	out(31,'I am a backup MX server not a primary mail server refusing mail for %s' % (", ".join(recipients)))

connected = None
codes = []
code = 'n/a'

for server in servers:
	try:
		s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
		s.settimeout(2.0)
		s.connect((server, 25))
	except:
		codes.append('connection failed')
		if connected == None:
			connected = False
		continue
	try:
		n = s.recv(1024)
		code = n[:3]
		if code.isdigit():
			if n[0] == '2':
				connected = 71
			if n[0] == '4':
				connected = 71
			if n[0] == '5':
				connected = 31
		codes.append(code)
		s.send('quit\n')
		s.close()
		break
	except:
		codes.append('transfer issue')
		if connected == None:
			connected = False

if connected in [31,71]:
	# we could connect ... we are under spam ..		
	out(connected,'the main MX servers are working (%s), refusing to secondary with code %s for %s' % (code,{71:'4xx',31:'5xx'}[connected],", ".join(recipients)))

# deliver valid email
out(0,'look like a genuine need for backup mx (%s) for %s, passing' % (", ".join(codes),", ".join(recipients)))
