#!/usr/bin/env python import psycopg, pwd, grp, smtplib, os from email.MIMEText import MIMEText import Settings, PasswordTools class InvalidDomain(Exception): """This exception is raised if an invalid domain is used.""" def __init__(self, domain): self.domain = domain def __str__(self): return repr("Invalid domain %s" % (self.domain)) class NoSysuserForDomain(Exception): """This exception is raised if no system user is associated with a domain.""" def __init__(self, domain): self.domain = domain def __str__(self): return repr("No system user for domain %s" % (self.domain)) class Domain: """A Domain representation object with service methods.""" def __init__(self, domain): self.cnx = psycopg.connect("user=%(dbuser)s password=%(dbpassword)s dbname=%(dbname)s" % Settings.dbsettings) self.domain = domain self.validate_domain() def validate_domain(self): """This function validates whether the given domain is allowed. That means that the domain needs to be registered in the database. If the domain is invalid InvalidDomain is raised.""" cr = self.cnx.cursor() cr.execute("SELECT * FROM domain WHERE domainname=%(name)s" % {'name': psycopg.QuotedString(self.domain)}) self.cnx.commit() result = cr.fetchall() if (not result): raise InvalidDomain(self) def __str__(self): return repr(self.domain) def getSysuser(self): """Gets the system user id of the domain.""" cr = self.cnx.cursor() cr.execute("""SELECT sysuser.name FROM domain, sysuser WHERE domain.domainname=%(name)s AND domain.sysuserid=sysuser.sysuserid""" % {'name': psycopg.QuotedString(self.domain)}) self.cnx.commit() result = cr.fetchall() if (not result): raise NoSysuserForDomain(self) # return row 0, field 0 return result[0][0] def getNextPopUser(self): """Gets the user id of the next available POP3/IMAP-user for the domain.""" cr = self.cnx.cursor() sysuser = self.getSysuser() cr.execute("""SELECT max(id) FROM mailpasswd WHERE id LIKE %(username)s""" % {'username': psycopg.QuotedString(sysuser+'%')}) self.cnx.commit() result = cr.fetchall() if (not result): return sysuser + "p01" maxpopuser = result[0][0] num = int(maxpopuser[len(sysuser)+1:])+1 return "%sp%d" % (sysuser, num) def makePopUser(self, password): """Creates a new POP3/IMAP-user for the domain using the given password.""" cr = self.cnx.cursor() sysuser = self.getSysuser() popaccount = self.getNextPopUser() crypted = PasswordTools.md5_crypt_password(password) uid = pwd.getpwnam(sysuser)[2] gid = grp.getgrnam(Settings.popgroup)[2] homedir = Settings.pophome + popaccount os.mkdir(homedir, 0660) os.system("maildirmake \"%s/Maildir\"" % (homedir)) os.system("chown %s.%s %s" % ( sysuser, Settings.popgroup, homedir )) cr = self.cnx.cursor() cr.execute("""INSERT INTO mailpasswd (id, crypt, clear, uid, gid, home) VALUES (%(id)s, %(crypt)s, %(clear)s, %(uid)d, %(gid)d, %(home)s)""" % { 'id': psycopg.QuotedString(popaccount), 'crypt': psycopg.QuotedString(crypted), 'clear': psycopg.QuotedString(password), 'uid': uid, 'gid': gid, 'home': psycopg.QuotedString(homedir)}) self.cnx.commit() text = """A new POP3/IMAP account has been created Domain: %(domain)s User: %(user)s Password: %(password)s""" % {'domain': self.domain, 'user': popaccount, 'password': password} themail = MIMEText(text) themail['Subject'] = "A new POP3/IMAP account has been created" themail['From'] = Settings.mailsender themail['To'] = Settings.mailreceiver s = smtplib.SMTP() s.connect() s.sendmail(Settings.mailsender, [Settings.mailreceiver], themail.as_string()) s.close()