# -*- coding: UTF-8 -*-# Copyright 2007-2008 VEB IT# See COPYING for distribution information.# $Id$"""Virtual Mail Manager's Account class to manage e-mail accounts."""fromconstants.VERSIONimportVERSION__author__='Pascal Volk <p.volk@veb-it.de>'__version__=VERSION__revision__='rev '+'$Rev$'.split()[1]__date__='$Date$'.split()[1]fromExceptionsimportVMMAccountExceptionasAccEfromDomainimportDomainfromTransportimportTransportfromMailLocationimportMailLocationfromEmailAddressimportEmailAddressimportVirtualMailManagerasVMMimportconstants.ERRORasERRclassAccount:"""Class to manage e-mail accounts."""def__init__(self,dbh,address,password=None):self._dbh=dbhself._base=Noneifisinstance(address,EmailAddress):self._addr=addresselse:raiseTypeError("Argument 'address' is not an EmailAddress")self._uid=0self._gid=0self._mid=0self._tid=0self._passwd=passwordself._setAddr()self._exists()ifself._uid<1andVMM.VirtualMailManager.aliasExists(self._dbh,self._addr):raiseAccE(_(u"There is already an alias with the address »%s«.")%\self._addr,ERR.ALIAS_EXISTS)ifself._uid<1andVMM.VirtualMailManager.relocatedExists(self._dbh,self._addr):raiseAccE(_(u"There is already a relocated user with the address »%s«.")%\self._addr,ERR.RELOCATED_EXISTS)def_exists(self):dbc=self._dbh.cursor()dbc.execute("SELECT uid, mid, tid FROM users \WHERE gid=%s AND local_part=%s",self._gid,self._addr._localpart)result=dbc.fetchone()dbc.close()ifresultisnotNone:self._uid,self._mid,self._tid=resultreturnTrueelse:returnFalsedef_setAddr(self):dom=Domain(self._dbh,self._addr._domainname)self._gid=dom.getID()ifself._gid==0:raiseAccE(_(u"The domain »%s« doesn't exist yet.")%\self._addr._domainname,ERR.NO_SUCH_DOMAIN)self._base=dom.getDir()self._tid=dom.getTransportID()def_setID(self):dbc=self._dbh.cursor()dbc.execute("SELECT nextval('users_uid')")self._uid=dbc.fetchone()[0]dbc.close()def_prepare(self,maillocation):self._setID()self._mid=MailLocation(self._dbh,maillocation=maillocation).getID()def_switchState(self,state,service):ifnotisinstance(state,bool):returnFalseifnotservicein['smtp','pop3','imap','managesieve','all',None]:raiseAccE(_(u"Unknown service »%s«.")%service,ERR.UNKNOWN_SERVICE)ifself._uid<1:raiseAccE(_(u"The account »%s« doesn't exists.")%self._addr,ERR.NO_SUCH_ACCOUNT)dbc=self._dbh.cursor()ifservicein['smtp','pop3','imap','managesieve']:dbc.execute("UPDATE users SET %s=%s WHERE local_part='%s' AND gid=%s"%(service,state,self._addr._localpart,self._gid))elifstate:dbc.execute("UPDATE users SET smtp = TRUE, pop3 = TRUE,\ imap = TRUE, managesieve = TRUE WHERE local_part = %s AND gid = %s",self._addr._localpart,self._gid)else:dbc.execute("UPDATE users SET smtp = FALSE, pop3 = FALSE,\ imap = FALSE, managesieve = FALSE WHERE local_part = %s AND gid = %s",self._addr._localpart,self._gid)ifdbc.rowcount>0:self._dbh.commit()dbc.close()def__aliaseCount(self):dbc=self._dbh.cursor()q="SELECT COUNT(destination) FROM alias WHERE destination = '%s'"\%self._addrdbc.execute(q)a_count=dbc.fetchone()[0]dbc.close()returna_countdefsetPassword(self,password):self._passwd=passworddefgetUID(self):returnself._uiddefgetGID(self):returnself._giddefgetDir(self,directory):ifdirectory=='domain':return'%s'%self._baseelifdirectory=='home':return'%s/%i'%(self._base,self._uid)defenable(self,service=None):self._switchState(True,service)defdisable(self,service=None):self._switchState(False,service)defsave(self,maillocation,smtp,pop3,imap,managesieve):ifself._uid<1:self._prepare(maillocation)dbc=self._dbh.cursor()dbc.execute("""INSERT INTO users (local_part, passwd, uid, gid,\ mid, tid, smtp, pop3, imap, managesieve)\ VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s)""",self._addr._localpart,self._passwd,self._uid,self._gid,self._mid,self._tid,smtp,pop3,imap,managesieve)self._dbh.commit()dbc.close()else:raiseAccE(_(u'The account »%s« already exists.')%self._addr,ERR.ACCOUNT_EXISTS)defmodify(self,what,value):ifself._uid==0:raiseAccE(_(u"The account »%s« doesn't exists.")%self._addr,ERR.NO_SUCH_ACCOUNT)ifwhatnotin['name','password','transport']:returnFalsedbc=self._dbh.cursor()ifwhat=='password':dbc.execute("UPDATE users SET passwd=%s WHERE local_part=%s AND\ gid=%s",value,self._addr._localpart,self._gid)elifwhat=='transport':self._tid=Transport(self._dbh,transport=value).getID()dbc.execute("UPDATE users SET tid=%s WHERE local_part=%s AND\ gid=%s",self._tid,self._addr._localpart,self._gid)else:dbc.execute("UPDATE users SET name=%s WHERE local_part=%s AND\ gid=%s",value,self._addr._localpart,self._gid)ifdbc.rowcount>0:self._dbh.commit()dbc.close()defgetInfo(self):dbc=self._dbh.cursor()dbc.execute("SELECT name, uid, gid, mid, tid, smtp, pop3, imap, \ managesieve FROM users WHERE local_part=%s AND gid=%s",self._addr._localpart,self._gid)info=dbc.fetchone()dbc.close()ifinfoisNone:raiseAccE(_(u"The account »%s« doesn't exists.")%self._addr,ERR.NO_SUCH_ACCOUNT)else:keys=['name','uid','gid','maildir','transport','smtp','pop3','imap','managesieve']info=dict(zip(keys,info))forservicein['smtp','pop3','imap','managesieve']:ifbool(info[service]):info[service]=_('enabled')else:info[service]=_('disabled')info['address']=self._addrinfo['maildir']='%s/%s/%s'%(self._base,info['uid'],MailLocation(self._dbh,mid=info['maildir']).getMailLocation())info['transport']=Transport(self._dbh,tid=info['transport']).getTransport()returninfodefgetAliases(self):dbc=self._dbh.cursor()dbc.execute("SELECT address ||'@'|| domainname FROM alias, domain_name\ WHERE destination = %s AND domain_name.gid = alias.gid\ AND domain_name.is_primary",str(self._addr))addresses=dbc.fetchall()dbc.close()aliases=[]iflen(addresses)>0:foraliasinaddresses:aliases.append(alias[0])returnaliasesdefdelete(self,delalias):ifself._uid<1:raiseAccE(_(u"The account »%s« doesn't exists.")%self._addr,ERR.NO_SUCH_ACCOUNT)dbc=self._dbh.cursor()ifdelalias=='delalias':dbc.execute("DELETE FROM users WHERE gid=%s AND local_part=%s",self._gid,self._addr._localpart)u_rc=dbc.rowcount# delete also all aliases where the destination address is the same# as for this account.dbc.execute("DELETE FROM alias WHERE destination = %s",self._addr)ifu_rc>0ordbc.rowcount>0:self._dbh.commit()else:# check first for aliasesa_count=self.__aliaseCount()ifa_count==0:dbc.execute("DELETE FROM users WHERE gid=%s AND local_part=%s",self._gid,self._addr._localpart)ifdbc.rowcount>0:self._dbh.commit()else:dbc.close()raiseAccE(_(u"There are %(count)d aliases with the destination address\ »%(address)s«.")%{'count':a_count,'address':self._addr},ERR.ALIAS_PRESENT)dbc.close()defgetAccountByID(uid,dbh):try:uid=long(uid)exceptValueError:raiseAccE(_(u'uid must be an int/long.'),ERR.INVALID_AGUMENT)ifuid<1:raiseAccE(_(u'uid must be greater than 0.'),ERR.INVALID_AGUMENT)dbc=dbh.cursor()dbc.execute("SELECT local_part||'@'|| domain_name.domainname AS address,\ uid, users.gid FROM users LEFT JOIN domain_name ON (domain_name.gid \ = users.gid AND is_primary) WHERE uid = %s;",uid)info=dbc.fetchone()dbc.close()ifinfoisNone:raiseAccE(_(u"There is no account with the UID »%d«.")%uid,ERR.NO_SUCH_ACCOUNT)keys=['address','uid','gid']info=dict(zip(keys,info))returninfo