Moved VirtualMailManager/Exceptions to VirtualMailManager/errors.
Renamed VMM*Exception classes to *Error.
No longer add the attribute 'message' to VMMError if it doesn't exist, like in
Python 2.4. It has been deprecated as of Python 2.6.
Also removed the methods code() and msg(), the values are now accessible via
the attributes 'code' and 'msg'.
# -*- coding: UTF-8 -*-# Copyright (c) 2007 - 2010, Pascal Volk# See COPYING for distribution information.""" VirtualMailManager.Alias Virtual Mail Manager's Alias class to manage e-mail aliases."""fromVirtualMailManager.Domainimportget_gidfromVirtualMailManager.EmailAddressimportEmailAddressfromVirtualMailManager.errorsimportAliasErrorasAErrfromVirtualMailManager.constants.ERRORimportALIAS_ADDR_DEST_IDENTICAL, \ALIAS_EXCEEDS_EXPANSION_LIMIT,ALIAS_EXISTS,NO_SUCH_ALIAS_=lambdamsg:msgclassAlias(object):"""Class to manage e-mail aliases."""__slots__=('_addr','_dests','_gid','_dbh')def__init__(self,dbh,address):assertisinstance(address,EmailAddress)self._addr=addressself._dbh=dbhself._gid=get_gid(self._dbh,self._addr.domainname)self._dests=[]self.__load_dests()def__load_dests(self):"""Loads all known destination addresses into the _dests list."""dbc=self._dbh.cursor()dbc.execute('SELECT destination FROM alias WHERE gid=%s AND address=%s',self._gid,self._addr.localpart)dests=iter(dbc.fetchall())ifdbc.rowcount>0:dest_add=self._dests.appendfordestindests:dest_add(EmailAddress(dest[0]))dbc.close()def__check_expansion(self,limit):"""Checks the current expansion limit of the alias."""dcount=len(self._dests)failed=Falseifdcount==limit:failed=Trueerrmsg=_(u"""Can't add new destination to alias %(address)r.Currently this alias expands into %(count)i/%(limit)i recipients.One more destination will render this alias unusable.Hint: Increase Postfix' virtual_alias_expansion_limit""")elifdcount>limit:failed=Trueerrmsg=_(u"""Can't add new destination to alias %(address)r.This alias already exceeds it's expansion limit (%(count)i/%(limit)i).So its unusable, all messages addressed to this alias will be bounced.Hint: Delete some destination addresses.""")iffailed:raiseAErr(errmsg%{'address':str(self._addr),'count':dcount,'limit':limit},ALIAS_EXCEEDS_EXPANSION_LIMIT)def__delete(self,destination=None):"""Deletes a destination from the alias, if ``destination`` is not ``None``. If ``destination`` is None, the alias with all it's destination addresses will be deleted. """dbc=self._dbh.cursor()ifnotdestination:dbc.execute("DELETE FROM alias WHERE gid=%s AND address=%s",self._gid,self._addr.localpart)else:dbc.execute("DELETE FROM alias WHERE gid=%s AND address=%s AND \ destination=%s",self._gid,self._addr.localpart,str(destination))ifdbc.rowcount>0:self._dbh.commit()dbc.close()def__len__(self):"""Returns the number of destinations of the alias."""returnlen(self._dests)defadd_destination(self,destination,expansion_limit):"""Adds the ``destination`` `EmailAddress` to the alias."""assertisinstance(destination,EmailAddress)ifself._addr==destination:raiseAErr(_(u"Address and destination are identical."),ALIAS_ADDR_DEST_IDENTICAL)ifdestinationinself._dests:raiseAErr(_(u'The alias %(a)r has already the destination %(d)r.')%{'a':str(self._addr),'d':str(destination)},ALIAS_EXISTS)self.__check_expansion(expansion_limit)dbc=self._dbh.cursor()dbc.execute('INSERT INTO alias (gid, address, destination) \VALUES (%s, %s, %s)',self._gid,self._addr.localpart,str(destination))self._dbh.commit()dbc.close()self._dests.append(destination)defdel_destination(self,destination):"""Deletes the specified ``destination`` address from the alias."""assertisinstance(destination,EmailAddress)ifnotself._dests:raiseAErr(_(u"The alias %r doesn't exist.")%str(self._addr),NO_SUCH_ALIAS)ifnotdestinationinself._dests:raiseAErr(_(u"The address %(d)r isn't a destination of \the alias %(a)r.")%{'a':str(self._addr),'d':str(destination)},NO_SUCH_ALIAS)self.__delete(destination)self._dests.remove(destination)defget_destinations(self):"""Returns an iterator for all destinations of the alias."""ifnotself._dests:raiseAErr(_(u"The alias %r doesn't exist.")%str(self._addr),NO_SUCH_ALIAS)returniter(self._dests)defdelete(self):"""Deletes the alias with all it's destinations."""ifnotself._dests:raiseAErr(_(u"The alias %r doesn't exist.")%str(self._addr),NO_SUCH_ALIAS)self.__delete()delself._dests[:]del_