Due to the UNION query in address_list, the assumption that the list of
gids received from the database would be continuous does not hold.
To prevent addresses for domains with multiple entry types from being
listed, it is necessary to check the list of domain gids for every
entry.
Signed-off-by: martin f. krafft <madduck@debian.org>
---
VirtualMailManager/common.py | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
# -*- coding: UTF-8 -*-# Copyright (c) 2008 - 2012, Pascal Volk# See COPYING for distribution information.""" VirtualMailManager.emailaddress ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Virtual Mail Manager's EmailAddress class to handle e-mail addresses."""importrefromVirtualMailManager.domainimportcheck_domainname,get_gidfromVirtualMailManager.constantsimport \DOMAIN_NO_NAME,INVALID_ADDRESS,LOCALPART_INVALID,LOCALPART_TOO_LONG, \DOMAIN_INVALIDfromVirtualMailManager.errorsimportDomainError,EmailAddressErrorasEAErrRE_LOCALPART=re.compile(r"[^\w!#$%&'\*\+-\.\/=?^_`{\|}~]")_=lambdamsg:msgclassEmailAddress(object):"""Simple class for validated e-mail addresses."""__slots__=('_localpart','_domainname')def__init__(self,address,_validate=True):"""Creates a new instance from the string/unicode ``address``."""assertisinstance(address,basestring)self._localpart=Noneself._domainname=Noneif_validate:self._chk_address(address)@propertydeflocalpart(self):"""The local-part of the address *local-part@domain*"""returnself._localpart@propertydefdomainname(self):"""The domain part of the address *local-part@domain*"""returnself._domainnamedef__eq__(self,other):ifisinstance(other,self.__class__):returnself._localpart==other._localpartand \self._domainname==other._domainnamereturnNotImplementeddef__ne__(self,other):ifisinstance(other,self.__class__):returnself._localpart!=other._localpartor \self._domainname!=other._domainnamereturnNotImplementeddef__hash__(self):returnhash((self._localpart.lower(),self._domainname.lower()))def__repr__(self):return"EmailAddress('%s@%s')"%(self._localpart,self._domainname)def__str__(self):return'%s@%s'%(self._localpart,self._domainname)def_chk_address(self,address):"""Checks if the string ``address`` could be used for an e-mail address. If so, it will assign the corresponding values to the attributes `_localpart` and `_domainname`."""parts=address.split('@')p_len=len(parts)ifp_len<2:raiseEAErr(_(u"Missing the '@' sign in address: '%s'")%address,INVALID_ADDRESS)elifp_len>2:raiseEAErr(_(u"Too many '@' signs in address: '%s'")%address,INVALID_ADDRESS)ifnotparts[0]:raiseEAErr(_(u"Missing local-part in address: '%s'")%address,LOCALPART_INVALID)ifnotparts[1]:raiseEAErr(_(u"Missing domain name in address: '%s'")%address,DOMAIN_NO_NAME)self._localpart=check_localpart(parts[0])self._domainname=check_domainname(parts[1])classDestinationEmailAddress(EmailAddress):"""Provides additionally the domains group ID - when the domain is known in the database."""__slots__=('_gid','_localhost')def__init__(self,address,dbh,_validate=False):"""Creates a new DestinationEmailAddress instance Arguments: `address`: string/unicode a e-mail address like user@example.com `dbh`: pyPgSQL.PgSQL.Connection/pyPgSQL.PgSQL.connection a database connection for the database access """super(DestinationEmailAddress,self).__init__(address,_validate)self._localhost=Falseifnot_validate:try:self._chk_address(address)exceptDomainError,err:iferr.codeisDOMAIN_INVALIDand \address.split('@')[1]=='localhost':self._localhost=Trueself._domainname='localhost'else:raiseself._gid=0ifnotself._localhost:self._find_domain(dbh)else:self._localpart=self._localpart.lower()def_find_domain(self,dbh):"""Checks if the domain is known"""self._gid=get_gid(dbh,self._domainname)ifself._gid:self._localpart=self._localpart.lower()@propertydefat_localhost(self):"""True when the address is something@localhost."""returnself._localhost@propertydefgid(self):"""The domains group ID. 0 if the domain is not known."""returnself._giddefcheck_localpart(localpart):"""Returns the validated local-part `localpart`. Throws a `EmailAddressError` if the local-part is too long or contains invalid characters. """iflen(localpart)>64:raiseEAErr(_(u"The local-part '%s' is too long.")%localpart,LOCALPART_TOO_LONG)invalid_chars=set(RE_LOCALPART.findall(localpart))ifinvalid_chars:i_chars=u''.join((u'"%s" '%cforcininvalid_chars))raiseEAErr(_(u"The local-part '%(l_part)s' contains invalid "u"characters: %(i_chars)s")%{'l_part':localpart,'i_chars':i_chars},LOCALPART_INVALID)returnlocalpartdel_