112 dbc.close() |
112 dbc.close() |
113 except PgSQL.libpq.DatabaseError, e: |
113 except PgSQL.libpq.DatabaseError, e: |
114 raise VMMException((str(e), ERR.DATABASE_ERROR)) |
114 raise VMMException((str(e), ERR.DATABASE_ERROR)) |
115 |
115 |
116 def __chkLocalpart(self, localpart): |
116 def __chkLocalpart(self, localpart): |
117 """Validates the local part of an email address. |
117 """Validates the local part of an e-mail address. |
118 |
118 |
119 Keyword arguments: |
119 Keyword arguments: |
120 localpart -- the email address that should be validated (str) |
120 localpart -- the e-mail address that should be validated (str) |
121 """ |
121 """ |
122 if len(localpart) > 64: |
122 if len(localpart) > 64: |
123 raise VMMException(('The local part is too long', |
123 raise VMMException(('The local part is too long', |
124 ERR.LOCALPART_TOO_LONG)) |
124 ERR.LOCALPART_TOO_LONG)) |
125 if re.compile(RE_LOCALPART).search(localpart): |
125 if re.compile(RE_LOCALPART).search(localpart): |
126 raise VMMException(( |
126 raise VMMException(( |
127 'The local part «%s» contains invalid characters.' % localpart, |
127 'The local part »%s« contains invalid characters.' % localpart, |
128 ERR.LOCALPART_INVALID)) |
128 ERR.LOCALPART_INVALID)) |
129 return localpart |
129 return localpart |
130 |
130 |
131 def __idn2ascii(self, domainname): |
131 def __idn2ascii(self, domainname): |
132 """Converts an idn domainname in punycode. |
132 """Converts an idn domainname in punycode. |
168 if not re.match(RE_DOMAIN, domainname): |
168 if not re.match(RE_DOMAIN, domainname): |
169 raise VMMException(('The domain name is invalid.', |
169 raise VMMException(('The domain name is invalid.', |
170 ERR.DOMAIN_INVALID)) |
170 ERR.DOMAIN_INVALID)) |
171 return domainname |
171 return domainname |
172 |
172 |
173 def __chkEmailadress(self, address): |
173 def __chkEmailAddress(self, address): |
174 try: |
174 try: |
175 localpart, domain = address.split('@') |
175 localpart, domain = address.split('@') |
176 except ValueError: |
176 except ValueError: |
177 raise VMMException(("Missing '@' sign in emailaddress «%s»." % |
177 raise VMMException(("Missing '@' sign in e-mail address »%s«." % |
178 address, ERR.INVALID_ADDRESS)) |
178 address, ERR.INVALID_ADDRESS)) |
179 except AttributeError: |
179 except AttributeError: |
180 raise VMMException(("'%s' looks not like an email address." % |
180 raise VMMException(("»%s« looks not like an e-mail address." % |
181 address, ERR.INVALID_ADDRESS)) |
181 address, ERR.INVALID_ADDRESS)) |
182 domain = self.__chkDomainname(domain) |
182 domain = self.__chkDomainname(domain) |
183 localpart = self.__chkLocalpart(localpart) |
183 localpart = self.__chkLocalpart(localpart) |
184 return '%s@%s' % (localpart, domain) |
184 return '%s@%s' % (localpart, domain) |
185 |
185 |
186 def __getAccount(self, address, password=None): |
186 def __getAccount(self, address, password=None): |
187 address = self.__chkEmailadress(address) |
187 address = self.__chkEmailAddress(address) |
188 self.__dbConnect() |
188 self.__dbConnect() |
189 if not password is None: |
189 if not password is None: |
190 password = self.__pwhash(password) |
190 password = self.__pwhash(password) |
191 return Account(self.__dbh, self.__Cfg.get('maildir', 'base'), address, |
191 return Account(self.__dbh, self.__Cfg.get('maildir', 'base'), address, |
192 password) |
192 password) |
193 |
193 |
194 def __getAlias(self, address, destination=None): |
194 def __getAlias(self, address, destination=None): |
195 address = self.__chkEmailadress(address) |
195 address = self.__chkEmailAddress(address) |
196 if not destination is None: |
196 if not destination is None: |
197 if destination.count('@'): |
197 if destination.count('@'): |
198 destination = self.__chkEmailadress(destination) |
198 destination = self.__chkEmailAddress(destination) |
199 else: |
199 else: |
200 destination = self.__chkLocalpart(destination) |
200 destination = self.__chkLocalpart(destination) |
201 self.__dbConnect() |
201 self.__dbConnect() |
202 return Alias(self.__dbh, address, self.__Cfg.get('maildir', 'base'), |
202 return Alias(self.__dbh, address, self.__Cfg.get('maildir', 'base'), |
203 destination) |
203 destination) |
355 dom = self.__getDomain(domainname, None) |
355 dom = self.__getDomain(domainname, None) |
356 dom.updateTransport(transport) |
356 dom.updateTransport(transport) |
357 |
357 |
358 def domain_delete(self, domainname, force=None): |
358 def domain_delete(self, domainname, force=None): |
359 if not force is None and force not in ['deluser','delalias','delall']: |
359 if not force is None and force not in ['deluser','delalias','delall']: |
360 raise VMMDomainException(('Invalid option: «%s»' % force, |
360 raise VMMDomainException(('Invalid argument: «%s»' % force, |
361 ERR.INVALID_OPTION)) |
361 ERR.INVALID_OPTION)) |
362 dom = self.__getDomain(domainname) |
362 dom = self.__getDomain(domainname) |
363 gid = dom.getID() |
363 gid = dom.getID() |
364 domdir = dom.getDir() |
364 domdir = dom.getDir() |
365 if self.__Cfg.getboolean('misc', 'forcedel') or force == 'delall': |
365 if self.__Cfg.getboolean('misc', 'forcedel') or force == 'delall': |
384 if detailed is None: |
384 if detailed is None: |
385 return dominfo |
385 return dominfo |
386 elif detailed == 'detailed': |
386 elif detailed == 'detailed': |
387 return dominfo, dom.getAccounts(), dom.getAliases() |
387 return dominfo, dom.getAccounts(), dom.getAliases() |
388 else: |
388 else: |
389 raise VMMDomainException(('Invalid option: «%s»' % detailed, |
389 raise VMMDomainException(('Invalid argument: »%s«' % detailed, |
390 ERR.INVALID_OPTION)) |
390 ERR.INVALID_OPTION)) |
391 |
391 |
392 def user_add(self, emailaddress, password): |
392 def user_add(self, emailaddress, password): |
393 acc = self.__getAccount(emailaddress, password) |
393 acc = self.__getAccount(emailaddress, password) |
394 acc.save(self.__Cfg.get('maildir', 'folder')) |
394 acc.save(self.__Cfg.get('maildir', 'folder')) |