1 # -*- coding: UTF-8 -*- |
|
2 # Copyright (c) 2007 - 2010, Pascal Volk |
|
3 # See COPYING for distribution information. |
|
4 |
|
5 """Virtual Mail Manager's Alias class to manage e-mail aliases.""" |
|
6 |
|
7 from __main__ import ERR |
|
8 from Exceptions import VMMAliasException as VMMAE |
|
9 from Domain import Domain |
|
10 from EmailAddress import EmailAddress |
|
11 import VirtualMailManager as VMM |
|
12 |
|
13 class Alias(object): |
|
14 """Class to manage e-mail aliases.""" |
|
15 __slots__ = ('_addr', '_dest', '_gid', '_isNew', '_dbh') |
|
16 def __init__(self, dbh, address, destination=None): |
|
17 if isinstance(address, EmailAddress): |
|
18 self._addr = address |
|
19 else: |
|
20 raise TypeError("Argument 'address' is not an EmailAddress") |
|
21 if destination is None: |
|
22 self._dest = None |
|
23 elif isinstance(destination, EmailAddress): |
|
24 self._dest = destination |
|
25 else: |
|
26 raise TypeError("Argument 'destination' is not an EmailAddress") |
|
27 if address == destination: |
|
28 raise VMMAE(_(u"Address and destination are identical."), |
|
29 ERR.ALIAS_ADDR_DEST_IDENTICAL) |
|
30 self._dbh = dbh |
|
31 self._gid = 0 |
|
32 self._isNew = False |
|
33 self._setAddr() |
|
34 if not self._dest is None: |
|
35 self._exists() |
|
36 if VMM.VirtualMailManager.accountExists(self._dbh, self._addr): |
|
37 raise VMMAE(_(u"There is already an account with address “%s”.") %\ |
|
38 self._addr, ERR.ACCOUNT_EXISTS) |
|
39 if VMM.VirtualMailManager.relocatedExists(self._dbh, self._addr): |
|
40 raise VMMAE( |
|
41 _(u"There is already a relocated user with the address “%s”.") %\ |
|
42 self._addr, ERR.RELOCATED_EXISTS) |
|
43 |
|
44 def _exists(self): |
|
45 dbc = self._dbh.cursor() |
|
46 dbc.execute("SELECT gid FROM alias WHERE gid=%s AND address=%s\ |
|
47 AND destination=%s", self._gid, self._addr._localpart, str(self._dest)) |
|
48 gid = dbc.fetchone() |
|
49 dbc.close() |
|
50 if gid is None: |
|
51 self._isNew = True |
|
52 |
|
53 def _setAddr(self): |
|
54 dom = Domain(self._dbh, self._addr._domainname) |
|
55 self._gid = dom.getID() |
|
56 if self._gid == 0: |
|
57 raise VMMAE(_(u"The domain “%s” doesn't exist.") %\ |
|
58 self._addr._domainname, ERR.NO_SUCH_DOMAIN) |
|
59 |
|
60 def _checkExpansion(self, limit): |
|
61 dbc = self._dbh.cursor() |
|
62 dbc.execute('SELECT count(gid) FROM alias where gid=%s AND address=%s', |
|
63 self._gid, self._addr._localpart) |
|
64 curEx = dbc.fetchone()[0] |
|
65 dbc.close() |
|
66 if curEx == limit: |
|
67 errmsg = _(u"""Can't add new destination to alias “%(address)s”. |
|
68 Currently this alias expands into %(count)i recipients. |
|
69 One more destination will render this alias unusable. |
|
70 Hint: Increase Postfix' virtual_alias_expansion_limit |
|
71 """) % {'address': self._addr, 'count': curEx} |
|
72 raise VMMAE(errmsg, ERR.ALIAS_EXCEEDS_EXPANSION_LIMIT) |
|
73 |
|
74 def save(self, expansion_limit): |
|
75 if self._dest is None: |
|
76 raise VMMAE(_(u"No destination address specified for alias."), |
|
77 ERR.ALIAS_MISSING_DEST) |
|
78 if self._isNew: |
|
79 self._checkExpansion(expansion_limit) |
|
80 dbc = self._dbh.cursor() |
|
81 dbc.execute("INSERT INTO alias (gid, address, destination) VALUES\ |
|
82 (%s, %s, %s)", self._gid, self._addr._localpart, str(self._dest)) |
|
83 self._dbh.commit() |
|
84 dbc.close() |
|
85 else: |
|
86 raise VMMAE( |
|
87 _(u"The alias “%(a)s” with destination “%(d)s” already exists.")\ |
|
88 % {'a': self._addr, 'd': self._dest}, ERR.ALIAS_EXISTS) |
|
89 |
|
90 def getInfo(self): |
|
91 dbc = self._dbh.cursor() |
|
92 dbc.execute('SELECT destination FROM alias WHERE gid=%s AND address=%s', |
|
93 self._gid, self._addr._localpart) |
|
94 destinations = dbc.fetchall() |
|
95 dbc.close() |
|
96 if len(destinations) > 0: |
|
97 targets = [destination[0] for destination in destinations] |
|
98 return targets |
|
99 else: |
|
100 raise VMMAE(_(u"The alias “%s” doesn't exist.") % self._addr, |
|
101 ERR.NO_SUCH_ALIAS) |
|
102 |
|
103 def delete(self): |
|
104 dbc = self._dbh.cursor() |
|
105 if self._dest is None: |
|
106 dbc.execute("DELETE FROM alias WHERE gid=%s AND address=%s", |
|
107 self._gid, self._addr._localpart) |
|
108 else: |
|
109 dbc.execute("DELETE FROM alias WHERE gid=%s AND address=%s AND \ |
|
110 destination=%s", self._gid, self._addr._localpart, str(self._dest)) |
|
111 rowcount = dbc.rowcount |
|
112 dbc.close() |
|
113 if rowcount > 0: |
|
114 self._dbh.commit() |
|
115 else: |
|
116 if self._dest is None: |
|
117 msg = _(u"The alias “%s” doesn't exist.") % self._addr |
|
118 else: |
|
119 msg = _(u"The alias “%(a)s” with destination “%(d)s” doesn't\ |
|
120 exist.") % {'a': self._addr, 'd': self._dest} |
|
121 raise VMMAE(msg, ERR.NO_SUCH_ALIAS) |
|
122 |
|