diff -r 659c4476c57c -r b678a1c43027 VirtualMailManager/emailaddress.py --- a/VirtualMailManager/emailaddress.py Mon Mar 24 19:22:04 2014 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,155 +0,0 @@ -# -*- coding: UTF-8 -*- -# Copyright (c) 2008 - 2014, Pascal Volk -# See COPYING for distribution information. -""" - VirtualMailManager.emailaddress - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - - Virtual Mail Manager's EmailAddress class to handle e-mail addresses. -""" -import re - -from VirtualMailManager.domain import check_domainname, get_gid -from VirtualMailManager.constants import \ - DOMAIN_NO_NAME, INVALID_ADDRESS, LOCALPART_INVALID, LOCALPART_TOO_LONG, \ - DOMAIN_INVALID -from VirtualMailManager.errors import DomainError, EmailAddressError as EAErr - - -RE_LOCALPART = re.compile(r"[^\w!#$%&'\*\+-\.\/=?^_`{\|}~]") -_ = lambda msg: msg - - -class EmailAddress(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``.""" - assert isinstance(address, basestring) - self._localpart = None - self._domainname = None - if _validate: - self._chk_address(address) - - @property - def localpart(self): - """The local-part of the address *local-part@domain*""" - return self._localpart - - @property - def domainname(self): - """The domain part of the address *local-part@domain*""" - return self._domainname - - def __eq__(self, other): - if isinstance(other, self.__class__): - return self._localpart == other._localpart and \ - self._domainname == other._domainname - return NotImplemented - - def __ne__(self, other): - if isinstance(other, self.__class__): - return self._localpart != other._localpart or \ - self._domainname != other._domainname - return NotImplemented - - def __hash__(self): - return hash((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) - if p_len < 2: - raise EAErr(_(u"Missing the '@' sign in address: '%s'") % address, - INVALID_ADDRESS) - elif p_len > 2: - raise EAErr(_(u"Too many '@' signs in address: '%s'") % address, - INVALID_ADDRESS) - if not parts[0]: - raise EAErr(_(u"Missing local-part in address: '%s'") % address, - LOCALPART_INVALID) - if not parts[1]: - raise EAErr(_(u"Missing domain name in address: '%s'") % address, - DOMAIN_NO_NAME) - self._localpart = check_localpart(parts[0]) - self._domainname = check_domainname(parts[1]) - - -class DestinationEmailAddress(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 = False - if not _validate: - try: - self._chk_address(address) - except DomainError, err: - if err.code is DOMAIN_INVALID and \ - address.split('@')[1] == 'localhost': - self._localhost = True - self._domainname = 'localhost' - else: - raise - self._gid = 0 - if not self._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) - if self._gid: - self._localpart = self._localpart.lower() - - @property - def at_localhost(self): - """True when the address is something@localhost.""" - return self._localhost - - @property - def gid(self): - """The domains group ID. 0 if the domain is not known.""" - return self._gid - - -def check_localpart(localpart): - """Returns the validated local-part `localpart`. - - Throws a `EmailAddressError` if the local-part is too long or contains - invalid characters. - """ - if len(localpart) > 64: - raise EAErr(_(u"The local-part '%s' is too long.") % localpart, - LOCALPART_TOO_LONG) - invalid_chars = set(RE_LOCALPART.findall(localpart)) - if invalid_chars: - i_chars = u''.join((u'"%s" ' % c for c in invalid_chars)) - raise EAErr(_(u"The local-part '%(l_part)s' contains invalid " - u"characters: %(i_chars)s") % {'l_part': localpart, - 'i_chars': i_chars}, LOCALPART_INVALID) - return localpart - -del _