Commits

Zhang Huangbin committed 8a60712

Code cleanup for SQL backends.

  • Participants
  • Parent commits 3084cc0

Comments (0)

Files changed (10)

             asynchat.async_chat.handle_close(self)
             logging.debug("Connection closed")
         else:
-            action = SMTP_ACTIONS['defer']
+            action = SMTP_ACTIONS['default']
             logging.debug("replying: " + action)
             self.push('action=' + action + '\n')
             asynchat.async_chat.handle_close(self)
             except Exception, e:
                 logging.error('Error while loading plugin (%s): %s' % (plugin, str(e)))
 
-        self.sender_search_attrlist = ['objectClass']
-        self.recipient_search_attrlist = ['objectClass']
-        for plugin in self.loaded_plugins:
-            self.sender_search_attrlist += plugin.SENDER_SEARCH_ATTRLIST
-            self.recipient_search_attrlist += plugin.RECIPIENT_SEARCH_ATTRLIST
+        self.sender_search_attrlist = []
+        self.recipient_search_attrlist = []
+        if settings.backend == 'ldap':
+            self.sender_search_attrlist = ['objectClass']
+            self.recipient_search_attrlist = ['objectClass']
+            for plugin in self.loaded_plugins:
+                self.sender_search_attrlist += plugin.SENDER_SEARCH_ATTRLIST
+                self.recipient_search_attrlist += plugin.RECIPIENT_SEARCH_ATTRLIST
 
     def handle_accept(self):
         conn, remote_addr = self.accept()
         logging.debug("Connect from %s, port %s." % remote_addr)
+
         PolicyChannel(
             conn,
             plugins=self.loaded_plugins,
     'default': 'DUNNO',
     'accept': 'OK',
     'reject': 'REJECT Not authorized',
-    'defer': 'DEFER_IF_PERMIT Service temporarily unavailable',
 }
 
-LDAP_ACCESS_POLICIES_OF_MAIL_LIST = {
-    'public': 'Unrestricted',
-    'domain': 'Only users under same domain are allowed',
-    'subdomain': 'Only users under same domain and sub domains are allowed',
-    'membersonly': 'Only members are allowed',
-    'members': 'Only members are allowed',
-    'moderatorsonly': 'Only moderators are allowed',
-    'moderators': 'Only moderators are allowed',
-    'allowedonly': 'Only moderators are allowed',
-    'membersandmoderatorsonly': 'Only members and moderators are allowed',
+MAILLIST_POLICY_PUBLIC = 'public'
+MAILLIST_POLICY_DOMAIN = 'domain'
+MAILLIST_POLICY_SUBDOMAIN = 'subdomain'
+MAILLIST_POLICY_MEMBERSONLY = 'membersonly'
+MAILLIST_POLICY_ALLOWEDONLY = 'allowedonly'      # Same as POLICY_MODERATORSONLY
+MAILLIST_POLICY_MEMBERSANDMODERATORSONLY = 'membersandmoderatorsonly'
+
+MAILLIST_ACCESS_POLICIES = {
+    MAILLIST_POLICY_PUBLIC: 'Unrestricted',
+    MAILLIST_POLICY_DOMAIN: 'Only users under same domain are allowed',
+    MAILLIST_POLICY_SUBDOMAIN: 'Only users under same domain and sub domains are allowed',
+    MAILLIST_POLICY_MEMBERSONLY: 'Only members are allowed',
+    MAILLIST_POLICY_ALLOWEDONLY: 'Only moderators/allowed are allowed',
+    MAILLIST_POLICY_MEMBERSANDMODERATORSONLY: 'Only members and moderators are allowed',
 }

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=%(account)s)(shadowAddress=%(account)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 list of allowed senders"""
+
+    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]
+
+        # 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 in ['allowedonly',
+                                            'moderatorsonly',
+                                            'moderators']:
+            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 [u.lower() for u in userList]
+    except Exception, e:
+        logging.debug('Error: %s' % str(e))
+        return []
+

libs/ldaplib/modeler.py

 import ldap
 import logging
 import settings
-from libs import SMTP_ACTIONS
-from libs.ldaplib import utils
+from libs import SMTP_ACTIONS, utils
+from libs.ldaplib import conn_utils
 
 
 class Modeler:
                     recipient_search_attrlist=[],
                    ):
         # No sender or recipient in smtp session.
-        if not 'sender' in smtp_session_data or not 'recipient' in smtp_session_data:
-            return SMTP_ACTIONS['defer']
+        if not 'sender' in smtp_session_data or \
+           not 'recipient' in smtp_session_data:
+            return SMTP_ACTIONS['default']
 
         # Not a valid email address.
         if len(smtp_session_data['sender']) < 6:
         if not plugins:
             return 'DUNNO'
 
-        # Get account dn and LDIF data.
         plugin_kwargs = {'smtp_session_data': smtp_session_data,
                          'conn': self.conn,
                          'base_dn': settings.ldap_basedn,
             # Get LDIF data of sender if required
             if plugin.REQUIRE_LOCAL_SENDER \
                and plugin_kwargs['sender_dn'] is None:
-                sender_dn, sender_ldif = utils.get_account_ldif(
+                sender_dn, sender_ldif = conn_utils.get_account_ldif(
                     conn=self.conn,
                     account=smtp_session_data['sender'],
                     attrlist=sender_search_attrlist,
             # Get LDIF data of recipient if required
             if plugin.REQUIRE_LOCAL_RECIPIENT \
                and plugin_kwargs['recipient_dn'] is None:
-                recipient_dn, recipient_ldif = utils.get_account_ldif(
+                recipient_dn, recipient_ldif = conn_utils.get_account_ldif(
                     conn=self.conn,
                     account=smtp_session_data['recipient'],
                     attrlist=recipient_search_attrlist,

libs/ldaplib/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=%(account)s)(shadowAddress=%(account)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 list of allowed senders"""
-
-    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]
-
-        # 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 in ['allowedonly',
-                                            'moderatorsonly',
-                                            'moderators']:
-            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 [u.lower() for u in 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

libs/sql/modeler.py

 # Author: Zhang Huangbin <zhb _at_ iredmail.org>
 
 import logging
-from libs import SMTP_ACTIONS
+import settings
+from libs import SMTP_ACTIONS, utils
 
 
 class Modeler:
-    def __init__(self, cfg):
-        self.cfg = cfg
-
-        # Backend
-        self.backend = self.cfg.get('general', 'backend', 'mysql')
-
-        if self.backend == 'mysql':
+    def __init__(self):
+        if settings.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'),
+                    host=settings.sql_server,
+                    port=int(settings.sql_port),
+                    db=settings.sql_db,
+                    user=settings.sql_user,
+                    passwd=settings.sql_password,
                 )
                 self.cursor = db.cursor()
             except Exception, e:
                 logging.error("Error while creating database connection: %s" % str(e))
-        elif self.backend == 'pgsql':
+        elif settings.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'),
+                    host=settings.sql_server,
+                    port=int(settings.sql_port),
+                    database=settings.sql_db,
+                    user=settings.sql_user,
+                    password=settings.sql_password,
                 )
                 self.cursor = db.cursor()
             except Exception, e:
         except Exception, e:
             logging.debug('Error while closing connection: %s' % str(e))
 
-    def handle_data(self, smtp_session_data, plugins=[]):
-        if 'sender' in smtp_session_data.keys() and 'recipient' in smtp_session_data.keys():
-            if len(smtp_session_data['sender']) < 6:
-                # Not a valid email address.
-                return 'DUNNO'
+    def handle_data(self,
+                    smtp_session_data,
+                    plugins=[],
+                    **kwargs
+                   ):
+        # No sender or recipient in smtp session.
+        if not 'sender' in smtp_session_data or \
+           not 'recipient' in smtp_session_data:
+            return SMTP_ACTIONS['default']
 
-            # 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(',')]
+        # Not a valid email address.
+        if len(smtp_session_data['sender']) < 6:
+            return 'DUNNO'
 
-            # Get sender, recipient.
-            # Sender/recipient are used almost in all plugins, so store them
-            # a dict and pass to plugins.
-            senderReceiver = {
-                'sender': smtp_session_data['sender'],
-                'recipient': smtp_session_data['recipient'],
-                'sender_domain': smtp_session_data['sender'].split('@')[-1],
-                'recipient_domain': smtp_session_data['recipient'].split('@')[-1],
-            }
+        # No plugins available.
+        if not plugins:
+            return 'DUNNO'
 
-            if len(self.plugins) > 0:
-                #
-                # Import plugin modules.
-                #
-                self.modules = []
+        plugin_kwargs = {'smtp_session_data': smtp_session_data,
+                         'conn': self.cursor,
+                         'sender': smtp_session_data['sender'],
+                         'recipient': smtp_session_data['recipient'],
+                         'sender_domain': smtp_session_data['sender'].split('@')[-1],
+                         'recipient_domain': smtp_session_data['recipient'].split('@')[-1],
+                        }
 
-                # 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)))
+        # TODO Get SQL record of mail user or mail alias before applying plugins
+        # TODO Query required sql columns instead of all
 
-                #
-                # 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,
-                            smtp_session_data=smtp_session_data,
-                        )
+        for plugin in plugins:
+            action = utils.apply_plugin(plugin, **plugin_kwargs)
+            if not action.startswith('DUNNO'):
+                return action
 
-                        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)))
+        return SMTP_ACTIONS['default']
 
-            else:
-                # No plugins available.
-                return 'DUNNO'
-        else:
-            return SMTP_ACTIONS['defer']
-
+import logging
+from libs import SMTP_ACTIONS
+
+
+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
+

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
-from libs.ldaplib import utils
+from libs import SMTP_ACTIONS, MAILLIST_ACCESS_POLICIES
+from libs.ldaplib import conn_utils
 
 REQUIRE_LOCAL_SENDER = False
 REQUIRE_LOCAL_RECIPIENT = True
     # Log access policy and description
     logging.debug('%s -> %s, access policy: %s (%s)' % (
         sender, recipient, policy,
-        LDAP_ACCESS_POLICIES_OF_MAIL_LIST.get(policy, 'no description'))
+        MAILLIST_ACCESS_POLICIES.get(policy, 'no description'))
     )
 
     if policy in ['domain', 'subdomain', ]:
                     'moderatorsonly', 'moderators',
                     'allowedonly', 'membersandmoderatorsonly']:
         # Handle other access policies: membersOnly, allowedOnly, membersAndModeratorsOnly.
-        allowedSenders = utils.get_allowed_senders_of_mail_list(
+        allowedSenders = conn_utils.get_allowed_senders_of_mail_list(
             conn=conn,
             base_dn=base_dn,
             dn_of_mail_list=recipient_dn,

plugins/sql_alias_access_policy.py

 import logging
 from web import sqlquote
 from libs import SMTP_ACTIONS
+from libs import MAILLIST_POLICY_PUBLIC
+from libs import MAILLIST_POLICY_DOMAIN
+from libs import MAILLIST_POLICY_SUBDOMAIN
+from libs import MAILLIST_POLICY_MEMBERSONLY
+from libs import MAILLIST_POLICY_ALLOWEDONLY
+from libs import MAILLIST_POLICY_MEMBERSANDMODERATORSONLY
+from libs import MAILLIST_ACCESS_POLICIES
 
-REQUIRE_LOCAL_SENDER = False
-REQUIRE_LOCAL_RECIPIENT = True
 
-# Policies. MUST be defined in lower case.
-POLICY_PUBLIC = 'public'
-POLICY_DOMAIN = 'domain'
-POLICY_SUBDOMAIN = 'subdomain'
-POLICY_MEMBERSONLY = 'membersonly'
-POLICY_MODERATORSONLY = 'moderatorsonly'
-POLICY_ALLOWEDONLY = 'allowedonly'      # Same as @POLICY_MODERATORSONLY
-POLICY_MEMBERSANDMODERATORSONLY = 'membersandmoderatorsonly'
-
-def restriction(dbConn, senderReceiver, smtp_session_data, **kargs):
+def restriction(**kwargs):
+    conn = kwargs['conn']
+    sender = kwargs['sender']
+    recipient = kwargs['recipient']
+    recipient_domain = kwargs['recipient_domain']
 
     sql = '''SELECT accesspolicy, goto, moderators
             FROM alias
                 AND domain=%s
                 AND active=1
             LIMIT 1
-    ''' % (sqlquote(senderReceiver.get('recipient')),
-           sqlquote(senderReceiver.get('recipient_domain')),
-          )
+    ''' % (sqlquote(recipient), sqlquote(recipient_domain))
     logging.debug('SQL: %s' % sql)
 
-    dbConn.execute(sql)
-    sqlRecord = dbConn.fetchone()
-    logging.debug('SQL Record: %s' % str(sqlRecord))
+    conn.execute(sql)
+    sql_record = conn.fetchone()
+    logging.debug('SQL Record: %s' % str(sql_record))
 
     # Recipient account doesn't exist.
-    if sqlRecord is None:
+    if sql_record is None:
         return 'DUNNO (Not mail alias)'
 
-    policy = str(sqlRecord[0]).lower()
+    policy = str(sql_record[0]).lower()
 
-    members = [str(v.lower()) for v in str(sqlRecord[1]).split(',')]
-    moderators = [str(v.lower()) for v in str(sqlRecord[2]).split(',')]
+    # Log access policy and description
+    logging.debug('%s -> %s, access policy: %s (%s)' % (
+        sender, recipient, policy,
+        MAILLIST_ACCESS_POLICIES.get(policy, 'no description'))
+    )
+
+    members = [str(v.lower()) for v in str(sql_record[1]).split(',')]
+    moderators = [str(v.lower()) for v in str(sql_record[2]).split(',')]
 
     logging.debug('policy: %s' % policy)
     logging.debug('members: %s' % ', '.join(members))
     if not len(policy) > 0:
         return 'DUNNO (No access policy)'
 
-    if policy == POLICY_PUBLIC:
+    if policy == MAILLIST_POLICY_PUBLIC:
         # Return if no access policy available or policy is @POLICY_PUBLIC.
         return 'DUNNO'
-    elif policy == POLICY_DOMAIN:
+    elif policy == MAILLIST_POLICY_DOMAIN:
         # Bypass all users under the same domain.
         if senderReceiver['sender_domain'] == senderReceiver['recipient_domain']:
             return 'DUNNO'
         else:
             return SMTP_ACTIONS['reject']
-    elif policy == POLICY_SUBDOMAIN:
+    elif policy == MAILLIST_POLICY_SUBDOMAIN:
         # Bypass all users under the same domain or sub domains.
         if senderReceiver['sender'].endswith(senderReceiver['recipient_domain']) or \
            senderReceiver['sender'].endswith('.' + senderReceiver['recipient_domain']):
             return 'DUNNO'
         else:
             return SMTP_ACTIONS['reject']
-    elif policy == POLICY_MEMBERSONLY:
+    elif policy == MAILLIST_POLICY_MEMBERSONLY:
         # Bypass all members.
         if senderReceiver['sender'] in members:
             return 'DUNNO'
         else:
             return SMTP_ACTIONS['reject']
-    elif policy == POLICY_MODERATORSONLY or policy == POLICY_ALLOWEDONLY:
+    elif policy == MAILLIST_POLICY_ALLOWEDONLY:
         # Bypass all moderators.
         if senderReceiver['sender'] in moderators:
             return 'DUNNO'
         else:
             return SMTP_ACTIONS['reject']
-    elif policy == POLICY_MEMBERSANDMODERATORSONLY:
+    elif policy == MAILLIST_POLICY_MEMBERSANDMODERATORSONLY:
         # Bypass both members and moderators.
         if senderReceiver['sender'] in members or senderReceiver['sender'] in moderators:
             return 'DUNNO'

plugins/sql_user_restrictions.py

 from web import sqlquote
 from libs import SMTP_ACTIONS
 
-REQUIRE_LOCAL_SENDER = False
-REQUIRE_LOCAL_RECIPIENT = False
 
-def restriction(dbConn, senderReceiver, smtp_session_data, **kargs):
+def restriction(**kwargs):
+    conn = kwargs['conn']
+    sender = kwargs['sender']
+    sender_domain = kwargs['sender_domain']
+    recipient = kwargs['recipient']
+    recipient_domain = kwargs['recipient_domain']
+
     # Get restriction rules for sender
     sql = '''
         SELECT
         FROM mailbox
         WHERE username=%s
         LIMIT 1
-    ''' % sqlquote(senderReceiver['sender'])
-    logging.debug('SQL to get restriction rules of sender (%s): %s' % (senderReceiver['sender'], sql))
+    ''' % sqlquote(sender)
+    logging.debug('SQL to get restriction rules of sender (%s): %s' % (sender, sql))
 
-    dbConn.execute(sql)
-    sql_record = dbConn.fetchone()
+    conn.execute(sql)
+    sql_record = conn.fetchone()
     logging.debug('Returned SQL Record: %s' % str(sql_record))
 
     # Sender account exists, perform recipient restrictions
             logging.debug('All allowed recipient: %s' % str(all_allowed_recipients))
 
             if all_allowed_recipients:
-                if senderReceiver['recipient'] in all_allowed_recipients \
-                   or senderReceiver['recipient_domain'] in all_allowed_recipients \
-                   or '.' + senderReceiver['recipient_domain'] in all_allowed_recipients \
+                if recipient in all_allowed_recipients \
+                   or recipient_domain in all_allowed_recipients \
+                   or '.' + recipient_domain in all_allowed_recipients \
                    or '*' in all_allowed_recipients:
                     return SMTP_ACTIONS['accept']
 
             logging.debug('All rejected recipient: %s' % str(all_rejected_recipients))
 
             if all_rejected_recipients:
-                if senderReceiver['recipient'] in all_rejected_recipients \
-                   or senderReceiver['recipient_domain'] in all_rejected_recipients \
-                   or '.' + senderReceiver['recipient_domain'] in all_rejected_recipients \
+                if recipient in all_rejected_recipients \
+                   or recipient_domain in all_rejected_recipients \
+                   or '.' + recipient_domain in all_rejected_recipients \
                    or '*' in all_rejected_recipients:
                     return SMTP_ACTIONS['reject']
 
     # Get restriction rules for recipient
     # Don't perform another SQL query if sender == recipient
-    if senderReceiver['sender'] != senderReceiver['recipient']:
+    if sender != recipient:
         sql = '''
             SELECT
                 allowedrecipients, rejectedrecipients,
             FROM mailbox
             WHERE username=%s
             LIMIT 1
-        ''' % sqlquote(senderReceiver['recipient'])
-        logging.debug('SQL to get restriction rules of recipient (%s): %s' % (senderReceiver['recipient'], sql))
+        ''' % sqlquote(recipient)
+        logging.debug('SQL to get restriction rules of recipient (%s): %s' % (recipient, sql))
 
-        dbConn.execute(sql)
-        sql_record = dbConn.fetchone()
+        conn.execute(sql)
+        sql_record = conn.fetchone()
         logging.debug('Returned SQL Record: %s' % str(sql_record))
 
     # Recipient account exists, perform sender restrictions
             logging.debug('All allowed senders: %s' % str(all_allowed_senders))
 
             if all_allowed_senders:
-                if senderReceiver['sender'] in all_allowed_senders \
-                   or senderReceiver['sender_domain'] in all_allowed_senders \
-                   or '.' + senderReceiver['sender_domain'] in all_allowed_senders \
+                if sender in all_allowed_senders \
+                   or sender_domain in all_allowed_senders \
+                   or '.' + sender_domain in all_allowed_senders \
                    or '.*' in all_allowed_senders:
                     return SMTP_ACTIONS['accept']
 
             logging.debug('All rejected senders: %s' % str(all_rejected_senders))
 
             if all_rejected_senders:
-                if senderReceiver['sender'] in all_rejected_senders \
-                   or senderReceiver['sender_domain'] in all_rejected_senders \
-                   or '.' + senderReceiver['sender_domain'] in all_rejected_senders \
+                if sender in all_rejected_senders \
+                   or sender_domain in all_rejected_senders \
+                   or '.' + sender_domain in all_rejected_senders \
                    or '*' in all_rejected_senders:
                     return SMTP_ACTIONS['reject']