26 from VirtualMailManager.AliasDomain import AliasDomain |
26 from VirtualMailManager.AliasDomain import AliasDomain |
27 from VirtualMailManager.common import exec_ok |
27 from VirtualMailManager.common import exec_ok |
28 from VirtualMailManager.Config import Config as Cfg |
28 from VirtualMailManager.Config import Config as Cfg |
29 from VirtualMailManager.Domain import Domain, ace2idna, get_gid |
29 from VirtualMailManager.Domain import Domain, ace2idna, get_gid |
30 from VirtualMailManager.EmailAddress import EmailAddress |
30 from VirtualMailManager.EmailAddress import EmailAddress |
31 from VirtualMailManager.errors import VMMError, AliasError, DomainError, \ |
31 from VirtualMailManager.errors import VMMError, DomainError |
32 RelocatedError |
|
33 from VirtualMailManager.Relocated import Relocated |
32 from VirtualMailManager.Relocated import Relocated |
34 from VirtualMailManager.Transport import Transport |
33 from VirtualMailManager.Transport import Transport |
35 |
34 |
|
35 |
|
36 _ = lambda msg: msg |
36 |
37 |
37 RE_DOMAIN_SEARCH = """^[a-z0-9-\.]+$""" |
38 RE_DOMAIN_SEARCH = """^[a-z0-9-\.]+$""" |
38 RE_MBOX_NAMES = """^[\x20-\x25\x27-\x7E]*$""" |
39 RE_MBOX_NAMES = """^[\x20-\x25\x27-\x7E]*$""" |
39 TYPE_ACCOUNT = 0x1 |
40 TYPE_ACCOUNT = 0x1 |
40 TYPE_ALIAS = 0x2 |
41 TYPE_ALIAS = 0x2 |
41 TYPE_RELOCATED = 0x4 |
42 TYPE_RELOCATED = 0x4 |
42 _ = lambda msg: msg |
43 OTHER_TYPES = { |
|
44 TYPE_ACCOUNT: (_(u'an account'), ERR.ACCOUNT_EXISTS), |
|
45 TYPE_ALIAS: (_(u'an alias'), ERR.ALIAS_EXISTS), |
|
46 TYPE_RELOCATED: (_(u'a relocated user'), ERR.RELOCATED_EXISTS), |
|
47 } |
43 |
48 |
44 |
49 |
45 class Handler(object): |
50 class Handler(object): |
46 """Wrapper class to simplify the access on all the stuff from |
51 """Wrapper class to simplify the access on all the stuff from |
47 VirtualMailManager""" |
52 VirtualMailManager""" |
151 be returned.""" |
156 be returned.""" |
152 assert exclude in (TYPE_ACCOUNT, TYPE_ALIAS, TYPE_RELOCATED) and \ |
157 assert exclude in (TYPE_ACCOUNT, TYPE_ALIAS, TYPE_RELOCATED) and \ |
153 isinstance(address, EmailAddress) |
158 isinstance(address, EmailAddress) |
154 if exclude is not TYPE_ACCOUNT: |
159 if exclude is not TYPE_ACCOUNT: |
155 account = Account(self._dbh, address) |
160 account = Account(self._dbh, address) |
156 if account.uid > 0: |
161 if account: |
157 return TYPE_ACCOUNT |
162 return TYPE_ACCOUNT |
158 if exclude is not TYPE_ALIAS: |
163 if exclude is not TYPE_ALIAS: |
159 alias = Alias(self._dbh, address) |
164 alias = Alias(self._dbh, address) |
160 if alias: |
165 if alias: |
161 return TYPE_ALIAS |
166 return TYPE_ALIAS |
162 if exclude is not TYPE_RELOCATED: |
167 if exclude is not TYPE_RELOCATED: |
163 relocated = Relocated(self._dbh, address) |
168 relocated = Relocated(self._dbh, address) |
164 if relocated: |
169 if relocated: |
165 return TYPE_RELOCATED |
170 return TYPE_RELOCATED |
166 return 0 |
171 return 0 |
|
172 |
|
173 def _is_other_address(self, address, exclude): |
|
174 """Checks if *address* is known for an Account (TYPE_ACCOUNT), |
|
175 Alias (TYPE_ALIAS) or Relocated (TYPE_RELOCATED), except for |
|
176 *exclude*. Returns `False` if the address is not known for other |
|
177 types. |
|
178 |
|
179 Raises a `VMMError` if the address is known. |
|
180 """ |
|
181 other = self._chk_other_address_types(address, exclude) |
|
182 if not other: |
|
183 return False |
|
184 msg = _(u"There is already %(a_type)s with the address '%(address)s'.") |
|
185 raise VMMError(msg % {'a_type': OTHER_TYPES[other][0], |
|
186 'address': address}, OTHER_TYPES[other][1]) |
167 |
187 |
168 def __getAccount(self, address): |
188 def __getAccount(self, address): |
169 address = EmailAddress(address) |
189 address = EmailAddress(address) |
170 self.__dbConnect() |
190 self.__dbConnect() |
171 return Account(self._dbh, address) |
191 return Account(self._dbh, address) |
530 |
550 |
531 def aliasInfo(self, aliasaddress): |
551 def aliasInfo(self, aliasaddress): |
532 """Returns an iterator object for all destinations (`EmailAddress` |
552 """Returns an iterator object for all destinations (`EmailAddress` |
533 instances) for the `Alias` with the given *aliasaddress*.""" |
553 instances) for the `Alias` with the given *aliasaddress*.""" |
534 alias = self.__getAlias(aliasaddress) |
554 alias = self.__getAlias(aliasaddress) |
535 try: |
555 if alias: |
536 return alias.get_destinations() |
556 return alias.get_destinations() |
537 except AliasError, err: |
557 if not self._is_other_address(alias.address, TYPE_ALIAS): |
538 if err.code == ERR.NO_SUCH_ALIAS: |
558 raise VMMError(_(u"The alias '%s' doesn't exist.") % |
539 other = self._chk_other_address_types(alias.address, |
559 alias.address, ERR.NO_SUCH_ALIAS) |
540 TYPE_ALIAS) |
|
541 if other is TYPE_ACCOUNT: |
|
542 raise VMMError(_(u"There is already an account with the \ |
|
543 address '%s'.") % |
|
544 alias.address, ERR.ACCOUNT_EXISTS) |
|
545 elif other is TYPE_RELOCATED: |
|
546 raise VMMError(_(u"There is already a relocated user \ |
|
547 with the address '%s'.") % |
|
548 alias.address, ERR.RELOCATED_EXISTS) |
|
549 else: # unknown address |
|
550 raise |
|
551 else: # something other went wrong |
|
552 raise |
|
553 |
560 |
554 def aliasDelete(self, aliasaddress, targetaddress=None): |
561 def aliasDelete(self, aliasaddress, targetaddress=None): |
555 """Deletes the `Alias` *aliasaddress* with all its destinations from |
562 """Deletes the `Alias` *aliasaddress* with all its destinations from |
556 the database. If *targetaddress* is not ``None``, only this |
563 the database. If *targetaddress* is not ``None``, only this |
557 destination will be removed from the alias.""" |
564 destination will be removed from the alias.""" |
566 if details not in (None, 'du', 'aliases', 'full'): |
573 if details not in (None, 'du', 'aliases', 'full'): |
567 raise VMMError(_(u"Invalid argument: '%s'") % details, |
574 raise VMMError(_(u"Invalid argument: '%s'") % details, |
568 ERR.INVALID_AGUMENT) |
575 ERR.INVALID_AGUMENT) |
569 acc = self.__getAccount(emailaddress) |
576 acc = self.__getAccount(emailaddress) |
570 if not acc: |
577 if not acc: |
571 raise VMMError(_(u"The account '%s' doesn't exist.") % |
578 if not self._is_other_address(acc.address, TYPE_ACCOUNT): |
572 acc.address, ERR.NO_SUCH_ACCOUNT) |
579 raise VMMError(_(u"The account '%s' doesn't exist.") % |
|
580 acc.address, ERR.NO_SUCH_ACCOUNT) |
573 info = acc.get_info() |
581 info = acc.get_info() |
574 if self._Cfg.dget('account.disk_usage') or details in ('du', 'full'): |
582 if self._Cfg.dget('account.disk_usage') or details in ('du', 'full'): |
575 path = os.path.join(acc.home, info['mail_location'].split('/')[-1]) |
583 path = os.path.join(acc.home, info['mail_location'].split('/')[-1]) |
576 info['disk usage'] = self.__getDiskUsage(path) |
584 info['disk usage'] = self.__getDiskUsage(path) |
577 if details in (None, 'du'): |
585 if details in (None, 'du'): |
651 |
659 |
652 def relocatedInfo(self, emailaddress): |
660 def relocatedInfo(self, emailaddress): |
653 """Returns the target address of the relocated user with the given |
661 """Returns the target address of the relocated user with the given |
654 *emailaddress*.""" |
662 *emailaddress*.""" |
655 relocated = self.__getRelocated(emailaddress) |
663 relocated = self.__getRelocated(emailaddress) |
656 try: |
664 if relocated: |
657 return relocated.get_info() |
665 return relocated.get_info() |
658 except RelocatedError, err: |
666 if not self._is_other_address(relocated.address, TYPE_RELOCATED): |
659 if err.code == ERR.NO_SUCH_RELOCATED: |
667 raise VMMError(_(u"The relocated user '%s' doesn't exist.") % |
660 other = self._chk_other_address_types(relocated.address, |
668 relocated.address, ERR.NO_SUCH_RELOCATED) |
661 TYPE_RELOCATED) |
|
662 if other is TYPE_ACCOUNT: |
|
663 raise VMMError(_(u"There is already an account with the \ |
|
664 address '%s'.") % |
|
665 relocated.address, ERR.ACCOUNT_EXISTS) |
|
666 elif other is TYPE_ALIAS: |
|
667 raise VMMError(_(u"There is already an alias with the \ |
|
668 address '%s'.") % |
|
669 relocated.address, ERR.ALIAS_EXISTS) |
|
670 else: # unknown address |
|
671 raise |
|
672 else: # something other went wrong |
|
673 raise |
|
674 |
669 |
675 def relocatedDelete(self, emailaddress): |
670 def relocatedDelete(self, emailaddress): |
676 """Deletes the relocated user with the given *emailaddress* from |
671 """Deletes the relocated user with the given *emailaddress* from |
677 the database.""" |
672 the database.""" |
678 relocated = self.__getRelocated(emailaddress) |
673 relocated = self.__getRelocated(emailaddress) |