|
1 #!/usr/bin/env python |
|
2 # -*- coding: UTF-8 -*- |
|
3 # opyright 2007-2008 VEB IT |
|
4 # See COPYING for distribution information. |
|
5 # $Id$ |
|
6 |
|
7 """Virtual Mail Manager's Domain class to manage email domains.""" |
|
8 |
|
9 __author__ = 'Pascal Volk <p.volk@veb-it.de>' |
|
10 __version__ = 'rev '+'$Rev$'.split()[1] |
|
11 __date__ = '$Date$'.split()[1] |
|
12 |
|
13 from random import choice |
|
14 |
|
15 from Exceptions import VMMDomainException |
|
16 import constants.ERROR as ERR |
|
17 |
|
18 MAILDIR_CHARS = '0123456789abcdefghijklmnopqrstuvwxyz' |
|
19 |
|
20 class Domain: |
|
21 """Class to manage email domains.""" |
|
22 def __init__(self, dbh, domainname, basedir, transport=None): |
|
23 """Creates a new Domain instance. |
|
24 |
|
25 Keyword arguments: |
|
26 dbh -- a pyPgSQL.PgSQL.connection |
|
27 domainname -- name of the domain (str) |
|
28 transport -- see transport(5), default 'dovecot:' (str) |
|
29 """ |
|
30 self._dbh = dbh |
|
31 self._name = domainname |
|
32 self._basedir = basedir |
|
33 if transport is None: |
|
34 self._transport = 'dovecot:' |
|
35 else: |
|
36 self._transport = transport |
|
37 self._id = 0 |
|
38 self._domaindir = None |
|
39 self._exists() |
|
40 |
|
41 def _exists(self): |
|
42 """Checks if the domain already exists. |
|
43 |
|
44 If the domain exists _id will be set and returns True, otherwise False |
|
45 will be returned. |
|
46 """ |
|
47 dbc = self._dbh.cursor() |
|
48 dbc.execute("SELECT gid, domaindir FROM domains WHERE domainname=%s", |
|
49 self._name) |
|
50 result = dbc.fetchone() |
|
51 dbc.close() |
|
52 if result is not None: |
|
53 self._id, self._domaindir = result[0], result[1] |
|
54 return True |
|
55 else: |
|
56 return False |
|
57 |
|
58 def _setID(self): |
|
59 """Sets the ID of the domain.""" |
|
60 dbc = self._dbh.cursor() |
|
61 dbc.execute("SELECT nextval('domains_gid')") |
|
62 self._id = dbc.fetchone()[0] |
|
63 dbc.close() |
|
64 |
|
65 def _prepare(self): |
|
66 self._setID() |
|
67 self._domaindir = "%s/%s/%i" % (self._basedir, choice(MAILDIR_CHARS), |
|
68 self._id) |
|
69 |
|
70 def _has(self, what): |
|
71 """Checks if aliases or accounts are assigned to the domain. |
|
72 |
|
73 If there are assigned accounts or aliases True will be returned, |
|
74 otherwise False will be returned. |
|
75 |
|
76 Keyword arguments: |
|
77 what -- 'alias' or 'users' (strings) |
|
78 """ |
|
79 if what not in ['alias', 'users']: |
|
80 return False |
|
81 dbc = self._dbh.cursor() |
|
82 if what == 'users': |
|
83 dbc.execute("SELECT count(gid) FROM users WHERE gid=%s", self._id) |
|
84 else: |
|
85 dbc.execute("SELECT count(gid) FROM alias WHERE gid=%s", self._id) |
|
86 count = dbc.fetchone() |
|
87 dbc.close() |
|
88 if count[0] > 0: |
|
89 return True |
|
90 else: |
|
91 return False |
|
92 |
|
93 def _chkDelete(self, delUser, delAlias): |
|
94 """Checks dependencies for deletion. |
|
95 |
|
96 Keyword arguments: |
|
97 delUser -- ignore available accounts (bool) |
|
98 delAlias -- ignore available aliases (bool) |
|
99 """ |
|
100 if not delUser: |
|
101 hasUser = self._has('users') |
|
102 else: |
|
103 hasUser = False |
|
104 if not delAlias: |
|
105 hasAlias = self._has('alias') |
|
106 else: |
|
107 hasAlias = False |
|
108 if hasUser and hasAlias: |
|
109 raise VMMDomainException(('There are accounts and aliases.', |
|
110 ERR.ACCOUNT_AND_ALIAS_PRESENT)) |
|
111 elif hasUser: |
|
112 raise VMMDomainException(('There are accounts.', |
|
113 ERR.ACCOUNT_PRESENT)) |
|
114 elif hasAlias: |
|
115 raise VMMDomainException(('There are aliases.', ERR.ALIAS_PRESENT)) |
|
116 |
|
117 def save(self): |
|
118 """Stores the new domain in the database.""" |
|
119 if self._id < 1: |
|
120 self._prepare() |
|
121 dbc = self._dbh.cursor() |
|
122 dbc.execute("INSERT INTO domains (gid, domainname, transport,\ |
|
123 domaindir) VALUES (%s, %s, %s, %s)", self._id, self._name, self._transport, |
|
124 self._domaindir) |
|
125 self._dbh.commit() |
|
126 dbc.close() |
|
127 else: |
|
128 raise VMMDomainException(('Domain already exists.', |
|
129 ERR.DOMAIN_EXISTS)) |
|
130 |
|
131 def delete(self, delUser=False, delAlias=False): |
|
132 """Deletes the domain. |
|
133 |
|
134 Keyword arguments: |
|
135 delUser -- force deletion of available accounts (bool) |
|
136 delAlias -- force deletion of available aliases (bool) |
|
137 """ |
|
138 if self._id > 0: |
|
139 self._chkDelete(delUser, delAlias) |
|
140 dbc = self._dbh.cursor() |
|
141 dbc.execute('DELETE FROM alias WHERE gid=%s', self._id) |
|
142 dbc.execute('DELETE FROM users WHERE gid=%s', self._id) |
|
143 dbc.execute('DELETE FROM relocated WHERE gid=%s', self._id) |
|
144 dbc.execute('DELETE FROM domains WHERE gid=%s', self._id) |
|
145 self._dbh.commit() |
|
146 dbc.close() |
|
147 else: |
|
148 raise VMMDomainException(("Domain doesn't exist yet.", |
|
149 ERR.NO_SUCH_DOMAIN)) |
|
150 |
|
151 def updateTransport(self, transport): |
|
152 """Sets a new transport for the domain. |
|
153 |
|
154 Keyword arguments: |
|
155 transport -- the new transport (str) |
|
156 """ |
|
157 if self._id > 0: |
|
158 dbc = self._dbh.cursor() |
|
159 dbc.execute("UPDATE domains SET transport=%s WHERE gid=%s", |
|
160 transport, self._id) |
|
161 if dbc.rowcount > 0: |
|
162 self._dbh.commit() |
|
163 dbc.close() |
|
164 else: |
|
165 raise VMMDomainException(("Domain doesn't exist yet.", |
|
166 ERR.NO_SUCH_DOMAIN)) |
|
167 |
|
168 def getID(self): |
|
169 """Returns the ID of the domain.""" |
|
170 return self._id |
|
171 |
|
172 def getDir(self): |
|
173 """Returns the directory of the domain.""" |
|
174 return self._domaindir |
|
175 |
|
176 def getInfo(self): |
|
177 """Returns a dictionary with information about the domain.""" |
|
178 sql = """\ |
|
179 SELECT gid, domainname, transport, domaindir, count(uid) AS accounts, aliases |
|
180 FROM domains |
|
181 LEFT JOIN users USING (gid) |
|
182 LEFT JOIN vmm_alias_count USING (gid) |
|
183 WHERE gid = %i |
|
184 GROUP BY gid, domainname, transport, domaindir, aliases""" % self._id |
|
185 dbc = self._dbh.cursor() |
|
186 dbc.execute(sql) |
|
187 info = dbc.fetchone() |
|
188 dbc.close() |
|
189 if info is None: |
|
190 raise VMMDomainException(("Domain doesn't exist yet.", |
|
191 ERR.NO_SUCH_DOMAIN)) |
|
192 else: |
|
193 keys = ['gid', 'domainname', 'transport', 'domaindir', 'accounts', |
|
194 'aliases'] |
|
195 return dict(zip(keys, info)) |
|
196 |
|
197 def getAccounts(self): |
|
198 """Returns a list with all accounts from the domain.""" |
|
199 dbc = self._dbh.cursor() |
|
200 dbc.execute("SELECT userid AS users FROM dovecot_user WHERE gid = %s", |
|
201 self._id) |
|
202 users = dbc.fetchall() |
|
203 dbc.close() |
|
204 accounts = [] |
|
205 if len(users) > 0: |
|
206 for account in users: |
|
207 accounts.append(account[0]) |
|
208 return accounts |
|
209 |
|
210 def getAliases(self): |
|
211 """Returns a list with all aliases from the domain.""" |
|
212 dbc = self._dbh.cursor() |
|
213 dbc.execute("SELECT DISTINCT address FROM postfix_alias WHERE gid=%s", |
|
214 self._id) |
|
215 addresses = dbc.fetchall() |
|
216 dbc.close() |
|
217 aliases = [] |
|
218 if len(addresses) > 0: |
|
219 for alias in addresses: |
|
220 aliases.append(alias[0]) |
|
221 return aliases |