26 from VirtualMailManager.Alias import Alias |
26 from VirtualMailManager.Alias import Alias |
27 from VirtualMailManager.AliasDomain import AliasDomain |
27 from VirtualMailManager.AliasDomain import AliasDomain |
28 from VirtualMailManager.Config import Config as Cfg |
28 from VirtualMailManager.Config import Config as Cfg |
29 from VirtualMailManager.Domain import Domain, get_gid |
29 from VirtualMailManager.Domain import Domain, 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, AliasError, DomainError, \ |
|
32 RelocatedError |
32 from VirtualMailManager.Relocated import Relocated |
33 from VirtualMailManager.Relocated import Relocated |
33 from VirtualMailManager.Transport import Transport |
34 from VirtualMailManager.Transport import Transport |
34 from VirtualMailManager.ext.Postconf import Postconf |
35 from VirtualMailManager.ext.Postconf import Postconf |
35 |
36 |
36 |
37 |
37 SALTCHARS = './0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ' |
38 SALTCHARS = './0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ' |
38 RE_DOMAIN_SEARCH = """^[a-z0-9-\.]+$""" |
39 RE_DOMAIN_SEARCH = """^[a-z0-9-\.]+$""" |
39 RE_MBOX_NAMES = """^[\x20-\x25\x27-\x7E]*$""" |
40 RE_MBOX_NAMES = """^[\x20-\x25\x27-\x7E]*$""" |
|
41 TYPE_ACCOUNT = 0x1 |
|
42 TYPE_ALIAS = 0x2 |
|
43 TYPE_RELOCATED = 0x4 |
40 |
44 |
41 |
45 |
42 class Handler(object): |
46 class Handler(object): |
43 """Wrapper class to simplify the access on all the stuff from |
47 """Wrapper class to simplify the access on all the stuff from |
44 VirtualMailManager""" |
48 VirtualMailManager""" |
141 dbc.execute("SET NAMES 'UTF8'") |
145 dbc.execute("SET NAMES 'UTF8'") |
142 dbc.close() |
146 dbc.close() |
143 except PgSQL.libpq.DatabaseError, e: |
147 except PgSQL.libpq.DatabaseError, e: |
144 raise VMMError(str(e), ERR.DATABASE_ERROR) |
148 raise VMMError(str(e), ERR.DATABASE_ERROR) |
145 |
149 |
146 def _exists(dbh, query): |
150 def _chk_other_address_types(self, address, exclude): |
147 dbc = dbh.cursor() |
151 """Checks if the EmailAddress *address* is known as `TYPE_ACCOUNT`, |
148 dbc.execute(query) |
152 `TYPE_ALIAS` or `TYPE_RELOCATED`, but not as the `TYPE_*` specified |
149 gid = dbc.fetchone() |
153 by *exclude*. If the *address* is known as one of the `TYPE_*`s |
150 dbc.close() |
154 the according `TYPE_*` constant will be returned. Otherwise 0 will |
151 if gid is None: |
155 be returned.""" |
152 return False |
156 assert exclude in (TYPE_ACCOUNT, TYPE_ALIAS, TYPE_RELOCATED) and \ |
153 else: |
157 isinstance(address, EmailAddress) |
154 return True |
158 if exclude is not TYPE_ACCOUNT: |
155 _exists = staticmethod(_exists) |
159 account = Account(self._dbh, address) |
156 |
160 if account.uid > 0: |
157 def accountExists(dbh, address): |
161 return TYPE_ACCOUNT |
158 sql = "SELECT gid FROM users WHERE gid = (SELECT gid FROM domain_name\ |
162 if exclude is not TYPE_ALIAS: |
159 WHERE domainname = '%s') AND local_part = '%s'" % (address.domainname, |
163 alias = Alias(self._dbh, address) |
160 address.localpart) |
164 if alias: |
161 return Handler._exists(dbh, sql) |
165 return TYPE_ALIAS |
162 accountExists = staticmethod(accountExists) |
166 if exclude is not TYPE_RELOCATED: |
163 |
167 relocated = Relocated(self._dbh, address) |
164 def aliasExists(dbh, address): |
168 if relocated: |
165 sql = "SELECT DISTINCT gid FROM alias WHERE gid = (SELECT gid FROM\ |
169 return TYPE_RELOCATED |
166 domain_name WHERE domainname = '%s') AND address = '%s'" % ( |
170 return 0 |
167 address.domainname, address.localpart) |
|
168 return Handler._exists(dbh, sql) |
|
169 aliasExists = staticmethod(aliasExists) |
|
170 |
|
171 def relocatedExists(dbh, address): |
|
172 sql = "SELECT gid FROM relocated WHERE gid = (SELECT gid FROM\ |
|
173 domain_name WHERE domainname = '%s') AND address = '%s'" % ( |
|
174 address.domainname, address.localpart) |
|
175 return Handler._exists(dbh, sql) |
|
176 relocatedExists = staticmethod(relocatedExists) |
|
177 |
171 |
178 def __getAccount(self, address, password=None): |
172 def __getAccount(self, address, password=None): |
179 address = EmailAddress(address) |
173 address = EmailAddress(address) |
180 if not password is None: |
174 if not password is None: |
181 password = self.__pwhash(password) |
175 password = self.__pwhash(password) |
595 """Returns an iterator object for all destinations (`EmailAddress` |
589 """Returns an iterator object for all destinations (`EmailAddress` |
596 instances) for the `Alias` with the given *aliasaddress*.""" |
590 instances) for the `Alias` with the given *aliasaddress*.""" |
597 alias = self.__getAlias(aliasaddress) |
591 alias = self.__getAlias(aliasaddress) |
598 try: |
592 try: |
599 return alias.get_destinations() |
593 return alias.get_destinations() |
600 except AliasError, e: |
594 except AliasError, err: |
601 if e.code == ERR.NO_SUCH_ALIAS: |
595 if err.code == ERR.NO_SUCH_ALIAS: |
602 if Handler.accountExists(self._dbh, alias._addr): |
596 other = self._chk_other_address_types(alias.address, |
603 raise VMMError( |
597 TYPE_ALIAS) |
604 _(u'There is already an account with address ā%sā.') % |
598 if other is TYPE_ACCOUNT: |
605 aliasaddress, ERR.ACCOUNT_EXISTS) |
599 raise VMMError(_(u"There is already an account with the \ |
606 if Handler.relocatedExists(self._dbh, alias._addr): |
600 address '%s'.") % |
607 raise VMMError(_(u'There is already a relocated user \ |
601 alias.address, ERR.ACCOUNT_EXISTS) |
608 with the address ā%sā.') % |
602 elif other is TYPE_RELOCATED: |
609 aliasaddress, ERR.RELOCATED_EXISTS) |
603 raise VMMError(_(u"There is already a relocated user \ |
610 raise |
604 with the address '%s'.") % |
611 else: |
605 alias.address, ERR.RELOCATED_EXISTS) |
|
606 else: # unknown address |
|
607 raise |
|
608 else: # something other went wrong |
612 raise |
609 raise |
613 |
610 |
614 def aliasDelete(self, aliasaddress, targetaddress=None): |
611 def aliasDelete(self, aliasaddress, targetaddress=None): |
615 """Deletes the `Alias` *aliasaddress* with all its destinations from |
612 """Deletes the `Alias` *aliasaddress* with all its destinations from |
616 the database. If *targetaddress* is not ``None``, only this |
613 the database. If *targetaddress* is not ``None``, only this |
687 |
684 |
688 def relocatedInfo(self, emailaddress): |
685 def relocatedInfo(self, emailaddress): |
689 """Returns the target address of the relocated user with the given |
686 """Returns the target address of the relocated user with the given |
690 *emailaddress*.""" |
687 *emailaddress*.""" |
691 relocated = self.__getRelocated(emailaddress) |
688 relocated = self.__getRelocated(emailaddress) |
692 return relocated.get_info() |
689 try: |
|
690 return relocated.get_info() |
|
691 except RelocatedError, err: |
|
692 if err.code == ERR.NO_SUCH_RELOCATED: |
|
693 other = self._chk_other_address_types(relocated.address, |
|
694 TYPE_RELOCATED) |
|
695 if other is TYPE_ACCOUNT: |
|
696 raise VMMError(_(u"There is already an account with the \ |
|
697 address '%s'.") % |
|
698 relocated.address, ERR.ACCOUNT_EXISTS) |
|
699 elif other is TYPE_ALIAS: |
|
700 raise VMMError(_(u"There is already an alias with the \ |
|
701 address '%s'.") % |
|
702 relocated.address, ERR.ALIAS_EXISTS) |
|
703 else: # unknown address |
|
704 raise |
|
705 else: # something other went wrong |
|
706 raise |
693 |
707 |
694 def relocatedDelete(self, emailaddress): |
708 def relocatedDelete(self, emailaddress): |
695 """Deletes the relocated user with the given *emailaddress* from |
709 """Deletes the relocated user with the given *emailaddress* from |
696 the database.""" |
710 the database.""" |
697 relocated = self.__getRelocated(emailaddress) |
711 relocated = self.__getRelocated(emailaddress) |