#!/usr/bin/python

import os
import sys

import vmailmgr
import ldap
import email.Parser

smtp_server = "<IP of the server sending the bounce>"
me = "<same as the content of the <~control/me>"

ldap_server = "<IP of your LDAP server>"
ldap_port = "389"
ldap_user = "cn=admin,dc=root" # or whatever you need to connect to LDAP
ldap_password = "<Your LDAP password>"
ldap_dn='cn=%s,ou=%s,ou=clients,ou=people,dc=root' # the LDAP root of your users.

# The list of domains using ldap (we have few ldap domains and lots of vmailmgr)
ldap_domains = [
	'domain1.com',
	'domain2.com',
]

def log (*param):
	sys.stderr.write('qmail-user %d: ' % os.getpid())
	sys.stderr.write(*param)
	sys.stderr.write('\n')
	sys.stderr.flush()

def vmailmgr_exists (username,domain):
	# Check catchall
	try:
		vmailmgr.commands.lookup(domain,'+','an-invalid-password')
		log('warning: the catchall for '+domain+' has our password')
		# The improbabable case where the password was right !
		return True
	except vmailmgr.daemon.Error, error:
		message = str(error)

		if message == "Incorrect password":
			log('the domain '+domain+' has a catchall')
			return True
		elif message == "Invalid or unknown domain name: " + domain:
			log('the domain '+domain+' is not a vmailmgr domain (must be a domain we relay for)')
			return True
		elif message == "Invalid or unknown virtual user":
			# No catchall, need to check the username
			pass
		else:
			log('warning: triggered change in the vmailmgr api checking catchall for '+domain+', failing open')
			log('debug: catchall: ' + message)
			return True

	# Check user
	try:
		vmailmgr.commands.lookup(domain,username,'an-invalid-password')
		log('warning: improbable valid password for '+username+'@'+domain)
		return True
	except vmailmgr.daemon.Error, error:
		message = str(error)

		if message == "Incorrect password":
			return True
		elif message == "Invalid or unknown virtual user":
			return False
		else:
			log('warning: triggered change in the vmailmgr api checking for '+username+'@'+domain+', failing open')
			return True

def ldap_exists (username,domain):
	try:
		l = ldap.initialize('ldap://%s:%s' % (ldap_server, ldap_port))
		l.simple_bind_s(ldap_user, ldap_password)
		dn=ldap_dn % (username,domain)
		search='(objectclass=*)'
		r = l.search_s(dn, ldap.SCOPE_SUBTREE, search)
		if len(r) == 0:
			return False
		return True
	except:
		log('could not connect to ldap')
		return True

found = False
emails = os.environ['QMAILRCPTS'].rstrip().split('\n')

for email in emails:
	log('checking ' + email)
	try:
		username,domain = email.split('@')
	except:
		continue
	
	if domain in ldap_domains:
		exists = ldap_exists
	else:
		exists = vmailmgr_exists

	if exists(username,domain):
		found = True
		break

if found:
	sys.exit(0)

# Comment this line to generate a bounce instead of refusing the mail during the SMTP conversation 
sys.exit(31)

log('blocking ' + ' '.join(emails))

try:
	from email.MIMEText import MIMEText
	from email.FeedParser import FeedParser
	from smtplib import SMTP
	import time

	user = os.environ['QMAILUSER']
	domain = os.environ['QMAILHOST']

	recipient = user + '@' + domain
	message = """
Hi. This is the qmail-user program at %s
I'm afraid I wasn't able to deliver your message to the following addresses.
This is a permanent error; I've given up. Sorry it didn't work out.

%s
Invalid or unknown email address(es)

--- Below this line is a copy of the message.
""" % (me,', '.join(emails))

	# Be carefull what you aee your DATALIMIT to !
	message += "".join(sys.stdin.readlines())

	msg = MIMEText(message)
	msg['Subject'] = "failure notice"
	msg['From'] = "mailder-daemon@"+me
	msg['To'] = recipient
	msg['Date'] = time.strftime("%a, %d %b %Y %H:%M:%S %Z",time.localtime())
	# msg['In-Reply-To'] =  ""

	smtp = SMTP(smtp_server,25,smtp_server)
	smtp.sendmail("<>",recipient,msg.as_string())
	smtp.close()

	log('bounce sent')
except:
	log('bounce generation failed, accepting mail')
	log(message)
	sys.exit(0)
	#log('bounce generation failed, refusing mail')
	#sys.exit(31)

sys.exit(99)
