#!/usr/local/bin/python2.4 # Vmail MGR Users Check - Qmail SPP Plugin # (c) 2006 Catalin Constantin - Dazoot import pwd, sys, os, cdb class NoSuchDomain(Exception): pass class InvalidEmail(Exception): pass class InvalidVmailMgrDomain(Exception): pass class VmailMgr: def __init__(self): self.read_virtualdomains() def read_virtualdomains(self): domains={} f=file("/var/qmail/control/virtualdomains", "rt") line=f.readline() while(line): line=line.replace("\n","").replace("\r","").strip() p=line.split(":") domain=p[0].lower() local_user=p[1] domains[domain]=local_user line=f.readline() f.close() self.domains=domains return self.domains def local_check(self, email_user, email_domain): p=email_user.split("-") system_user=p[0] # check /var/qmail/alias .qmail files self.home_dir="/var/qmail/alias" for i in range(0, min(len(p), 5)): if self.is_dotqmail(p, i): return True # check if we have a system user try: pwd_entry=pwd.getpwnam(system_user) except: return False home_dir=pwd_entry[5] # check if there is a home dir for this user if not os.path.isdir(home_dir): return False # check if he has a Maildir folder if os.path.isdir(os.path.join(home_dir, "Maildir")): if email_user==system_user: return True # check if there is a .qmail file (no - dash) if os.path.isfile(os.path.join(home_dir, ".qmail")): if email_user==system_user: return True # check if there is a .qmail-default file if os.path.isfile(os.path.join(home_dir, ".qmail-default")): if email_user!=system_user: return True # check if there are .qmail-... files in his home_dir self.home_dir=home_dir for i in range(0, min(len(p)-1, 5)): if self.is_dotqmail(p[1:], i): return True # no match return False def check(self, email): p=email.split("@") if len(p)!=2: raise InvalidEmail("Invalid email %s" % email) email_user=p[0].lower() email_domain=p[1].lower() if not self.domains.has_key(email_domain): return self.local_check(email_user, email_domain) # raise NoSuchDomain("No such vmailmgr domain %s" % email_domain) system_user=self.domains[email_domain] try: pwd_entry=pwd.getpwnam(system_user) except: raise InvalidVmailMgrDomain("No such system user for domain %s" % email_domain) home_dir=pwd_entry[5] passwd_dbfile=os.path.abspath(os.path.join(home_dir, "passwd.cdb")) if not os.path.isfile(passwd_dbfile): raise InvalidVmailMgrDomain("Missing domain users database for domain %s" % email_domain) try: db=cdb.init(passwd_dbfile) except: raise InvalidVmailMgrDomain("Could not read cdb database for domain %s" % email_domain) # check if the user is in the CDB database try: cdb_user_data=db[email_user] return True except: pass self.home_dir=home_dir p=email_user.split("-") for i in range(0, min(len(p), 5)): if self.is_dotqmail(p, i): return True return False def is_dotqmail(self, parts, pos): #print parts dotqmail_name="-".join(parts[0:pos+1]) if len(parts)==pos+1: f=os.path.join(self.home_dir, ".qmail-%s" % dotqmail_name) if os.path.isfile(f): return True else: f=os.path.join(self.home_dir, ".qmail-%s-default" % dotqmail_name) if os.path.isfile(f): return True return False if __name__=="__main__": vmgr=VmailMgr() if len(sys.argv)==2: print vmgr.check(sys.argv[1]) sys.exit(0) # if we have RELAYCLIENT=="" skip test if os.getenv("RELAYCLIENT")=="": sys.exit(0) # check if we passed RCPTHOSTS if os.getenv("SMTPRCPTHOSTSOK")!="1": sys.exit(0) rcpt_email=os.getenv("SMTPRCPTTO") if rcpt_email is None: sys.exit(0) try: ok=vmgr.check(rcpt_email) if not ok: print >>sys.stdout, "E550 No such mailbox %s" % rcpt_email print >>sys.stderr, "No such mailbox %s from: %s (%s)" % (rcpt_email, os.getenv("TCPREMOTEHOST"), os.getenv("TCPREMOTEIP")) except Exception, inst: print >>sys.stderr, "ERROR %s" % str(inst) sys.exit(0)