4 |
4 |
5 """Virtual Mail Manager's EmailAddress class to handle e-mail addresses.""" |
5 """Virtual Mail Manager's EmailAddress class to handle e-mail addresses.""" |
6 |
6 |
7 import re |
7 import re |
8 |
8 |
9 import VirtualMailManager.constants.ERROR as ERR |
|
10 from VirtualMailManager import chk_domainname |
9 from VirtualMailManager import chk_domainname |
|
10 from VirtualMailManager.constants.ERROR import \ |
|
11 DOMAIN_NO_NAME, INVALID_ADDRESS, LOCALPART_INVALID, LOCALPART_TOO_LONG |
11 from VirtualMailManager.Exceptions import VMMEmailAddressException as VMMEAE |
12 from VirtualMailManager.Exceptions import VMMEmailAddressException as VMMEAE |
|
13 |
12 |
14 |
13 RE_LOCALPART = """[^\w!#$%&'\*\+-\.\/=?^_`{\|}~]""" |
15 RE_LOCALPART = """[^\w!#$%&'\*\+-\.\/=?^_`{\|}~]""" |
14 |
16 |
|
17 |
15 class EmailAddress(object): |
18 class EmailAddress(object): |
16 __slots__ = ('_localpart', '_domainname') |
19 __slots__ = ('_localpart', '_domainname') |
|
20 |
17 def __init__(self, address): |
21 def __init__(self, address): |
|
22 if not isinstance(address, basestring): |
|
23 raise TypeError('address is not a str/unicode object: %r' % |
|
24 address) |
18 self._localpart = None |
25 self._localpart = None |
19 self._domainname = None |
26 self._domainname = None |
20 self.__chkAddress(address) |
27 self.__chkAddress(address) |
21 |
28 |
22 def __eq__(self, other): |
29 def __eq__(self, other): |
23 if isinstance(other, self.__class__): |
30 if isinstance(other, self.__class__): |
24 return self._localpart == other._localpart\ |
31 return self._localpart == other._localpart and \ |
25 and self._domainname == other._domainname |
32 self._domainname == other._domainname |
26 return NotImplemented |
33 return NotImplemented |
27 |
34 |
28 def __ne__(self, other): |
35 def __ne__(self, other): |
29 if isinstance(other, self.__class__): |
36 if isinstance(other, self.__class__): |
30 return self._localpart != other._localpart\ |
37 return self._localpart != other._localpart or \ |
31 or self._domainname != other._domainname |
38 self._domainname != other._domainname |
32 return NotImplemented |
39 return NotImplemented |
33 |
40 |
34 def __repr__(self): |
41 def __repr__(self): |
35 return "EmailAddress('%s@%s')" % (self._localpart, self._domainname) |
42 return "EmailAddress('%s@%s')" % (self._localpart, self._domainname) |
36 |
43 |
37 def __str__(self): |
44 def __str__(self): |
38 return "%s@%s" % (self._localpart, self._domainname) |
45 return "%s@%s" % (self._localpart, self._domainname) |
39 |
46 |
40 def __chkAddress(self, address): |
47 def __chkAddress(self, address): |
41 try: |
48 parts = address.split('@') |
42 localpart, domain = address.split('@') |
49 p_len = len(parts) |
43 except ValueError: |
50 if p_len is 2: |
|
51 self._localpart = self.__chkLocalpart(parts[0]) |
|
52 if len(parts[1]) > 0: |
|
53 self._domainname = chk_domainname(parts[1]) |
|
54 else: |
|
55 raise VMMEAE(_(u"Missing domain name after “%s@”.") % |
|
56 self._localpart, DOMAIN_NO_NAME) |
|
57 elif p_len < 2: |
44 raise VMMEAE(_(u"Missing '@' sign in e-mail address “%s”.") % |
58 raise VMMEAE(_(u"Missing '@' sign in e-mail address “%s”.") % |
45 address, ERR.INVALID_ADDRESS) |
59 address, INVALID_ADDRESS) |
46 except AttributeError: |
60 elif p_len > 2: |
47 raise VMMEAE(_(u"“%s” doesn't look like an e-mail address.") % |
61 raise VMMEAE(_(u"Too many '@' signs in e-mail address “%s”.") % |
48 address, ERR.INVALID_ADDRESS) |
62 address, INVALID_ADDRESS) |
49 if len(domain) > 0: |
|
50 domain = chk_domainname(domain) |
|
51 else: |
|
52 raise VMMEAE(_(u"Missing domain name after “%s@”.") % localpart, |
|
53 ERR.DOMAIN_NO_NAME) |
|
54 localpart = self.__chkLocalpart(localpart) |
|
55 self._localpart, self._domainname = localpart, domain |
|
56 |
63 |
57 def __chkLocalpart(self, localpart): |
64 def __chkLocalpart(self, localpart): |
58 """Validates the local-part of an e-mail address. |
65 """Validates the local-part of an e-mail address. |
59 |
66 |
60 Arguments: |
67 Arguments: |
61 localpart -- local-part of the e-mail address that should be validated (str) |
68 localpart -- local-part of the e-mail address that should be validated |
62 """ |
69 """ |
63 if len(localpart) < 1: |
70 if len(localpart) < 1: |
64 raise VMMEAE(_(u'No local-part specified.'), |
71 raise VMMEAE(_(u'No local-part specified.'), LOCALPART_INVALID) |
65 ERR.LOCALPART_INVALID) |
|
66 if len(localpart) > 64: |
72 if len(localpart) > 64: |
67 raise VMMEAE(_(u'The local-part “%s” is too long') % |
73 raise VMMEAE(_(u'The local-part “%s” is too long') % localpart, |
68 localpart, ERR.LOCALPART_TOO_LONG) |
74 LOCALPART_TOO_LONG) |
69 ic = set(re.findall(RE_LOCALPART, localpart)) |
75 ic = set(re.findall(RE_LOCALPART, localpart)) |
70 if len(ic): |
76 if len(ic): |
71 ichrs = '' |
77 ichrs = u''.join((u'“%s” ' % c for c in ic)) |
72 for c in ic: |
|
73 ichrs += u"“%s” " % c |
|
74 raise VMMEAE(_(u"The local-part “%(lpart)s” contains invalid\ |
78 raise VMMEAE(_(u"The local-part “%(lpart)s” contains invalid\ |
75 characters: %(ichrs)s") % {'lpart': localpart, 'ichrs': ichrs}, |
79 characters: %(ichrs)s") % {'lpart': localpart, 'ichrs': ichrs}, |
76 ERR.LOCALPART_INVALID) |
80 LOCALPART_INVALID) |
77 return localpart |
81 return localpart |
78 |
|