7 |
7 |
8 Virtual Mail Manager's Domain class to manage e-mail domains. |
8 Virtual Mail Manager's Domain class to manage e-mail domains. |
9 """ |
9 """ |
10 |
10 |
11 import os |
11 import os |
|
12 import re |
|
13 from encodings.idna import ToASCII, ToUnicode |
12 from random import choice |
14 from random import choice |
13 |
15 |
14 from VirtualMailManager import check_domainname |
|
15 from VirtualMailManager.constants.ERROR import \ |
16 from VirtualMailManager.constants.ERROR import \ |
16 ACCOUNT_AND_ALIAS_PRESENT, ACCOUNT_PRESENT, ALIAS_PRESENT, \ |
17 ACCOUNT_AND_ALIAS_PRESENT, ACCOUNT_PRESENT, ALIAS_PRESENT, \ |
17 DOMAIN_ALIAS_EXISTS, DOMAIN_EXISTS, NO_SUCH_DOMAIN |
18 DOMAIN_ALIAS_EXISTS, DOMAIN_EXISTS, DOMAIN_INVALID, DOMAIN_TOO_LONG, \ |
|
19 NO_SUCH_DOMAIN |
18 from VirtualMailManager.errors import DomainError as DomErr |
20 from VirtualMailManager.errors import DomainError as DomErr |
19 from VirtualMailManager.Transport import Transport |
21 from VirtualMailManager.Transport import Transport |
20 |
22 |
21 |
23 |
22 MAILDIR_CHARS = '0123456789abcdefghijklmnopqrstuvwxyz' |
24 MAILDIR_CHARS = '0123456789abcdefghijklmnopqrstuvwxyz' |
23 _ = lambda x: x |
25 RE_DOMAIN = re.compile(r"^(?:[a-z0-9-]{1,63}\.){1,}[a-z]{2,6}$") |
|
26 _ = lambda msg: msg |
24 |
27 |
25 |
28 |
26 class Domain(object): |
29 class Domain(object): |
27 """Class to manage e-mail domains.""" |
30 """Class to manage e-mail domains.""" |
28 __slots__ = ('_directory', '_gid', '_name', '_transport', '_dbh', '_new') |
31 __slots__ = ('_directory', '_gid', '_name', '_transport', '_dbh', '_new') |
314 dbc.close() |
317 dbc.close() |
315 aliasdomains = [] |
318 aliasdomains = [] |
316 if anames: |
319 if anames: |
317 aliasdomains = [aname[0] for aname in anames] |
320 aliasdomains = [aname[0] for aname in anames] |
318 return aliasdomains |
321 return aliasdomains |
|
322 |
|
323 |
|
324 def ace2idna(domainname): |
|
325 """Converts the domain name `domainname` from ACE according to IDNA.""" |
|
326 return u'.'.join([ToUnicode(lbl) for lbl in domainname.split('.') if lbl]) |
|
327 |
|
328 |
|
329 def check_domainname(domainname): |
|
330 """Returns the validated domain name `domainname`. |
|
331 |
|
332 It also converts the name of the domain from IDN to ASCII, if |
|
333 necessary. |
|
334 |
|
335 Throws an `DomainError`, if the domain name is too long or doesn't |
|
336 look like a valid domain name (label.label.label). |
|
337 |
|
338 """ |
|
339 if not RE_DOMAIN.match(domainname): |
|
340 domainname = idn2ascii(domainname) |
|
341 if len(domainname) > 255: |
|
342 raise DomErr(_(u'The domain name is too long'), DOMAIN_TOO_LONG) |
|
343 if not RE_DOMAIN.match(domainname): |
|
344 raise DomErr(_(u"The domain name '%s' is invalid") % domainname, |
|
345 DOMAIN_INVALID) |
|
346 return domainname |
|
347 |
|
348 |
|
349 def get_gid(dbh, domainname): |
|
350 """Returns the group id of the domain *domainname*. |
|
351 |
|
352 If the domain couldn't be found in the database 0 will be returned. |
|
353 """ |
|
354 domainname = check_domainname(domainname) |
|
355 dbc = dbh.cursor() |
|
356 dbc.execute('SELECT gid FROM domain_name WHERE domainname=%s', domainname) |
|
357 gid = dbc.fetchone() |
|
358 dbc.close() |
|
359 if gid: |
|
360 return gid[0] |
|
361 return 0 |
|
362 |
|
363 |
|
364 def idn2ascii(domainname): |
|
365 """Converts the idn domain name `domainname` into punycode.""" |
|
366 return '.'.join([ToASCII(lbl) for lbl in domainname.split('.') if lbl]) |
319 |
367 |
320 |
368 |
321 def search(dbh, pattern=None, like=False): |
369 def search(dbh, pattern=None, like=False): |
322 """'Search' for domains by *pattern* in the database. |
370 """'Search' for domains by *pattern* in the database. |
323 |
371 |