From 8a0c22bdae209d1b0ddf487633559a0aab77ebd7 Mon Sep 17 00:00:00 2001 From: Jan Dittberner Date: Wed, 28 Sep 2005 22:02:42 +0000 Subject: [PATCH] - complete addpopuser git-svn-id: file:///home/www/usr01/svn/gnuviechadmin/gnuviech.info/gnuviechadmin/trunk@122 a67ec6bc-e5d5-0310-a910-815c51eb3124 --- backend/addpopuser.py | 9 +-- backend/gvadm/DomainTools.py | 122 ++++++++++++++++++++++++++++++----- backend/gvadm/Settings.py | 6 ++ 3 files changed, 116 insertions(+), 21 deletions(-) diff --git a/backend/addpopuser.py b/backend/addpopuser.py index 0a8c552..6bc6586 100755 --- a/backend/addpopuser.py +++ b/backend/addpopuser.py @@ -33,9 +33,9 @@ if __name__ == "__main__": sys.exit(1) # specify the domain - domain = dict(options[0])['--domain'] + domain = None try: - DomainTools.validate_domain(domain) + domain = DomainTools.Domain(dict(options[0])['--domain']) except DomainTools.InvalidDomain, iv: print iv sys.exit(1) @@ -48,7 +48,4 @@ if __name__ == "__main__": if (password == None): password = PasswordTools.generate_password() - print domain - print password - - print PasswordTools.md5_crypt_password(password) + domain.makePopUser(password) diff --git a/backend/gvadm/DomainTools.py b/backend/gvadm/DomainTools.py index d5a17e2..7666ea4 100644 --- a/backend/gvadm/DomainTools.py +++ b/backend/gvadm/DomainTools.py @@ -1,30 +1,122 @@ #!/usr/bin/env python -import psycopg -import Settings +import psycopg, pwd, grp, smtplib, os +from email.MIMEText import MIMEText +import Settings, PasswordTools class InvalidDomain(Exception): - """This Exception is thrown if an invalid domain is used.""" + """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)) -def validate_domain(domain): - """This function validates whether the given domain is allowed. - That means that the domain needs to be registered in the database. +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.""" - cnx = psycopg.connect("user=%(dbuser)s password=%(dbpassword)s dbname=%(dbname)s" % Settings.dbsettings) - cr = cnx.cursor() + If the domain is invalid InvalidDomain is raised.""" + cr = self.cnx.cursor() - cr.execute("SELECT * FROM domain WHERE domainname=%(name)s" % - {'name': psycopg.QuotedString(domain)}) - cnx.commit() + 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(domain) + 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() diff --git a/backend/gvadm/Settings.py b/backend/gvadm/Settings.py index cf79bef..7351f0d 100644 --- a/backend/gvadm/Settings.py +++ b/backend/gvadm/Settings.py @@ -3,3 +3,9 @@ dbsettings = { 'dbuser': 'exim4', 'dbpassword' : 'CotOgigmeIk5', 'dbname' : 'gnuviechadmin' } + +mailsender = 'root@gnuviech.info' +mailreceiver = 'root@gnuviech.info' +popgroup = 'poponly' +popgroup = 'poponly' +pophome = '/home/mail/'