Commits

Zhang Huangbin committed 6962a9a

Update directory structure.

  • Participants
  • Parent commits 9a7b574

Comments (0)

Files changed (10)

 sys.path.append(os.path.abspath(os.path.dirname(__file__)) + '/plugins')
 
 if settings.backend == 'ldap':
-    from libs.ldaplib import LDAPModeler as Modeler
+    from libs.ldaplib.modeler import Modeler
 elif settings.backend in ['mysql', 'pgsql']:
-    from libs.sqllib import SQLModeler as Modeler
+    from libs.sql.modeler import Modeler
 else:
     sys.exit('Invalid backend, it must be ldap, mysql or pgsql.')
 

File libs/ldap_conn_utils.py

-# Author: Zhang Huangbin <zhb _at_ iredmail.org>
-
-import logging
-import ldap
-import settings
-from libs import SMTP_ACTIONS
-
-
-def get_account_ldif(conn, account, attrlist=None):
-    logging.debug('[+] Getting LDIF data of account: %s' % account)
-
-    ldap_filter = '(&(|(mail=%s)(shadowAddress=%s))(|(objectClass=mailUser)(objectClass=mailList)(objectClass=mailAlias)))' % (account, account)
-
-    logging.debug('search filter: %s' % ldap_filter)
-    logging.debug('search attributes: %s' % str(attrlist))
-    if not isinstance(attrlist, list):
-        # Attribute list must be None or non-empty list
-        attrlist = None
-
-    try:
-        result = conn.search_s(settings.ldap_basedn,
-                               ldap.SCOPE_SUBTREE,
-                               ldap_filter,
-                               attrlist)
-
-        if len(result) == 1:
-            logging.debug('result: %s' % str(result))
-            dn, entry = result[0]
-            return (dn, entry)
-        else:
-            logging.debug('Not a local account.')
-            return (None, None)
-    except Exception, e:
-        logging.debug('!!! ERROR !!! result: %s' % str(e))
-        return (None, None)
-
-
-def get_allowed_senders_of_mail_list(conn,
-                                     base_dn,
-                                     dn_of_mail_list,
-                                     sender,
-                                     recipient,
-                                     policy):
-    """return search_result_list_based_on_access_policy"""
-
-    logging.debug('[+] Getting allowed senders of mail list: %s' % recipient)
-    recipient_domain = recipient.split('@', 1)[-1]
-
-    # Set base dn as domain dn.
-    domaindn = 'domainName=' + recipient_domain + ',' + base_dn
-
-    # Default search scope. 2==ldap.SCOPE_SUBTREE
-    searchScope = 2
-
-    # Set search filter, attributes based on policy.
-    # Override base dn, scope if necessary.
-    if policy in ['membersonly', 'members']:
-        basedn = domaindn
-        # Filter: get mail list members.
-        searchFilter = "(&(|(objectclass=mailUser)(objectClass=mailExternalUser))(accountStatus=active)(memberOfGroup=%s))" % (recipient, )
-
-        # Get both mail and shadowAddress.
-        searchAttrs = ['mail', 'shadowAddress', ]
-
-    elif policy in ['allowedonly', 'moderatorsonly', 'moderators']:
-        # Get mail list moderators.
-        basedn = dn_of_mail_list
-        searchScope = 0     # Use ldap.SCOPE_BASE to improve performance.
-        searchFilter = "(&(objectclass=mailList)(mail=%s))" % (recipient, )
-        searchAttrs = ['listAllowedUser']
-
-    else:
-        basedn = domaindn
-        # Policy: policy==membersAndModeratorsOnly or not set.
-        # Filter used to get both members and moderators.
-        searchFilter = "(|(&(|(objectClass=mailUser)(objectClass=mailExternalUser))(memberOfGroup=%s))(&(objectclass=mailList)(mail=%s)))" % (recipient, recipient, )
-        searchAttrs = ['mail', 'shadowAddress', 'listAllowedUser', ]
-
-    logging.debug('base dn: %s' % basedn)
-    logging.debug('search scope: %s' % searchScope)
-    logging.debug('search filter: %s' % searchFilter)
-    logging.debug('search attributes: %s' % ', '.join(searchAttrs))
-
-    try:
-        result = conn.search_s(basedn, searchScope, searchFilter, searchAttrs)
-        userList = []
-        for obj in result:
-            for k in searchAttrs:
-                if k in obj[1].keys():
-                    # Example of result data:
-                    # [('dn', {'listAllowedUser': ['user@domain.ltd']})]
-                    userList += obj[1][k]
-                else:
-                    pass
-
-        # Exclude mail list itself.
-        if recipient in userList:
-            userList.remove(recipient)
-
-        logging.debug('result: %s' % str(userList))
-
-        # Query once more to get 'shadowAddress'.
-        if len(userList) > 0 and (policy == 'allowedonly' or policy == 'moderatorsonly'):
-            logging.debug('Addition query to get user aliases...')
-
-            basedn = 'ou=Users,' + domaindn
-            searchFilter = '(&(objectClass=mailUser)(enabledService=shadowaddress)(|'
-            for i in userList:
-                searchFilter += '(mail=%s)' % i
-            searchFilter += '))'
-
-            searchAttrs = ['shadowAddress', ]
-
-            logging.debug('base dn: %s' % basedn)
-            logging.debug('search scope: 2 (ldap.SCOPE_SUBTREE)')
-            logging.debug('search filter: %s' % searchFilter)
-            logging.debug('search attributes: %s' % ', '.join(searchAttrs))
-
-            try:
-                resultOfShadowAddresses = conn.search_s(
-                    'ou=Users,' + domaindn,
-                    2,  # ldap.SCOPE_SUBTREE
-                    searchFilter,
-                    ['mail', 'shadowAddress', ],
-                )
-
-                for obj in resultOfShadowAddresses:
-                    for k in searchAttrs:
-                        if k in obj[1].keys():
-                            # Example of result data:
-                            # [('dn', {'listAllowedUser': ['user@domain.ltd']})]
-                            userList += obj[1][k]
-                        else:
-                            pass
-
-                logging.debug('final result: %s' % str(userList))
-
-            except Exception, e:
-                logging.debug('Error: %s' % str(e))
-
-        return userList
-    except Exception, e:
-        logging.debug('Error: %s' % str(e))
-        return []
-
-
-def apply_plugin(plugin, **kwargs):
-    action = SMTP_ACTIONS['default']
-
-    logging.debug('--> Apply plugin: %s' % plugin.__name__)
-    try:
-        action = plugin.restriction(**kwargs)
-        logging.debug('<-- Result: %s' % action)
-    except Exception, e:
-        logging.debug('<!> Error: %s' % str(e))
-
-    return action

File libs/ldaplib.py

-# Author: Zhang Huangbin <zhb _at_ iredmail.org>
-
-import sys
-import ldap
-import logging
-import settings
-from libs import SMTP_ACTIONS, ldap_conn_utils
-
-
-class LDAPModeler:
-    def __init__(self):
-        # Initialize ldap connection.
-        try:
-            self.conn = ldap.initialize(settings.ldap_uri)
-            logging.debug('LDAP connection initialied success.')
-        except Exception, e:
-            logging.error('LDAP initialized failed: %s.' % str(e))
-            sys.exit()
-
-        # Bind to ldap server.
-        try:
-            self.conn.bind_s(settings.ldap_binddn, settings.ldap_bindpw)
-            logging.debug('LDAP bind success.')
-        except ldap.INVALID_CREDENTIALS:
-            logging.error('LDAP bind failed: incorrect bind dn or password.')
-            sys.exit()
-        except Exception, e:
-            logging.error('LDAP bind failed: %s.' % str(e))
-            sys.exit()
-
-    def __del__(self):
-        try:
-            self.conn.unbind_s()
-            logging.debug('Close LDAP connection.')
-        except Exception, e:
-            logging.debug('Error while closing connection: %s' % str(e))
-
-    def handle_data(self, smtp_session_map,
-                    plugins=[],
-                    plugins_for_sender=[],
-                    plugins_for_recipient=[],
-                    plugins_for_misc=[],
-                    sender_search_attrlist=None,
-                    recipient_search_attrlist=None,
-                    ):
-        # No sender or recipient in smtp session.
-        if not 'sender' in smtp_session_map or not 'recipient' in smtp_session_map:
-            return SMTP_ACTIONS['defer']
-
-        # Not a valid email address.
-        if len(smtp_session_map['sender']) < 6:
-            return 'DUNNO'
-
-        # No plugins available.
-        if not plugins:
-            return 'DUNNO'
-
-        # Check whether we should get sender/recipient LDIF data first
-        get_sender_ldif = False
-        get_recipient_ldif = False
-        if plugins_for_sender:
-            get_sender_ldif = True
-
-        if plugins_for_recipient:
-            get_recipient_ldif = True
-
-        # Get account dn and LDIF data.
-        plugin_kwargs = {'smtpSessionData': smtp_session_map,
-                         'conn': self.conn,
-                         'baseDn': settings.ldap_basedn,
-                         'senderDn': None,
-                         'senderLdif': None,
-                         'recipientDn': None,
-                         'recipientLdif': None,
-                         }
-
-        if get_sender_ldif:
-            senderDn, senderLdif = ldap_conn_utils.get_account_ldif(
-                conn=self.conn,
-                account=smtp_session_map['sender'],
-                attrlist=sender_search_attrlist,
-            )
-            plugin_kwargs['senderDn'] = senderDn
-            plugin_kwargs['senderLdif'] = senderLdif
-
-            for plugin in plugins_for_sender:
-                action = ldap_conn_utils.apply_plugin(plugin, **plugin_kwargs)
-                if not action.startswith('DUNNO'):
-                    return action
-
-        if get_recipient_ldif:
-            recipientDn, recipientLdif = ldap_conn_utils.get_account_ldif(
-                conn=self.conn,
-                account=smtp_session_map['recipient'],
-                attrlist=recipient_search_attrlist,
-            )
-            plugin_kwargs['recipientDn'] = recipientDn
-            plugin_kwargs['recipientLdif'] = recipientLdif
-
-            for plugin in plugins_for_recipient:
-                action = ldap_conn_utils.apply_plugin(plugin, **plugin_kwargs)
-                if not action.startswith('DUNNO'):
-                    return action
-
-        for plugin in plugins_for_misc:
-            action = ldap_conn_utils.apply_plugin(plugin, **plugin_kwargs)
-            if not action.startswith('DUNNO'):
-                return action
-
-        return SMTP_ACTIONS['default']

File libs/ldaplib/__init__.py

Empty file added.

File libs/ldaplib/conn_utils.py

+# Author: Zhang Huangbin <zhb _at_ iredmail.org>
+
+import logging
+import ldap
+import settings
+from libs import SMTP_ACTIONS
+
+
+def get_account_ldif(conn, account, attrlist=None):
+    logging.debug('[+] Getting LDIF data of account: %s' % account)
+
+    ldap_filter = '(&(|(mail=%s)(shadowAddress=%s))(|(objectClass=mailUser)(objectClass=mailList)(objectClass=mailAlias)))' % (account, account)
+
+    logging.debug('search filter: %s' % ldap_filter)
+    logging.debug('search attributes: %s' % str(attrlist))
+    if not isinstance(attrlist, list):
+        # Attribute list must be None or non-empty list
+        attrlist = None
+
+    try:
+        result = conn.search_s(settings.ldap_basedn,
+                               ldap.SCOPE_SUBTREE,
+                               ldap_filter,
+                               attrlist)
+
+        if len(result) == 1:
+            logging.debug('result: %s' % str(result))
+            dn, entry = result[0]
+            return (dn, entry)
+        else:
+            logging.debug('Not a local account.')
+            return (None, None)
+    except Exception, e:
+        logging.debug('!!! ERROR !!! result: %s' % str(e))
+        return (None, None)
+
+
+def get_allowed_senders_of_mail_list(conn,
+                                     base_dn,
+                                     dn_of_mail_list,
+                                     sender,
+                                     recipient,
+                                     policy):
+    """return search_result_list_based_on_access_policy"""
+
+    logging.debug('[+] Getting allowed senders of mail list: %s' % recipient)
+    recipient_domain = recipient.split('@', 1)[-1]
+
+    # Set base dn as domain dn.
+    domaindn = 'domainName=' + recipient_domain + ',' + base_dn
+
+    # Default search scope. 2==ldap.SCOPE_SUBTREE
+    searchScope = 2
+
+    # Set search filter, attributes based on policy.
+    # Override base dn, scope if necessary.
+    if policy in ['membersonly', 'members']:
+        basedn = domaindn
+        # Filter: get mail list members.
+        searchFilter = "(&(|(objectclass=mailUser)(objectClass=mailExternalUser))(accountStatus=active)(memberOfGroup=%s))" % (recipient, )
+
+        # Get both mail and shadowAddress.
+        searchAttrs = ['mail', 'shadowAddress', ]
+
+    elif policy in ['allowedonly', 'moderatorsonly', 'moderators']:
+        # Get mail list moderators.
+        basedn = dn_of_mail_list
+        searchScope = 0     # Use ldap.SCOPE_BASE to improve performance.
+        searchFilter = "(&(objectclass=mailList)(mail=%s))" % (recipient, )
+        searchAttrs = ['listAllowedUser']
+
+    else:
+        basedn = domaindn
+        # Policy: policy==membersAndModeratorsOnly or not set.
+        # Filter used to get both members and moderators.
+        searchFilter = "(|(&(|(objectClass=mailUser)(objectClass=mailExternalUser))(memberOfGroup=%s))(&(objectclass=mailList)(mail=%s)))" % (recipient, recipient, )
+        searchAttrs = ['mail', 'shadowAddress', 'listAllowedUser', ]
+
+    logging.debug('base dn: %s' % basedn)
+    logging.debug('search scope: %s' % searchScope)
+    logging.debug('search filter: %s' % searchFilter)
+    logging.debug('search attributes: %s' % ', '.join(searchAttrs))
+
+    try:
+        result = conn.search_s(basedn, searchScope, searchFilter, searchAttrs)
+        userList = []
+        for obj in result:
+            for k in searchAttrs:
+                if k in obj[1].keys():
+                    # Example of result data:
+                    # [('dn', {'listAllowedUser': ['user@domain.ltd']})]
+                    userList += obj[1][k]
+                else:
+                    pass
+
+        # Exclude mail list itself.
+        if recipient in userList:
+            userList.remove(recipient)
+
+        logging.debug('result: %s' % str(userList))
+
+        # Query once more to get 'shadowAddress'.
+        if len(userList) > 0 and (policy == 'allowedonly' or policy == 'moderatorsonly'):
+            logging.debug('Addition query to get user aliases...')
+
+            basedn = 'ou=Users,' + domaindn
+            searchFilter = '(&(objectClass=mailUser)(enabledService=shadowaddress)(|'
+            for i in userList:
+                searchFilter += '(mail=%s)' % i
+            searchFilter += '))'
+
+            searchAttrs = ['shadowAddress', ]
+
+            logging.debug('base dn: %s' % basedn)
+            logging.debug('search scope: 2 (ldap.SCOPE_SUBTREE)')
+            logging.debug('search filter: %s' % searchFilter)
+            logging.debug('search attributes: %s' % ', '.join(searchAttrs))
+
+            try:
+                resultOfShadowAddresses = conn.search_s(
+                    'ou=Users,' + domaindn,
+                    2,  # ldap.SCOPE_SUBTREE
+                    searchFilter,
+                    ['mail', 'shadowAddress', ],
+                )
+
+                for obj in resultOfShadowAddresses:
+                    for k in searchAttrs:
+                        if k in obj[1].keys():
+                            # Example of result data:
+                            # [('dn', {'listAllowedUser': ['user@domain.ltd']})]
+                            userList += obj[1][k]
+                        else:
+                            pass
+
+                logging.debug('final result: %s' % str(userList))
+
+            except Exception, e:
+                logging.debug('Error: %s' % str(e))
+
+        return userList
+    except Exception, e:
+        logging.debug('Error: %s' % str(e))
+        return []
+
+
+def apply_plugin(plugin, **kwargs):
+    action = SMTP_ACTIONS['default']
+
+    logging.debug('--> Apply plugin: %s' % plugin.__name__)
+    try:
+        action = plugin.restriction(**kwargs)
+        logging.debug('<-- Result: %s' % action)
+    except Exception, e:
+        logging.debug('<!> Error: %s' % str(e))
+
+    return action

File libs/ldaplib/modeler.py

+# Author: Zhang Huangbin <zhb _at_ iredmail.org>
+
+import sys
+import ldap
+import logging
+import settings
+from libs import SMTP_ACTIONS
+from libs.ldaplib import conn_utils
+
+
+class Modeler:
+    def __init__(self):
+        # Initialize ldap connection.
+        try:
+            self.conn = ldap.initialize(settings.ldap_uri)
+            logging.debug('LDAP connection initialied success.')
+        except Exception, e:
+            logging.error('LDAP initialized failed: %s.' % str(e))
+            sys.exit()
+
+        # Bind to ldap server.
+        try:
+            self.conn.bind_s(settings.ldap_binddn, settings.ldap_bindpw)
+            logging.debug('LDAP bind success.')
+        except ldap.INVALID_CREDENTIALS:
+            logging.error('LDAP bind failed: incorrect bind dn or password.')
+            sys.exit()
+        except Exception, e:
+            logging.error('LDAP bind failed: %s.' % str(e))
+            sys.exit()
+
+    def __del__(self):
+        try:
+            self.conn.unbind_s()
+            logging.debug('Close LDAP connection.')
+        except Exception, e:
+            logging.debug('Error while closing connection: %s' % str(e))
+
+    def handle_data(self, smtp_session_map,
+                    plugins=[],
+                    plugins_for_sender=[],
+                    plugins_for_recipient=[],
+                    plugins_for_misc=[],
+                    sender_search_attrlist=None,
+                    recipient_search_attrlist=None,
+                    ):
+        # No sender or recipient in smtp session.
+        if not 'sender' in smtp_session_map or not 'recipient' in smtp_session_map:
+            return SMTP_ACTIONS['defer']
+
+        # Not a valid email address.
+        if len(smtp_session_map['sender']) < 6:
+            return 'DUNNO'
+
+        # No plugins available.
+        if not plugins:
+            return 'DUNNO'
+
+        # Check whether we should get sender/recipient LDIF data first
+        get_sender_ldif = False
+        get_recipient_ldif = False
+        if plugins_for_sender:
+            get_sender_ldif = True
+
+        if plugins_for_recipient:
+            get_recipient_ldif = True
+
+        # Get account dn and LDIF data.
+        plugin_kwargs = {'smtpSessionData': smtp_session_map,
+                         'conn': self.conn,
+                         'baseDn': settings.ldap_basedn,
+                         'senderDn': None,
+                         'senderLdif': None,
+                         'recipientDn': None,
+                         'recipientLdif': None,
+                         }
+
+        if get_sender_ldif:
+            senderDn, senderLdif = conn_utils.get_account_ldif(
+                conn=self.conn,
+                account=smtp_session_map['sender'],
+                attrlist=sender_search_attrlist,
+            )
+            plugin_kwargs['senderDn'] = senderDn
+            plugin_kwargs['senderLdif'] = senderLdif
+
+            for plugin in plugins_for_sender:
+                action = conn_utils.apply_plugin(plugin, **plugin_kwargs)
+                if not action.startswith('DUNNO'):
+                    return action
+
+        if get_recipient_ldif:
+            recipientDn, recipientLdif = conn_utils.get_account_ldif(
+                conn=self.conn,
+                account=smtp_session_map['recipient'],
+                attrlist=recipient_search_attrlist,
+            )
+            plugin_kwargs['recipientDn'] = recipientDn
+            plugin_kwargs['recipientLdif'] = recipientLdif
+
+            for plugin in plugins_for_recipient:
+                action = conn_utils.apply_plugin(plugin, **plugin_kwargs)
+                if not action.startswith('DUNNO'):
+                    return action
+
+        for plugin in plugins_for_misc:
+            action = conn_utils.apply_plugin(plugin, **plugin_kwargs)
+            if not action.startswith('DUNNO'):
+                return action
+
+        return SMTP_ACTIONS['default']

File libs/sql/__init__.py

Empty file added.

File libs/sql/modeler.py

+# Author: Zhang Huangbin <zhb _at_ iredmail.org>
+
+import logging
+from libs import SMTP_ACTIONS
+
+
+class Modeler:
+    def __init__(self, cfg):
+        self.cfg = cfg
+
+        # Backend
+        self.backend = self.cfg.get('general', 'backend', 'mysql')
+
+        if self.backend == 'mysql':
+            import MySQLdb
+            try:
+                db = MySQLdb.connect(
+                    host=self.cfg.get('sql', 'server', 'localhost'),
+                    db=self.cfg.get('sql', 'db', 'vmail'),
+                    user=self.cfg.get('sql', 'user', 'vmail'),
+                    passwd=self.cfg.get('sql', 'password'),
+                )
+                self.cursor = db.cursor()
+            except Exception, e:
+                logging.error("Error while creating database connection: %s" % str(e))
+        elif self.backend == 'pgsql':
+            import psycopg2
+            try:
+                db = psycopg2.connect(
+                    host=self.cfg.get('sql', 'server', 'localhost'),
+                    port=self.cfg.get('sql', 'port', '5432'),
+                    database=self.cfg.get('sql', 'db', 'vmail'),
+                    user=self.cfg.get('sql', 'user', 'vmail'),
+                    password=self.cfg.get('sql', 'password'),
+                )
+                self.cursor = db.cursor()
+            except Exception, e:
+                logging.error("Error while creating database connection: %s" % str(e))
+        else:
+            return SMTP_ACTIONS['default']
+
+    def __del__(self):
+        try:
+            self.cursor.close()
+            logging.debug('Closed SQL connection.')
+        except Exception, e:
+            logging.debug('Error while closing connection: %s' % str(e))
+
+    def handle_data(self, smtp_session_map, plugins=[]):
+        if 'sender' in smtp_session_map.keys() and 'recipient' in smtp_session_map.keys():
+            if len(smtp_session_map['sender']) < 6:
+                # Not a valid email address.
+                return 'DUNNO'
+
+            # Get plugin module name and convert plugin list to python list type.
+            self.plugins = self.cfg.get('sql', 'plugins', '')
+            self.plugins = [v.strip() for v in self.plugins.split(',')]
+
+            # Get sender, recipient.
+            # Sender/recipient are used almost in all plugins, so store them
+            # a dict and pass to plugins.
+            senderReceiver = {
+                'sender': smtp_session_map['sender'],
+                'recipient': smtp_session_map['recipient'],
+                'sender_domain': smtp_session_map['sender'].split('@')[-1],
+                'recipient_domain': smtp_session_map['recipient'].split('@')[-1],
+            }
+
+            if len(self.plugins) > 0:
+                #
+                # Import plugin modules.
+                #
+                self.modules = []
+
+                # Load plugin module.
+                for plugin in self.plugins:
+                    try:
+                        self.modules.append(__import__(plugin))
+                    except ImportError:
+                        # Print error message if plugin module doesn't exist.
+                        # Use logging.info to let admin know this critical error.
+                        logging.info('Error: plugin %s.py not exist.' % plugin)
+                    except Exception, e:
+                        logging.debug('Error while importing plugin module (%s): %s' % (plugin, str(e)))
+
+                #
+                # Apply plugins.
+                #
+                self.action = ''
+                for module in self.modules:
+                    try:
+                        logging.debug('Apply plugin: %s.' % (module.__name__, ))
+                        pluginAction = module.restriction(
+                            dbConn=self.cursor,
+                            senderReceiver=senderReceiver,
+                            smtpSessionData=smtp_session_map,
+                        )
+
+                        logging.debug('Response from plugin (%s): %s' % (module.__name__, pluginAction))
+                        if not pluginAction.startswith('DUNNO'):
+                            logging.info('Response from plugin (%s): %s' % (module.__name__, pluginAction))
+                            return pluginAction
+                    except Exception, e:
+                        logging.debug('Error while apply plugin (%s): %s' % (module, str(e)))
+
+            else:
+                # No plugins available.
+                return 'DUNNO'
+        else:
+            return SMTP_ACTIONS['defer']
+

File libs/sqllib.py

-# Author: Zhang Huangbin <zhb _at_ iredmail.org>
-
-import logging
-from libs import SMTP_ACTIONS
-
-
-class SQLModeler:
-    def __init__(self, cfg):
-        self.cfg = cfg
-
-        # Backend
-        self.backend = self.cfg.get('general', 'backend', 'mysql')
-
-        if self.backend == 'mysql':
-            import MySQLdb
-            try:
-                db = MySQLdb.connect(
-                    host=self.cfg.get('sql', 'server', 'localhost'),
-                    db=self.cfg.get('sql', 'db', 'vmail'),
-                    user=self.cfg.get('sql', 'user', 'vmail'),
-                    passwd=self.cfg.get('sql', 'password'),
-                )
-                self.cursor = db.cursor()
-            except Exception, e:
-                logging.error("Error while creating database connection: %s" % str(e))
-        elif self.backend == 'pgsql':
-            import psycopg2
-            try:
-                db = psycopg2.connect(
-                    host=self.cfg.get('sql', 'server', 'localhost'),
-                    port=self.cfg.get('sql', 'port', '5432'),
-                    database=self.cfg.get('sql', 'db', 'vmail'),
-                    user=self.cfg.get('sql', 'user', 'vmail'),
-                    password=self.cfg.get('sql', 'password'),
-                )
-                self.cursor = db.cursor()
-            except Exception, e:
-                logging.error("Error while creating database connection: %s" % str(e))
-        else:
-            return SMTP_ACTIONS['default']
-
-    def __del__(self):
-        try:
-            self.cursor.close()
-            logging.debug('Closed SQL connection.')
-        except Exception, e:
-            logging.debug('Error while closing connection: %s' % str(e))
-
-    def handle_data(self, smtp_session_map, plugins=[]):
-        if 'sender' in smtp_session_map.keys() and 'recipient' in smtp_session_map.keys():
-            if len(smtp_session_map['sender']) < 6:
-                # Not a valid email address.
-                return 'DUNNO'
-
-            # Get plugin module name and convert plugin list to python list type.
-            self.plugins = self.cfg.get('sql', 'plugins', '')
-            self.plugins = [v.strip() for v in self.plugins.split(',')]
-
-            # Get sender, recipient.
-            # Sender/recipient are used almost in all plugins, so store them
-            # a dict and pass to plugins.
-            senderReceiver = {
-                'sender': smtp_session_map['sender'],
-                'recipient': smtp_session_map['recipient'],
-                'sender_domain': smtp_session_map['sender'].split('@')[-1],
-                'recipient_domain': smtp_session_map['recipient'].split('@')[-1],
-            }
-
-            if len(self.plugins) > 0:
-                #
-                # Import plugin modules.
-                #
-                self.modules = []
-
-                # Load plugin module.
-                for plugin in self.plugins:
-                    try:
-                        self.modules.append(__import__(plugin))
-                    except ImportError:
-                        # Print error message if plugin module doesn't exist.
-                        # Use logging.info to let admin know this critical error.
-                        logging.info('Error: plugin %s.py not exist.' % plugin)
-                    except Exception, e:
-                        logging.debug('Error while importing plugin module (%s): %s' % (plugin, str(e)))
-
-                #
-                # Apply plugins.
-                #
-                self.action = ''
-                for module in self.modules:
-                    try:
-                        logging.debug('Apply plugin: %s.' % (module.__name__, ))
-                        pluginAction = module.restriction(
-                            dbConn=self.cursor,
-                            senderReceiver=senderReceiver,
-                            smtpSessionData=smtp_session_map,
-                        )
-
-                        logging.debug('Response from plugin (%s): %s' % (module.__name__, pluginAction))
-                        if not pluginAction.startswith('DUNNO'):
-                            logging.info('Response from plugin (%s): %s' % (module.__name__, pluginAction))
-                            return pluginAction
-                    except Exception, e:
-                        logging.debug('Error while apply plugin (%s): %s' % (module, str(e)))
-
-            else:
-                # No plugins available.
-                return 'DUNNO'
-        else:
-            return SMTP_ACTIONS['defer']
-

File plugins/ldap_maillist_access_policy.py

 # Note: Access policy is defined in libs/__init__.py.
 
 import logging
-from libs import SMTP_ACTIONS, LDAP_ACCESS_POLICIES_OF_MAIL_LIST, ldap_conn_utils
+from libs import SMTP_ACTIONS, LDAP_ACCESS_POLICIES_OF_MAIL_LIST
+from libs.ldaplib import conn_utils
 
 REQUIRE_LOCAL_SENDER = False
 REQUIRE_LOCAL_RECIPIENT = True
             return SMTP_ACTIONS['reject']
     else:
         # Handle other access policies: membersOnly, allowedOnly, membersAndModeratorsOnly.
-        allowedSenders = ldap_conn_utils.get_allowed_senders_of_mail_list(
+        allowedSenders = conn_utils.get_allowed_senders_of_mail_list(
             conn=ldapConn,
             base_dn=ldapBaseDn,
             dn_of_mail_list=ldapRecipientDn,