Commits

Zhang Huangbin committed c39c38a

* Use python file as setting file.
* Code cleanup.

  • Participants
  • Parent commits e85694f

Comments (0)

Files changed (11)

iredapd.ini.sample

-[general]
-# Listen address and port.
-listen_addr     = 127.0.0.1
-listen_port     = 7777
-
-# Run as a low privileged user.
-# If you don't want to create one, you can try 'nobody'.
-run_as_user     = iredapd
-
-# Background/daemon mode: yes, no.
-# Run iRedAPD as daemon, detach iredapd from terminal.
-run_as_daemon   = yes
-
-# Path to pid file.
-pid_file        = /var/run/iredapd.pid
-
-# Log type: file.
-# Set 'log_file = /dev/null' if you don't want to keep the log.
-log_type        = file
-log_file        = /var/log/iredapd.log
-
-# Log level: info, error, debug.
-log_level       = error
-
-# Backend: ldap, mysql, pgsql.
-backend = ldap
-
-[ldap]
-# For ldap backend only.
-# LDAP server setting.
-# Uri must starts with ldap:// or ldaps:// (TLS/SSL).
-#
-# Tip: You can get binddn, bindpw from /etc/postfix/ldap_*.cf.
-#
-uri         = ldap://127.0.0.1:389
-binddn      = cn=vmail,dc=iredmail,dc=org
-bindpw      = mRAEWpGRtlCs1O0QuWpXoaJ36EjRql
-basedn      = o=domains,dc=iredmail,dc=org
-
-# Enabled plugins.
-#   - Plugin name is file name which placed under 'src/plugins/' directory.
-#   - Plugin names MUST be seperated by comma.
-#
-# Available plugins:
-#   * ldap_domain_wblist: per-domain white/blacklist support.
-#       Note: If you want to enable this plugin, it's better to make it the
-#             first one in enabled plugin list.
-#   * ldap_maillist_access_policy: mail list deliver restrictions.
-#   * block_amavisd_blacklisted_senders: per-user white/blacklist support.
-plugins = ldap_maillist_access_policy, block_amavisd_blacklisted_senders
-
-[sql]
-# For MySQL and PostgreSQL backends
-server      = 127.0.0.1
-port        = 3306
-db          = vmail
-user        = vmail
-password    = Psaf68wsuVctYSbj4PJzRqmFsE0rlQ
-
-# Enabled plugins.
-#   - Plugin name is file name which placed under 'src/plugins/' directory,
-#     starts with 'sql_'.
-#   - Plugin names MUST be seperated by comma.
-plugins = sql_alias_access_policy
 import os.path
 import sys
 import pwd
-import ConfigParser
 import socket
 import asyncore
 import asynchat
 import logging
 
+import settings
+
 # Append plugin directory.
 sys.path.append(os.path.abspath(os.path.dirname(__file__)) + '/plugins')
 
-# Get config file.
-if len(sys.argv) != 2:
-    sys.exit('Usage: %s /path/to/iredapd.ini')
-else:
-    config_file = sys.argv[1]
-
-    # Check file exists.
-    if not os.path.exists(config_file):
-        sys.exit('File not exist: %s.' % config_file)
-
-# Read configurations.
-cfg = ConfigParser.SafeConfigParser()
-cfg.read(config_file)
-backend = cfg.get('general', 'backend', 'ldap')
-
-if backend == 'ldap':
+if settings.backend == 'ldap':
     from libs.ldaplib import LDAPModeler as Modeler
-    plugins = cfg.get('ldap', 'plugins', '')
-elif backend in ['mysql', 'pgsql']:
+elif settings.backend in ['mysql', 'pgsql']:
     from libs.sqllib import SQLModeler as Modeler
-    plugins = cfg.get('sql', 'plugins', '')
 else:
     sys.exit('Invalid backend, it must be ldap, mysql or pgsql.')
 
 from libs import __version__, SMTP_ACTIONS, daemon
 
 
-class apd_channel(asynchat.async_chat):
+class PolicyChannel(asynchat.async_chat):
     def __init__(self, conn, remote_addr):
         asynchat.async_chat.__init__(self, conn)
         self.remote_addr = remote_addr
                 self.smtp_attrs[key] = value
         elif len(self.smtp_attrs) != 0:
             try:
-                modeler = Modeler(cfg=cfg, logger=logging)
+                modeler = Modeler()
 
                 result = modeler.handle_data(self.smtp_attrs)
                 if result:
             logging.debug("Connection closed")
 
 
-class apd_socket(asyncore.dispatcher):
+class DaemonSocket(asyncore.dispatcher):
     def __init__(self, localaddr):
         asyncore.dispatcher.__init__(self)
         self.create_socket(socket.AF_INET, socket.SOCK_STREAM)
         self.bind(localaddr)
         self.listen(5)
         ip, port = localaddr
-        logging.info("Starting iRedAPD (version %s, %s backend), listening on %s:%d." % (__version__, backend, ip, port))
-        logging.info("Enabled plugin(s): %s." % (plugins))
+        logging.info("Starting iRedAPD (version %s, %s backend), listening on %s:%d." % (__version__, settings.backend, ip, port))
+        logging.info("Enabled plugin(s): %s." % (', '.join(settings.plugins)))
 
     def handle_accept(self):
         conn, remote_addr = self.accept()
-        channel = apd_channel(conn, remote_addr)
+        channel = PolicyChannel(conn, remote_addr)
 
 
 def main():
     # Set umask.
     os.umask(0077)
 
-    # Get listen address/port.
-    listen_addr = cfg.get('general', 'listen_addr', '127.0.0.1')
-    listen_port = int(cfg.get('general', 'listen_port', '7777'))
-
-    run_as_daemon = cfg.get('general', 'run_as_daemon', 'yes')
-
     # Get log level.
-    log_level = getattr(logging, cfg.get('general', 'log_level', 'info').upper())
+    log_level = getattr(logging, str(settings.log_level).upper())
 
     # Initialize file based logger.
-    if cfg.get('general', 'log_type', 'file') == 'file':
-        if run_as_daemon == 'yes':
+    if settings.log_type == 'file':
+        if settings.run_as_daemon:
             logging.basicConfig(
-                    level=log_level,
-                    format='%(asctime)s %(levelname)s %(message)s',
-                    datefmt='%Y-%m-%d %H:%M:%S',
-                    filename=cfg.get('general', 'log_file', '/var/log/iredapd.log'),
-                    )
+                level=log_level,
+                format='%(asctime)s %(levelname)s %(message)s',
+                datefmt='%Y-%m-%d %H:%M:%S',
+                filename=settings.log_file,
+            )
         else:
             logging.basicConfig(
-                    level=log_level,
-                    format='%(asctime)s %(levelname)s %(message)s',
-                    datefmt='%Y-%m-%d %H:%M:%S',
-                    )
+                level=log_level,
+                format='%(asctime)s %(levelname)s %(message)s',
+                datefmt='%Y-%m-%d %H:%M:%S',
+            )
 
     # Initialize policy daemon.
-    socket_daemon = apd_socket((listen_addr, listen_port))
+    socket_daemon = DaemonSocket((settings.listen_address, settings.listen_port))
 
     # Run this program as daemon.
-    if run_as_daemon == 'yes':
+    if settings.run_as_daemon:
         daemon.daemonize()
 
     # Run as a low privileged user.
-    run_as_user = cfg.get('general', 'run_as_user', 'nobody')
-    uid = pwd.getpwnam(run_as_user)[2]
+    uid = pwd.getpwnam(settings.run_as_user)[2]
 
     try:
         # Write pid number into pid file.
-        f = open(cfg.get('general', 'pid_file', '/var/run/iredapd.pid'), 'w')
+        f = open(settings.pid_file, 'w')
         f.write(str(os.getpid()))
         f.close()
 
 
 import sys
 import ldap
+import logging
+import settings
 from libs import SMTP_ACTIONS
 
 
 class LDAPModeler:
-    def __init__(self, cfg, logger):
-        self.cfg = cfg
-        self.logger = logger
-
-        # Read LDAP server related settings.
-        self.uri = self.cfg.get('ldap', 'uri', 'ldap://127.0.0.1:389')
-        self.binddn = self.cfg.get('ldap', 'binddn')
-        self.bindpw = self.cfg.get('ldap', 'bindpw')
-        self.baseDN = self.cfg.get('ldap', 'basedn')
-
+    def __init__(self):
         # Initialize ldap connection.
         try:
-            self.conn = ldap.initialize(self.uri)
-            self.logger.debug('LDAP connection initialied success.')
+            self.conn = ldap.initialize(settings.ldap_uri)
+            logging.debug('LDAP connection initialied success.')
         except Exception, e:
-            self.logger.error('LDAP initialized failed: %s.' % str(e))
+            logging.error('LDAP initialized failed: %s.' % str(e))
             sys.exit()
 
         # Bind to ldap server.
         try:
-            self.conn.bind_s(self.binddn, self.bindpw)
-            self.logger.debug('LDAP bind success.')
+            self.conn.bind_s(settings.ldap_binddn, settings.ldap_bindpw)
+            logging.debug('LDAP bind success.')
         except ldap.INVALID_CREDENTIALS:
-            self.logger.error('LDAP bind failed: incorrect bind dn or password.')
+            logging.error('LDAP bind failed: incorrect bind dn or password.')
             sys.exit()
         except Exception, e:
-            self.logger.error('LDAP bind failed: %s.' % str(e))
+            logging.error('LDAP bind failed: %s.' % str(e))
             sys.exit()
 
     def __del__(self):
         try:
             self.conn.unbind_s()
-            self.logger.debug('Close LDAP connection.')
+            logging.debug('Close LDAP connection.')
         except Exception, e:
-            self.logger.debug('Error while closing connection: %s' % str(e))
+            logging.debug('Error while closing connection: %s' % str(e))
 
     def __get_recipient_dn_ldif(self, recipient):
-        self.logger.debug('__get_recipient_dn_ldif (recipient): %s' % recipient)
+        logging.debug('__get_recipient_dn_ldif (recipient): %s' % recipient)
         try:
             filter = '(&(|(mail=%s)(shadowAddress=%s))(|(objectClass=mailUser)(objectClass=mailList)(objectClass=mailAlias)))' % (recipient, recipient)
-            self.logger.debug('__get_recipient_dn_ldif (ldap query filter): %s' % filter)
+            logging.debug('__get_recipient_dn_ldif (ldap query filter): %s' % filter)
 
-            result = self.conn.search_s(self.baseDN, ldap.SCOPE_SUBTREE, filter)
+            result = self.conn.search_s(settings.ldap_basedn, ldap.SCOPE_SUBTREE, filter)
 
             if len(result) == 1:
-                self.logger.debug('__get_recipient_dn_ldif (ldap query result): %s' % str(result))
+                logging.debug('__get_recipient_dn_ldif (ldap query result): %s' % str(result))
                 dn, entry = result[0]
                 return (dn, entry)
             else:
-                self.logger.debug('__get_recipient_dn_ldif: Can not find recipient in LDAP server.')
+                logging.debug('__get_recipient_dn_ldif: Can not find recipient in LDAP server.')
                 return (None, None)
         except Exception, e:
-            self.logger.debug('!!! ERROR !!! __get_recipient_dn_ldif (result): %s' % str(e))
+            logging.debug('!!! ERROR !!! __get_recipient_dn_ldif (result): %s' % str(e))
             return (None, None)
 
     def __get_access_policy(self, recipient):
 
         return (dn_of_mail_list, value_of_access_policy,)"""
 
-        self.logger.debug('__get_access_policy (list): %s' % recipient)
+        logging.debug('__get_access_policy (list): %s' % recipient)
 
         # Replace 'recipient' placehold in config file with mail list address.
         try:
             self.cfg.set('ldap', "recipient", recipient)
         except Exception, e:
-            self.logger.error("""Error while replacing 'recipient': %s""" % (str(e)))
+            logging.error("""Error while replacing 'recipient': %s""" % (str(e)))
 
         # Search mail list object.
-        searchBasedn = 'mail=%s,ou=Groups,domainName=%s,%s' % (recipient, recipient.split('@')[1], self.baseDN)
+        searchBasedn = 'mail=%s,ou=Groups,domainName=%s,%s' % (recipient, recipient.split('@')[1], settings.ldap_basedn)
         searchScope = ldap.SCOPE_BASE
         searchFilter = self.cfg.get('ldap', 'filter_maillist')
         searchAttr = self.cfg.get('ldap', 'attr_access_policy', 'accessPolicy')
 
-        self.logger.debug('__get_access_policy (searchBasedn): %s' % searchBasedn)
-        self.logger.debug('__get_access_policy (searchScope): %s' % searchScope)
-        self.logger.debug('__get_access_policy (searchFilter): %s' % searchFilter)
-        self.logger.debug('__get_access_policy (searchAttr): %s' % searchAttr)
+        logging.debug('__get_access_policy (searchBasedn): %s' % searchBasedn)
+        logging.debug('__get_access_policy (searchScope): %s' % searchScope)
+        logging.debug('__get_access_policy (searchFilter): %s' % searchFilter)
+        logging.debug('__get_access_policy (searchAttr): %s' % searchAttr)
 
         try:
             result = self.conn.search_s(searchBasedn, searchScope, searchFilter, [searchAttr])
-            self.logger.debug('__get_access_policy (search result): %s' % str(result))
+            logging.debug('__get_access_policy (search result): %s' % str(result))
         except ldap.NO_SUCH_OBJECT:
-            self.logger.debug('__get_access_policy (not a mail list: %s) Returned (None)' % recipient)
+            logging.debug('__get_access_policy (not a mail list: %s) Returned (None)' % recipient)
             return (None, None)
         except Exception, e:
-            self.logger.debug('__get_access_policy (ERROR while searching list): %s' % str(e))
+            logging.debug('__get_access_policy (ERROR while searching list): %s' % str(e))
             return (None, None)
 
         if len(result) != 1:
             listpolicy = result[0][1][searchAttr][0]
             returnVal = (listdn, listpolicy)
 
-            self.logger.debug('__get_access_policy (returned): %s' % str(returnVal))
+            logging.debug('__get_access_policy (returned): %s' % str(returnVal))
             return returnVal
 
     def __get_allowed_senders(self, listdn, recipient, listpolicy, sender=''):
         """return search_result_list_based_on_access_policy"""
-        self.logger.debug('__get_allowed_senders (listpolicy): %s' % listpolicy)
+        logging.debug('__get_allowed_senders (listpolicy): %s' % listpolicy)
 
         # Replace 'recipient' and 'sender' with email addresses.
-        self.cfg.set("ldap", "recipient", recipient)
-        self.cfg.set("ldap", "sender", sender)
+        #self.cfg.set("ldap", "recipient", recipient)
+        #self.cfg.set("ldap", "sender", sender)
 
         # Set search base dn, scope, filter and attribute list based on access policy.
         if listpolicy == 'membersOnly':
-            baseDN = self.baseDN
+            baseDN = settings.ldap_basedn
             searchScope = ldap.SCOPE_SUBTREE
             # Filter used to get mail list members.
-            searchFilter = self.cfg.get("ldap", "filter_member")
-            searchAttr = self.cfg.get("ldap", "attr_member")
+            #searchFilter = self.cfg.get("ldap", "filter_member")
+            #searchAttr = self.cfg.get("ldap", "attr_member")
         else:
             baseDN = listdn
             # Use SCOPE_BASE to improve performance.
             searchScope = ldap.SCOPE_BASE
             # Filter used to get mail list moderators.
-            searchFilter = self.cfg.get("ldap", "filter_allowed_senders")
-            searchAttr = self.cfg.get("ldap", "attr_moderator")
+            #searchFilter = self.cfg.get("ldap", "filter_allowed_senders")
+            #searchAttr = self.cfg.get("ldap", "attr_moderator")
 
-        self.logger.debug('__get_allowed_senders (baseDN): %s' % baseDN)
-        self.logger.debug('__get_allowed_senders (searchScope): %s' % searchScope)
-        self.logger.debug('__get_allowed_senders (searchFilter): %s' % searchFilter)
-        self.logger.debug('__get_allowed_senders (searchAttr): %s' % searchAttr)
+        logging.debug('__get_allowed_senders (baseDN): %s' % baseDN)
+        logging.debug('__get_allowed_senders (searchScope): %s' % searchScope)
+        logging.debug('__get_allowed_senders (searchFilter): %s' % searchFilter)
+        logging.debug('__get_allowed_senders (searchAttr): %s' % searchAttr)
 
         try:
             result = self.conn.search_s(baseDN, searchScope, searchFilter, [searchAttr])
-            self.logger.debug('__get_allowed_senders (search result): %s' % str(result))
+            logging.debug('__get_allowed_senders (search result): %s' % str(result))
         except ldap.NO_SUCH_OBJECT:
-            self.logger.debug('__get_allowed_senders (not a mail list: %s) Returned (None)' % recipient)
+            logging.debug('__get_allowed_senders (not a mail list: %s) Returned (None)' % recipient)
             return None
         except Exception, e:
-            self.logger.debug('__get_allowed_senders (ERROR while searching list): %s' % str(e))
+            logging.debug('__get_allowed_senders (ERROR while searching list): %s' % str(e))
             return None
 
         if len(result) != 1:
                 # Not a valid email address.
                 return 'DUNNO'
 
-            # Get plugin module name and convert plugin list to python list type.
-            self.plugins = self.cfg.get('ldap', 'plugins', '')
-            self.plugins = [v.strip() for v in self.plugins.split(',')]
-
-            if self.plugins:
-
+            if settings.plugins:
                 # Get account dn and LDIF data.
                 recipientDn, recipientLdif = self.__get_recipient_dn_ldif(map['recipient'])
 
                 # Return if recipient account doesn't exist.
                 if recipientDn is None or recipientLdif is None:
-                    self.logger.debug('Recipient DN or LDIF is None.')
+                    logging.debug('Recipient DN or LDIF is None.')
                     return SMTP_ACTIONS['default']
 
                 #
                 self.modules = []
 
                 # Load plugin module.
-                for plugin in self.plugins:
+                for plugin in settings.plugins:
                     try:
                         self.modules.append(__import__(plugin))
                     except ImportError:
                         # Print error message if plugin module doesn't exist.
-                        # Use self.logger.info to let admin know this critical error.
-                        self.logger.info('Error: plugin %s.py not exist.' % plugin)
+                        # Use logging.info to let admin know this critical error.
+                        logging.info('Error: plugin %s.py not exist.' % plugin)
                     except Exception, e:
-                        self.logger.debug('Error while importing plugin module (%s): %s' % (plugin, str(e)))
+                        logging.debug('Error while importing plugin module (%s): %s' % (plugin, str(e)))
 
                 #
                 # Apply plugins.
                 self.action = ''
                 for module in self.modules:
                     try:
-                        self.logger.debug('Apply plugin (%s).' % (module.__name__, ))
+                        logging.debug('Apply plugin: %s.' % (module.__name__, ))
                         pluginAction = module.restriction(
                             ldapConn=self.conn,
-                            ldapBaseDn=self.baseDN,
+                            ldapBaseDn=settings.ldap_basedn,
                             ldapRecipientDn=recipientDn,
                             ldapRecipientLdif=recipientLdif,
                             smtpSessionData=map,
-                            logger=self.logger,
+                            logger=logging,
                         )
 
-                        self.logger.debug('Response from plugin (%s): %s' % (module.__name__, pluginAction))
+                        logging.debug('Response from plugin (%s): %s' % (module.__name__, pluginAction))
                         if not pluginAction.startswith('DUNNO'):
-                            self.logger.info('Response from plugin (%s): %s' % (module.__name__, pluginAction))
+                            logging.info('Response from plugin (%s): %s' % (module.__name__, pluginAction))
                             return pluginAction
                     except Exception, e:
-                        self.logger.debug('Error while apply plugin (%s): %s' % (module, str(e)))
+                        logging.debug('Error while apply plugin (%s): %s' % (module, str(e)))
 
             else:
                 # No plugins available.
 # Author: Zhang Huangbin <zhb _at_ iredmail.org>
 
+import logging
 from libs import SMTP_ACTIONS
 
 
 class SQLModeler:
-    def __init__(self, cfg, logger):
+    def __init__(self, cfg):
         self.cfg = cfg
-        self.logger = logger
 
         # Backend
         self.backend = self.cfg.get('general', 'backend', 'mysql')
                 )
                 self.cursor = db.cursor()
             except Exception, e:
-                self.logger.error("Error while creating database connection: %s" % str(e))
+                logging.error("Error while creating database connection: %s" % str(e))
         elif self.backend == 'pgsql':
             import psycopg2
             try:
                 )
                 self.cursor = db.cursor()
             except Exception, e:
-                self.logger.error("Error while creating database connection: %s" % str(e))
+                logging.error("Error while creating database connection: %s" % str(e))
         else:
             return SMTP_ACTIONS['default']
 
     def __del__(self):
         try:
             self.cursor.close()
-            self.logger.debug('Closed SQL connection.')
+            logging.debug('Closed SQL connection.')
         except Exception, e:
-            self.logger.debug('Error while closing connection: %s' % str(e))
+            logging.debug('Error while closing connection: %s' % str(e))
 
     def handle_data(self, map):
         if 'sender' in map.keys() and 'recipient' in map.keys():
                         self.modules.append(__import__(plugin))
                     except ImportError:
                         # Print error message if plugin module doesn't exist.
-                        # Use self.logger.info to let admin know this critical error.
-                        self.logger.info('Error: plugin %s.py not exist.' % plugin)
+                        # Use logging.info to let admin know this critical error.
+                        logging.info('Error: plugin %s.py not exist.' % plugin)
                     except Exception, e:
-                        self.logger.debug('Error while importing plugin module (%s): %s' % (plugin, str(e)))
+                        logging.debug('Error while importing plugin module (%s): %s' % (plugin, str(e)))
 
                 #
                 # Apply plugins.
                 self.action = ''
                 for module in self.modules:
                     try:
-                        self.logger.debug('Apply plugin (%s).' % (module.__name__, ))
+                        logging.debug('Apply plugin: %s.' % (module.__name__, ))
                         pluginAction = module.restriction(
                             dbConn=self.cursor,
                             senderReceiver=senderReceiver,
                             smtpSessionData=map,
-                            logger=self.logger,
+                            logger=logging,
                         )
 
-                        self.logger.debug('Response from plugin (%s): %s' % (module.__name__, pluginAction))
+                        logging.debug('Response from plugin (%s): %s' % (module.__name__, pluginAction))
                         if not pluginAction.startswith('DUNNO'):
-                            self.logger.info('Response from plugin (%s): %s' % (module.__name__, pluginAction))
+                            logging.info('Response from plugin (%s): %s' % (module.__name__, pluginAction))
                             return pluginAction
                     except Exception, e:
-                        self.logger.debug('Error while apply plugin (%s): %s' % (module, str(e)))
+                        logging.debug('Error while apply plugin (%s): %s' % (module, str(e)))
 
             else:
                 # No plugins available.

rc_scripts/iredapd.debian

 
 PROG='iredapd'
 BINPATH='/opt/iredapd/iredapd.py'
-CONFIG='/opt/iredapd/etc/iredapd.ini'
+CONFIG='/opt/iredapd/etc/settings.ini'
 PIDFILE='/var/run/iredapd.pid'
 
 check_status() {

rc_scripts/iredapd.freebsd

 rcvar=`set_rcvar`
 
 BINPATH='/opt/iredapd/iredapd.py'
-CONFIG='/opt/iredapd/etc/iredapd.ini'
+CONFIG='/opt/iredapd/etc/settings.ini'
 pidfile='/var/run/iredapd.pid'
 
 check_status() {

rc_scripts/iredapd.gentoo

 prog='/opt/iredapd/iredapd.py'
 progname="iRedAPD"
 
-CONFIG='/opt/iredapd/etc/iredapd.ini'
+CONFIG='/opt/iredapd/etc/settings.ini'
 PIDFILE='/var/run/iredapd.pid'
 
 depend() {

rc_scripts/iredapd.openbsd

 #!/bin/sh
 
-daemon='python /opt/iredapd/iredapd.py /opt/iredapd/etc/iredapd.ini'
+daemon='python /opt/iredapd/iredapd.py /opt/iredapd/etc/settings.ini'
 
 . /etc/rc.d/rc.subr
 

rc_scripts/iredapd.opensuse

 
 PROG='iredapd'
 BINPATH='/opt/iredapd/iredapd.py'
-CONFIG='/opt/iredapd/etc/iredapd.ini'
+CONFIG='/opt/iredapd/etc/settings.ini'
 PIDFILE='/var/run/iredapd.pid'
 
 check_status() {

rc_scripts/iredapd.rhel

 
 PROG='iredapd'
 BINPATH='/opt/iredapd/iredapd.py'
-CONFIG='/opt/iredapd/etc/iredapd.ini'
+CONFIG='/opt/iredapd/etc/settings.ini'
 PIDFILE='/var/run/iredapd.pid'
 
 check_status() {

settings.py.sample

+# Listen address and port.
+listen_address = '127.0.0.1'
+listen_port = 7777
+
+# Run as a low privileged user.
+# If you don't want to create one, you can try 'nobody'.
+run_as_user = 'iredapd'
+
+# Background/daemon mode: True, False.
+# Run iRedAPD as daemon, detach iredapd from terminal.
+run_as_daemon = True
+
+# Path to pid file.
+pid_file = '/var/run/iredapd.pid'
+
+# Log type: file.
+# Set 'log_file = /dev/null' if you don't want to keep the log.
+log_type = 'file'
+log_file = '/var/log/iredapd.log'
+
+# Log level: info, error, debug.
+log_level = 'error'
+
+# Backend: ldap, mysql, pgsql.
+backend = 'ldap'
+
+# Enabled plugins.
+#   - Plugin name is file name which placed under 'plugins/' directory.
+#   - Plugin names MUST be seperated by comma.
+plugins = ['ldap_maillist_access_policy', 'block_amavisd_blacklisted_senders']
+
+#
+# For ldap backend.
+#
+# LDAP server setting.
+# Uri must starts with ldap:// or ldaps:// (TLS/SSL).
+#
+# Tip: You can get binddn, bindpw from /etc/postfix/ldap_*.cf.
+#
+ldap_uri    = 'ldap://127.0.0.1:389'
+ldap_basedn = 'o=domains,dc=iredmail,dc=org'
+ldap_binddn = 'cn=vmail,dc=iredmail,dc=org'
+ldap_bindpw = 'mRAEWpGRtlCs1O0QuWpXoaJ36EjRql'
+
+#
+# For MySQL and PostgreSQL backends.
+#
+sql_server      = '127.0.0.1'
+sql_port        = '3306'
+sql_db          = 'vmail'
+sql_user        = 'vmail'
+sql_password    = 'Psaf68wsuVctYSbj4PJzRqmFsE0rlQ'