# Author: Zhang Huangbin import sys import ldap import web from libs import iredutils from libs.ldaplib import core, attrs, iredldif, ldaputils, deltree, connUtils, decorators session = web.config.get('_session') class Alias(core.LDAPWrap): def __del__(self): try: self.conn.unbind() except: pass @decorators.require_domain_access def listAccounts(self, domain, filter=None,): if domain is not None: self.domain = str(domain) self.domainDN = ldaputils.convKeywordToDN(self.domain, accountType='domain') else: pass if filter is not None: self.filter = filter else: self.filter = '(objectClass=mailAlias)' try: self.aliases = self.conn.search_s( attrs.DN_BETWEEN_ALIAS_AND_DOMAIN + self.domainDN, ldap.SCOPE_SUBTREE, self.filter, attrs.ALIAS_SEARCH_ATTRS, ) connutils = connUtils.Utils() connutils.updateAttrSingleValue(self.domainDN, 'domainCurrentAliasNumber', len(self.aliases)) return (True, self.aliases) except ldap.NO_SUCH_OBJECT: self.conn.add_s( attrs.DN_BETWEEN_ALIAS_AND_DOMAIN + self.domainDN, iredldif.ldif_group(attrs.GROUP_ALIASES), ) return (True, []) except ldap.SIZELIMIT_EXCEEDED: return (False, 'EXCEEDED_LDAP_SERVER_SIZELIMIT') except Exception, e: return (False, str(e)) @decorators.require_domain_access def add(self, domain, data): self.domain = web.safestr(domain).lower() if self.domain == '' or self.domain is None: return (False, 'EMPTY_DOMAIN') self.listname = web.safestr(data.get('listname')) if self.listname == '': return (False, 'EMPTY_LISTNAME') self.mail = self.listname + '@' + self.domain self.dn = ldaputils.convKeywordToDN(self.mail, accountType='alias') # Check whether account exist or not. connutils = connUtils.Utils() if connutils.isAccountExists(domain=self.domain, filter='(|(mail=%s)(shadowAddress=%s))' % (self.mail, self.mail)): return (False, 'ALREADY_EXISTS') ldif = iredldif.ldif_alias(self.mail, cn=data.get('cn')) try: self.conn.add_s(self.dn, ldif) web.logger(msg="Create mail alias: %s." % (self.mail), domain=self.domain, event='create',) return (True,) except ldap.ALREADY_EXISTS: return (False, 'ALREADY_EXISTS') except ldap.LDAPError, e: return (False, ldaputils.getExceptionDesc(e)) # Get profile of mail alias. @decorators.require_domain_access def profile(self, domain, mail): self.mail = web.safestr(mail) self.domain = self.mail.split('@', 1)[-1] if self.domain != domain: return web.seeother('/domains?msg=PERMISSION_DENIED') if not self.mail.endswith('@' + self.domain): return web.seeother('/domains?msg=PERMISSION_DENIED') self.dn = ldaputils.convKeywordToDN(self.mail, accountType='alias') try: self.alias_profile = self.conn.search_s( self.dn, ldap.SCOPE_BASE, '(&(objectClass=mailAlias)(mail=%s))' % self.mail, attrs.ALIAS_ATTRS_ALL, ) return (True, self.alias_profile) except Exception, e: return (False, ldaputils.getExceptionDesc(e)) # Get members of mail alias. # @ Return list of mail addresses. @decorators.require_domain_access def members(self, domain, mail,): self.mail = web.safestr(mail) self.domain = self.mail.split('@', 1)[1] if self.domain != domain: return web.seeother('/domains?msg=PERMISSION_DENIED') if not self.mail.endswith('@' + self.domain): return web.seeother('/domains?msg=PERMISSION_DENIED') # Get domain dn. self.dn = ldaputils.convKeywordToDN(self.mail, accountType='alias') try: # Search domain subtree. self.alias_members = self.conn.search_s( self.dn, ldap.SCOPE_SUBTREE, '(&(objectClass=mailAlias)(mail=%s))' % self.mail, ['mailForwardingAddress'], ) return (True, self.alias_members[0][1].get('mailForwardingAddress', [])) except Exception, e: return (False, ldaputils.getExceptionDesc(e)) # Get current members from mail alias or assign members to mail alias. @decorators.require_domain_access def assignOrRemoveMembers(self, domain, mail, data): self.mail = web.safestr(mail) self.memberMails= data.get('mailForwardingAddress', None) if self.domain != domain: return web.seeother('/domains?msg=PERMISSION_DENIED') if not self.mail.endswith('@' + self.domain): return web.seeother('/domains?msg=PERMISSION_DENIED') self.dn = ldaputils.convKeywordToDN(self.mail, accountType='alias') # Get action: assign or remove. if 'add' in data.keys(): self.action = 'add' self.msg = 'MEMBER_ASSIGNED_SUCCESS' elif 'delete' in data.keys(): self.action = 'delete' self.msg = 'MEMBER_REMOVED_SUCCESS' # Assign or remove. msg = {} for memberMail in self.memberMails: connutils = connUtils.Utils() result = connutils.addOrDelAttrValue( dn=self.dn, attr='mailForwardingAddress', value=memberMail, action=self.action, ) if result[0] is False: msg[memberMail] = result[1] if msg == {}: return (True, self.msg) else: return (False, msg) # Update mail alias profile. @decorators.require_domain_access def update(self, profile_type, mail, data,): self.profile_type = web.safestr(profile_type) self.mail = web.safestr(mail) self.domain = self.mail.split('@', 1)[1] self.dn = ldaputils.convKeywordToDN(self.mail, accountType='alias') mod_attrs = [] if self.profile_type == 'general': # Get cn. cn = data.get('cn', None) mod_attrs += ldaputils.getSingleModAttr(attr='cn', value=cn, default=self.mail.split('@')[0]) # Get accountStatus. if 'accountStatus' in data.keys(): accountStatus = 'active' else: accountStatus = 'disabled' mod_attrs += [ (ldap.MOD_REPLACE, 'accountStatus', accountStatus) ] # Get enabledService=displayedInGlobalAddressBook. if 'displayedInGlobalAddressBook' in data.keys(): mod_type = 'add' else: mod_type = 'delete' connutils = connUtils.Utils() result = connutils.addOrDelAttrValue( dn=self.dn, attr='enabledService', value='displayedInGlobalAddressBook', action=mod_type, ) if result[0] is False: return (False, ldaputils.getExceptionDesc(result)) #################### # Members # self.mailForwardingAddresses = [ str(v) for v in data.get('mailForwardingAddress', []) if iredutils.isEmail(str(v)) ] # Get mail forwarding addresses from form. self.newMailForwardingAddresses = set( web.safestr(v).lower() for v in data.get('newMailForwardingAddresses').splitlines() if iredutils.isEmail(str(v)) ) self.allMembers = set(self.mailForwardingAddresses) | self.newMailForwardingAddresses mod_attrs += [(ldap.MOD_REPLACE, 'mailForwardingAddress', list(self.allMembers))] try: self.conn.modify_s(self.dn, mod_attrs) return (True,) except Exception, e: return (False, ldaputils.getExceptionDesc(e)) # Delete mail alias. @decorators.require_domain_access def delete(self, domain, mails,): if mails is None or len(mails) == 0: return (False, 'INVALID_MAIL') self.mails = [str(v) for v in mails if iredutils.isEmail(v) and str(v).endswith('@'+domain)] result = {} for mail in self.mails: self.mail = web.safestr(mail) dn = ldaputils.convKeywordToDN(self.mail, accountType='alias') try: deltree.DelTree( self.conn, dn, ldap.SCOPE_SUBTREE ) web.logger( msg="Delete mail alias: %s." % (self.mail), domain=self.mail.split('@')[1], event='delete', ) except ldap.LDAPError, e: result[self.mail] = str(e) if result == {}: return (True,) else: return (False, ldaputils.getExceptionDesc(result)) # Enable or disable mail alias. @decorators.require_domain_access def enableOrDisableAccount(self, domain, mails, action, attr='accountStatus',): if mails is None or len(mails) == 0: return (False, 'NO_ACCOUNT_SELECTED') result = {} connutils = connUtils.Utils() for mail in mails: self.mail = web.safestr(mail).strip().lower() if not iredutils.isEmail(self.mail): continue self.domain = self.mail.split('@')[-1] self.dn = ldaputils.convKeywordToDN(self.mail, accountType='alias') try: connutils.enableOrDisableAccount( domain=self.domain, account=self.mail, dn=self.dn, action=web.safestr(action).strip().lower(), accountTypeInLogger='alias', ) except ldap.LDAPError, e: result[self.mail] = str(e) if result == {}: return (True,) else: return (False, ldaputils.getExceptionDesc(result))