Zhang Huangbin avatar Zhang Huangbin committed 7c26194

Clone from Google Code.

Comments (0)

Files changed (100)

extra/clear_iredmail.sh

+#!/usr/bin/env bash
+
+# Author:   Zhang Huangbin (michaelbibby <at> gmail.com)
+# Purpose:  Remove main components which installed by iRedMail, so that
+#           you can re-install iRedMail.
+# Project:  iRedMail (http://www.iredmail.org/)
+
+# ------------ USAGE --------
+# Execute this file in the current directory.
+#
+#   # bash clear_iredmail.sh
+#
+
+export CONF_DIR='../conf'
+
+# For Ubuntu & Debian.
+export DEBIAN_FRONTEND='noninteractive'
+
+# Source functions.
+. ${CONF_DIR}/global
+. ${CONF_DIR}/functions
+. ${CONF_DIR}/core
+
+# Source configurations.
+. ${CONF_DIR}/apache_php
+. ${CONF_DIR}/openldap
+. ${CONF_DIR}/phpldapadmin
+. ${CONF_DIR}/mysql
+. ${CONF_DIR}/postfix
+. ${CONF_DIR}/policyd
+. ${CONF_DIR}/pypolicyd-spf
+. ${CONF_DIR}/dovecot
+. ${CONF_DIR}/managesieve
+. ${CONF_DIR}/procmail
+. ${CONF_DIR}/amavisd
+. ${CONF_DIR}/clamav
+. ${CONF_DIR}/spamassassin
+[ -f ${CONF_DIR}/squirrelmail ] && . ${CONF/squirrelmail
+. ${CONF_DIR}/roundcube
+. ${CONF_DIR}/postfixadmin
+. ${CONF_DIR}/phpmyadmin
+. ${CONF_DIR}/awstats
+. ${CONF_DIR}/iredadmin
+
+# Source user configurations of iRedMail.
+. ../config
+
+confirm_to_remove_account()
+{
+    # Usage: confirm_to_remove_account user USERNAME
+    #        confirm_to_remove_account group GROUPNAME
+    TYPE="${1}"
+    NAME="${2}"
+
+    if [ X"${TYPE}" == X"user" ]; then
+        id -u ${NAME} >/dev/null 2>&1
+        RETVAL="$?"
+        remove_cmd="userdel -r"
+    elif [ X"${TYPE}" == X"group" ]; then
+        id -g ${NAME} >/dev/null 2>&1
+        RETVAL="$?"
+        remove_cmd="groupdel"
+    fi
+
+    if [ X"${RETVAL}" == X"0" ]; then
+        ECHO_INFO -n "Remove ${TYPE} ${NAME}. [Y|n]"
+
+        read ANSWER
+        case $ANSWER in
+            N|n ) : ;;
+            Y|y|* )
+                ECHO_INFO -n "Removing ${TYPE} ${NAME} ..."
+                ${remove_cmd} ${NAME}
+                echo -e "\t[ DONE ]\n--"
+                ;;
+        esac
+    else
+        # Account not exist.
+        :
+    fi
+}
+
+remove_pkg()
+{
+    ECHO_INFO "Removing package(s): $@"
+    if [ X"${DISTRO}" == X"RHEL" ]; then
+        yum remove $@
+    elif [ X"${DISTRO}" == X"DEBIAN" -o X"${DISTRO}" == X"UBUNTU" ]; then
+        dpkg -P postfix-policyd mailx bsd-mailx
+        dpkg -P $@
+    fi
+}
+
+# ---- Below is code snippet of functions/packages.sh ----
+# Get all packages.
+get_all_pkgs()
+{
+    export ALL_PKGS=''
+    export ENABLED_SERVICES=''
+
+    # Apache and PHP.
+    if [ X"${USE_EXIST_AMP}" != X"YES" ]; then
+        # Apache & PHP.
+        if [ X"${DISTRO}" == X"RHEL" ]; then
+            ALL_PKGS="${ALL_PKGS} httpd.${ARCH} mod_ssl.${ARCH} php.${ARCH} php-common.${ARCH} php-imap.${ARCH} php-gd.${ARCH} php-mbstring.${ARCH} libmcrypt.${ARCH} php-mcrypt.${ARCH} php-pear.noarch php-xml.${ARCH} php-pecl-fileinfo.${ARCH} php-mysql.${ARCH} php-ldap.${ARCH}"
+            ENABLED_SERVICES="${ENABLED_SERVICES} httpd"
+
+        elif [ X"${DISTRO}" == X"DEBIAN" -o X"${DISTRO}" == X"UBUNTU" ]; then
+            ALL_PKGS="${ALL_PKGS} apache2 apache2-mpm-prefork apache2.2-common libapache2-mod-php5 libapache2-mod-auth-mysql apache2-utils libaprutil1 php5-common php5-cli php5-imap php5-gd php5-mcrypt php5-mysql php5-ldap php-pear"
+            ENABLED_SERVICES="${ENABLED_SERVICES} apache2"
+        else
+            :
+        fi
+    else
+        :
+    fi
+
+    # Postfix.
+    if [ X"${DISTRO}" == X"RHEL" ]; then
+        ALL_PKGS="${ALL_PKGS} postfix.${ARCH}"
+    elif [ X"${DISTRO}" == X"DEBIAN" -o X"${DISTRO}" == X"UBUNTU" ]; then
+        ALL_PKGS="${ALL_PKGS} postfix postfix-pcre"
+    else
+        :
+    fi
+
+    ENABLED_SERVICES="${ENABLED_SERVICES} postfix"
+
+    # Awstats.
+    if [ X"${USE_AWSTATS}" == X"YES" ]; then
+        if [ X"${DISTRO}" == X"RHEL" ]; then
+            ALL_PKGS="${ALL_PKGS} awstats.noarch"
+        elif [ X"${DISTRO}" == X"DEBIAN" -o X"${DISTRO}" == X"UBUNTU" ]; then
+            ALL_PKGS="${ALL_PKGS} awstats"
+        else
+            :
+        fi
+    else
+        :
+    fi
+
+    # Note: mysql server is required, used to store extra data,
+    #       such as policyd, roundcube webmail data.
+    if [ X"${DISTRO}" == X"RHEL" ]; then
+        ALL_PKGS="${ALL_PKGS} mysql-server.${ARCH} mysql.${ARCH}"
+        ENABLED_SERVICES="${ENABLED_SERVICES} mysqld"
+    elif [ X"${DISTRO}" == X"DEBIAN" -o X"${DISTRO}" == X"UBUNTU" ]; then
+        [ X"${DISTRO_CODENAME}" == X"jaunty" ] && ALL_PKGS="${ALL_PKGS} mysql-server-core-5.0"
+        ALL_PKGS="${ALL_PKGS} libdbd-mysql-perl libmysqlclient15off libmysqlclient15-dev mysql-common mysql-server-5.0 mysql-client mysql-client-5.0"
+        ENABLED_SERVICES="${ENABLED_SERVICES} mysql"
+    else
+        :
+    fi
+
+    # Backend: OpenLDAP or MySQL.
+    if [ X"${BACKEND}" == X"OpenLDAP" ]; then
+        # OpenLDAP server & client.
+        if [ X"${DISTRO}" == X"RHEL" ]; then
+            ALL_PKGS="${ALL_PKGS} openldap.${ARCH} openldap-clients.${ARCH} openldap-servers.${ARCH}"
+            ENABLED_SERVICES="${ENABLED_SERVICES} ldap"
+
+        elif [ X"${DISTRO}" == X"DEBIAN" -o X"${DISTRO}" == X"UBUNTU" ]; then
+            ALL_PKGS="${ALL_PKGS} postfix-ldap slapd ldap-utils"
+            ENABLED_SERVICES="${ENABLED_SERVICES} slapd"
+        else
+            :
+        fi
+    elif [ X"${BACKEND}" == X"MySQL" ]; then
+        # MySQL server & client.
+        if [ X"${DISTRO}" == X"RHEL" ]; then
+            # For Awstats.
+            [ X"${USE_AWSTATS}" == X"YES" ] && ALL_PKGS="${ALL_PKGS} mod_auth_mysql.${ARCH}"
+
+        elif [ X"${DISTRO}" == X"DEBIAN" -o X"${DISTRO}" == X"UBUNTU" ]; then
+            ALL_PKGS="${ALL_PKGS} postfix-mysql"
+
+            # For Awstats.
+            [ X"${USE_AWSTATS}" == X"YES" ] && ALL_PKGS="${ALL_PKGS} libapache2-mod-auth-mysql"
+        else
+            :
+        fi
+    else
+        :
+    fi
+
+    # Policyd.
+    if [ X"${DISTRO}" == X"RHEL" ]; then
+        ALL_PKGS="${ALL_PKGS} policyd.${ARCH}"
+        ENABLED_SERVICES="${ENABLED_SERVICES} policyd"
+    elif [ X"${DISTRO}" == X"DEBIAN" -o X"${DISTRO}" == X"UBUNTU" ]; then
+        ALL_PKGS="${ALL_PKGS} postfix-policyd"
+        ENABLED_SERVICES="${ENABLED_SERVICES} postfix-policyd"
+    else
+        :
+    fi
+
+    # Dovecot.
+    if [ X"${ENABLE_DOVECOT}" == X"YES" ]; then
+        if [ X"${DISTRO}" == X"RHEL" ]; then
+            ALL_PKGS="${ALL_PKGS} dovecot.${ARCH} dovecot-sieve.${ARCH}"
+
+        elif [ X"${DISTRO}" == X"DEBIAN" -o X"${DISTRO}" == X"UBUNTU" ]; then
+            ALL_PKGS="${ALL_PKGS} dovecot-common dovecot-imapd dovecot-pop3d"
+        else
+            :
+        fi
+
+        ENABLED_SERVICES="${ENABLED_SERVICES} dovecot"
+    else
+        ALL_PKGS="procmail"
+        [ X"${DISTRO}" == X"RHEL" ] && ENABLED_SERVICES="${ENABLED_SERVICES} saslauthd"
+    fi
+
+    # Amavisd-new & ClamAV & Altermime.
+    if [ X"${DISTRO}" == X"RHEL" ]; then
+        ALL_PKGS="${ALL_PKGS} amavisd-new.${ARCH} clamd.${ARCH} clamav.${ARCH} clamav-db.${ARCH} spamassassin.${ARCH} altermime.${ARCH}"
+        ENABLED_SERVICES="${ENABLED_SERVICES} ${AMAVISD_RC_SCRIPT_NAME} clamd"
+    elif [ X"${DISTRO}" == X"DEBIAN" -o X"${DISTRO}" == X"UBUNTU" ]; then
+        ALL_PKGS="${ALL_PKGS} amavisd-new libcrypt-openssl-rsa-perl libmail-dkim-perl clamav clamav-base clamav-freshclam clamav-daemon spamassassin altermime"
+        ENABLED_SERVICES="${ENABLED_SERVICES} ${AMAVISD_RC_SCRIPT_NAME} clamav-daemon clamav-freshclam"
+    else
+        :
+    fi
+
+    [ X"${DISTRO}" == X"DEBIAN" -o X"${DISTRO_CODENAME}" == X"hardy" ] && ALL_PKGS="${ALL_PKGS} libclamav5"
+
+    # SPF.
+    if [ X"${ENABLE_SPF}" == X"YES" ]; then
+        if [ X"${DISTRO}" == X"RHEL" ]; then
+            # SPF implemention via perl-Mail-SPF.
+            ALL_PKGS="${ALL_PKGS} perl-Mail-SPF.noarch perl-Mail-SPF-Query.noarch"
+
+        elif [ X"${DISTRO}" == X"DEBIAN" -o X"${DISTRO}" == X"UBUNTU" ]; then
+            ALL_PKGS="${ALL_PKGS} libmail-spf-perl"
+        else
+            :
+        fi
+    else
+        :
+    fi
+
+    # pysieved.
+    # Warning: Do *NOT* add 'pysieved' service in 'ENABLED_SERVICES'.
+    #          We don't have rc/init script under /etc/init.d/ till
+    #          package is installed.
+    if [ X"${USE_MANAGESIEVE}" == X"YES" ]; then
+        # Note for Ubuntu & Debian:
+        # Dovecot shipped in Debian/Ubuntu has managesieve plugin patched.
+        [ X"${DISTRO}" == X"RHEL" ] && ALL_PKGS="${ALL_PKGS} pysieved.noarch"
+    else
+        :
+    fi
+
+    # SquirrelMail.
+    if [ X"${USE_SM}" == X"YES" ]; then
+        [ X"${DISTRO}" == X"RHEL" ] && ALL_PKGS="${ALL_PKGS} php-pear-db.noarch"
+        [ X"${DISTRO}" == X"DEBIAN" -o X"${DISTRO}" == X"UBUNTU" ] && \
+            ALL_PKGS="${ALL_PKGS} php-db"
+    else
+        :
+    fi
+
+    # iRedAdmin.
+    if [ X"${USE_IREDADMIN}" == X"YES" ]; then
+        [ X"${DISTRO}" == X"RHEL" ] && \
+        ALL_PKGS="${ALL_PKGS} python-jinja2.${ARCH} python-webpy.noarch python-ldap.${ARCH} MySQL-python.${ARCH} mod_wsgi.${ARCH}"
+
+        [ X"${DISTRO}" == X"DEBIAN" -o X"${DISTRO}" == X"UBUNTU" ] && \
+            ALL_PKGS="${ALL_PKGS} libapache2-mod-wsgi python-mysqldb python-ldap python-jinja2 python-netifaces python-webpy"
+    else
+        :
+    fi
+}
+
+get_all_misc()
+{
+    export EXTRA_FILES=''
+
+    # SSL keys.
+    EXTRA_FILES="${EXTRA_FILES} ${SSL_CERT_FILE} ${SSL_KEY_FILE}"
+
+    # Apache & PHP.
+    EXTRA_FILES="${EXTRA_FILES} ${HTTPD_CONF_ROOT} ${PHP_INI} /etc/php.d"
+
+    # MySQL.
+    EXTRA_FILES="${EXTRA_FILES} ${MYSQL_MY_CNF} /var/lib/mysql /var/log/mysqld.log /var/log/mysql.log /etc/mysql"
+
+    # OpenLDAP.
+    EXTRA_FILES="${EXTRA_FILES} ${OPENLDAP_CONF_ROOT} ${OPENLDAP_DATA_DIR} ${OPENLDAP_LOGFILE} ${OPENLDAP_LOGROTATE_FILE}"
+
+    # Postfix.
+    EXTRA_FILES="${EXTRA_FILES} ${POSTFIX_ROOTDIR}"
+
+    # Dovecot.
+    EXTRA_FILES="${EXTRA_FILES} ${DOVECOT_CONF} ${DOVECOT_LDAP_CONF} ${DOVECOT_MYSQL_CONF} ${DOVECOT_LOG_FILE} ${SIEVE_LOG_FILE} ${DOVECOT_LOGROTATE_FILE} ${SIEVE_LOGROTATE_FILE} ${DOVECOT_EXPIRE_DICT_BDB} ${GLOBAL_SIEVE_FILE} ${DOVECOT_QUOTA_WARNING_BIN}"
+
+    # Procmail.
+    EXTRA_FILES="${EXTRA_FILES} ${PROCMAILRC} ${PROCMAIL_LOGFILE} ${PROCMAIL_LOGROTATE_FILE}"
+
+    # Policyd.
+    EXTRA_FILES="${EXTRA_FILES} ${POLICYD_CONF} ${POLICYD_SENDER_THROTTLE_CONF} ${POLICYD_LOGFILE} ${POLICYD_LOGROTATE_FILE}"
+
+    # Pysieved.
+    EXTRA_FILES="${EXTRA_FILES} ${PYSIEVED_INI} /etc/init.d/pysieved"
+
+    # Amavisd.
+    EXTRA_FILES="${EXTRA_FILES} ${AMAVISD_CONF} ${AMAVISD_DKIM_CONF} ${AMAVISD_DKIM_DIR} ${AMAVISD_LOGFILE} ${AMAVISD_LOGROTATE_FILE} ${DISCLAIMER_DIR}"
+
+    # ClamAV.
+    EXTRA_FILES="${EXTRA_FILES} ${CLAMD_CONF} ${FRESHCLAM_CONF} ${CLAMD_LOGFILE} ${FRESHCLAM_LOGFILE}"
+
+    # Awstats.
+    EXTRA_FILES="${EXTRA_FILES} ${AWSTATS_CONF_DIR} ${AWSTATS_HTTPD_ROOT} ${AWSTATS_CGI_DIR}"
+
+    # phpLDAPadmin.
+    EXTRA_FILES="${EXTRA_FILES} ${PLA_HTTPD_ROOT} ${HTTPD_SERVERROOT}/phpldapadmin"
+
+    # phpMyAdmin.
+    EXTRA_FILES="${EXTRA_FILES} ${PHPMYADMIN_HTTPD_ROOT} ${HTTPD_SERVERROOT}/phpmyadmin"
+
+    # Roundcube webmail.
+    EXTRA_FILES="${EXTRA_FILES} ${RCM_HTTPD_ROOT} ${HTTPD_SERVERROOT}/roundcubemail ${RCM_LOGFILE} ${RCM_LOGROTATE_FILE}"
+
+    # PostfixAdmin.
+    EXTRA_FILES="${EXTRA_FILES} ${POSTFIXADMIN_HTTPD_ROOT} ${HTTPD_SERVERROOT}/postfixadmin"
+
+    # SquirrelMail.
+    EXTRA_FILES="${EXTRA_FILES} ${SM_HTTPD_ROOT} ${HTTPD_SERVERROOT}/squirrelmail"
+
+    # iRedAdmin.
+    EXTRA_FILES="${EXTRA_FILES} ${IREDADMIN_HTTPD_ROOT} ${HTTPD_SERVERROOT}/iredadmin"
+
+    # Misc.
+    EXTRA_FILES="${EXTRA_FILES} ${LOCAL_REPO_FILE}"
+}
+
+# Ge all users & groups
+get_all_accounts()
+{
+    export ALL_USERS=''
+    export ALL_GROUPS=''
+
+    # Vmail.
+    ALL_USERS="${ALL_USERS} ${VMAIL_USER_NAME}"
+    ALL_GROUPS="${ALL_GROUPS} ${VMAIL_GROUP_NAME}"
+
+    # Apache.
+    #ALL_USERS="${ALL_USERS} ${HTTPD_USER}"
+    #ALL_GROUPS="${ALL_GROUPS} ${HTTPD_GROUP}"
+
+    # OpenLDAP.
+    #ALL_USERS="${ALL_USERS} ${LDAP_USER}"
+    #ALL_GROUPS="${ALL_GROUPS} ${LDAP_GROUP}"
+
+    # Dovecot.
+    #ALL_USERS="${ALL_USERS} ${DOVECOT_USER}"
+    #ALL_GROUPS="${ALL_GROUPS} ${DOVECOT_GROUP}"
+
+    # Policyd.
+    ALL_USERS="${ALL_USERS} ${POLICYD_USER}"
+    ALL_GROUPS="${ALL_GROUPS} ${POLICYD_GROUP}"
+
+    # Amavisd.
+    if [ X"${DISTRO}" == X"DEBIAN" -o X"${DISTRO}" == X"UBUNTU" ]; then
+        ALL_USERS="${ALL_USERS} ${AMAVISD_SYS_USER}"
+        ALL_GROUPS="${ALL_GROUPS} ${AMAVISD_SYS_GROUP}"
+    fi
+
+    # ClamAV.
+    #ALL_USERS="${ALL_USERS} ${CLAMAV_USER}"
+    #ALL_GROUPS="${ALL_GROUPS} ${CLAMAV_GROUP}"
+}
+
+get_all_pkgs
+get_all_misc
+get_all_accounts
+
+ECHO_INFO "=================== Stop services ================"
+for i in ${ENABLED_SERVICES}; do
+    [ -x /etc/init.d/$i ] && /etc/init.d/$i stop
+done
+
+ECHO_INFO "=================== Remove binary packages ================"
+remove_pkg ${ALL_PKGS}
+
+ECHO_INFO "=================== Remove users ================"
+for user in ${ALL_USERS}; do
+    confirm_to_remove_account user ${user}
+done
+
+ECHO_INFO "=================== Remove groups ================"
+for group in ${ALL_GROUPS}; do
+    confirm_to_remove_account group ${group}
+done
+
+ECHO_INFO "=================== Remove configuration files ================"
+for i in ${EXTRA_FILES}; do
+    [ -e ${i} -o -L ${i} ] && rm -rfi ${i}
+done
+
+if [ X"${DISTRO}" == X"DEBIAN" -o X"${DISTRO}" == X"UBUNTU" ]; then
+    for i in $(dpkg-statoverride --list); do
+        file="$(echo $i | awk '{print $NF}')"
+        #rm -rf $file 2>/dev/null
+        [ ! -z ${file} ] && dpkg-statoverride --remove $file
+    done
+fi

extra/delete_ldap_accounts.py

+#!/usr/bin/env python
+# encoding: utf-8
+
+# Author:   Zhang Huangbin <zhb@iredmail.org>
+# Purpose:  Delete specified mail accounts.
+# Date:     2011-03-01
+
+import sys
+import shlex
+import subprocess
+import ldap
+
+# Note:
+#   * bind_dn must have write privilege on LDAP server.
+uri = 'ldap://127.0.0.1:389'
+basedn = 'o=domains,dc=iredmail,dc=org'
+bind_dn = 'cn=Manager,dc=iredmail,dc=org'
+bind_pw = 'passwd'
+
+allAccounts = sys.argv[1:]
+total = len(allAccounts)
+
+if not total > 0:
+    print >> sys.stderr, '* Exit. No users specified.'
+    sys.exit(0)
+else:
+    print >> sys.stderr, "* Total %d user(s)." % (total)
+
+# Initialize LDAP connection.
+print >> sys.stderr, "* Connecting to LDAP server: %s" % uri
+conn = ldap.initialize(uri=uri, trace_level=0,)
+conn.bind_s(bind_dn, bind_pw)
+
+# Generate LDAP search filter.
+filter_objcls = '(|(objectClass=mailUser)(objectClass=mailList)(objectClass=mailAlias))'
+filter_mails = '(|'
+for mail in allAccounts:
+    filter_mails += '(mail=%s)(shadowAddress=%s)' % (str(mail), str(mail))
+filter_mails += ')'
+
+filter = '(&%s%s)' % (filter_objcls, filter_mails,)
+
+# Query LDAP to get maildir related info.
+print >> sys.stderr, "* Get LDAP info of specified mail accounts..."
+qr = conn.search_s(
+    basedn,
+    ldap.SCOPE_SUBTREE,
+    filter,
+    ['dn', 'objectClass', 'mail', 'storageBaseDirectory', 'mailMessageStore',],
+)
+
+print >> sys.stderr, '* Total %d account(s) found in LDAP server.' % (len(qr))
+for account in qr:
+    (dn, entry) = account
+    mail = entry.get('mail', [''])[0]
+    objectClasses = entry.get('objectClass', [])
+
+    if 'mailUser' in objectClasses:
+        storageBaseDirectory = entry.get('storageBaseDirectory', [''])[0]
+        mailMessageStore = entry.get('mailMessageStore', [''])[0]
+        mailbox = storageBaseDirectory + '/' + mailMessageStore
+
+        answer = raw_input('? Delete mailbox of %s (%s)? [y|N]' % (mail, mailbox))
+        if answer.lower() == 'y':
+            try:
+                p = subprocess.Popen(shlex.split('rm -rf %s' % mailbox))
+            except Exception, e:
+                print >> sys.stderr, '<< ERROR >> %s' % str(e)
+
+    # Delete account from LDAP server.
+    answer = raw_input('? Delete account from LDAP server (%s)? [y|N]' % (dn))
+    if answer.lower() == 'y':
+        try:
+            conn.delete_s(dn)
+        except Exception, e:
+            print >> sys.stderr, e
+
+# Unbind connection.
+print >> sys.stderr, "* Unbind LDAP server."
+conn.unbind()

extra/iRedMail.tips

+Admin of domain example.com:
+    * Account: postmaster@example.com
+    * Password: iredmail
+
+    Note:
+        - This account is used only for system administrations, not a mail user.
+        - You can login iRedAdmin or PostfixAdmin with this account, login name
+          is full email address.
+
+First mail user:
+    * Account: www@example.com
+    * Password: iredmail
+
+    Note:
+        - This account is a normal mail user.
+        - You can login webmail with this account, login name is full email address.
+
+Admin of domain example.com:
+    * Account: postmaster@example.com
+    * Password: iredmail
+
+    Note:
+        - This account is used only for system administrations, not a mail user.
+        - You can login iRedAdmin or PostfixAdmin with this account, login name
+          is full email address.
+
+First mail user:
+    * Account: www@example.com
+    * Password: iredmail
+
+    Note:
+        - This account is a normal mail user.
+        - You can login webmail with this account, login name is full email address.
+
+Mail Storage:
+    - Path:
+        + /var/vmail
+        + /var/vmail/vmail01
+
+Apache & PHP:
+    * Configuration files:
+        - /etc/apache2
+        - /etc/apache2/conf.d
+        - /etc/php5/apache2/php.ini
+    * Directories:
+        - /usr/share/apache2
+        - /var/www
+
+OpenLDAP:
+    * LDAP suffix: dc=example,dc=com
+    * LDAP root dn: cn=Manager,dc=example,dc=com, password: iredmail
+    * LDAP bind dn: cn=vmail,dc=example,dc=com, password: rtj8peGYAnCHQWogf1MJuTnP7y2iYq
+    * LDAP admin dn: cn=vmailadmin,dc=example,dc=com, password: mdM7S6QoKM1mKcylLjUOp53UYscat1
+    * LDAP base dn: o=domains,dc=example,dc=com
+    * LDAP admin base dn: o=domainAdmins,dc=example,dc=com
+    * Configuration files:
+        - /etc/ldap
+        - /etc/ldap/slapd.conf
+        - /etc/ldap/ldap.conf
+        - /etc/ldap/schema/iredmail.schema
+    * Log file related:
+        - /etc/syslog.conf
+        - /var/log/openldap.log
+        - /etc/logrotate.d/openldap
+    * Data dir and files:
+        - /var/lib/ldap
+        - /var/lib/ldap/example.com
+        - /var/lib/ldap/example.com/DB_CONFIG
+    * RC script:
+        - /etc/init.d/slapd
+    * See also:
+        - /root/iRedMail-0.5.1/conf/ldap_init.ldif
+
+MySQL:
+    * Data directory:
+        - /var/lib/mysql
+    * RC script:
+        - /etc/init.d/mysql
+    * Log file:
+        - /var/log/mysqld.log
+    * SSL Cert keys:
+        - /etc/ssl/certs/iRedMail_CA.pem
+        - /etc/ssl/private/iRedMail.key
+    * See also:
+        - /root/iRedMail-0.5.1/conf/mysql_init.sql
+
+Postfix (basic):
+    * Configuration files:
+        - /etc/postfix
+        - /etc/postfix/aliases
+        - /etc/postfix/main.cf
+        - /etc/postfix/master.cf
+
+Postfix (LDAP):
+    * Configuration files:
+        - /etc/postfix/ldap_virtual_mailbox_domains.cf
+
+        - /etc/postfix/ldap_transport_maps_domain.cf
+
+        - /etc/postfix/ldap_transport_maps_user.cf
+
+        - /etc/postfix/ldap_virtual_mailbox_maps.cf
+
+        - /etc/postfix/ldap_virtual_alias_maps.cf
+
+        - /etc/postfix/ldap_virtual_group_maps.cf
+
+        - /etc/postfix/ldap_recipient_bcc_maps_domain.cf
+
+        - /etc/postfix/ldap_recipient_bcc_maps_user.cf
+
+        - /etc/postfix/ldap_sender_bcc_maps_domain.cf
+
+        - /etc/postfix/ldap_sender_bcc_maps_user.cf
+
+Postfix (syslog):
+    * logrotate file: /etc/logrotate.d/maillog
+
+Policyd:
+    * Configuration files:
+        - /etc/postfix-policyd.conf
+    * RC script:
+        - /etc/init.d/policyd
+    * Misc:
+        - /etc/cron.daily/policyd-cleanup
+        - 
+        - crontab -l -u policyd
+
+
+Dovecot:
+    * Configuration files:
+        - /etc/dovecot/dovecot.conf
+    * LDAP:
+        - /etc/dovecot/dovecot-ldap.conf
+    * MySQL:
+        - /etc/dovecot/dovecot-mysql.conf
+    * RC script:
+        - /etc/init.d/dovecot
+    * Log files:
+        - /etc/logrotate.d/dovecot
+        - /var/log/dovecot.log
+        - /var/log/sieve.log
+    * See also:
+        - /var/vmail/sieve/dovecot.sieve
+
+ClamAV:
+    * Configuration files:
+        - /etc/clamav/clamd.conf
+        - /etc/clamav/freshclam.conf
+        - /etc/logrotate.d/clamav
+    * RC scripts:
+        - RHEL/CentOS:
+            + /etc/init.d/clamd 
+            + /etc/init.d/freshclam
+        - Debian & Ubuntu:
+            + /etc/init.d/clamav-daemon
+            + /etc/init.d/clamav-freshclam
+    * Log files:
+        - /var/log/clamav/clamd.log
+        - /var/log/clamav/freshclam.log
+
+DNS record for DKIM support:
+; key#1, domain example.com, /var/lib/dkim/example.com.pem
+dkim._domainkey.example.com.	3600 TXT (
+  "v=DKIM1; p="
+  "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCyVhmN8+xW5OpVA7SXQd345BbG"
+  "ZoB/zIDxCsS84c/jSA7An6tLRDXkIr3egtrJCmjYt3+B5IJWH1CVuIyalCT90mcw"
+  "NDuDgcImMXQJVB7J9ocIS7XT44YOqKXk/8TZHWTXtsfV3JmcsVcUC9nNzKHEOohf"
+  "uuTfNTPiCotFwOhifQIDAQAB")
+
+Amavisd-new:
+    * Configuration files:
+        - /etc/amavis/conf.d/50-user
+        - /etc/postfix/master.cf
+        - /etc/postfix/main.cf
+    * RC script:
+        - /etc/init.d/amavis
+
+SpamAssassin:
+    * Configuration files:
+        - /etc/mail/spamassassin/
+
+    - Rules:
+        * /usr/share/spamassassin/
+
+WebMail(Roundcubemail):
+    * Configuration files:
+        - /usr/share/apache2/roundcubemail-0.2.1/
+        - /usr/share/apache2/roundcubemail-0.2.1/config/
+    * URL:
+        - http://mail.example.com/mail/
+        - http://mail.example.com/webmail/
+    * Login account:
+        - Username: www@example.com, password: iredmail
+    * See also:
+        - /etc/apache2/conf.d/roundcubemail.conf
+
+phpLDAPadmin:
+    * Configuration files:
+        - /usr/share/apache2/phpldapadmin-1.1.0.7/config/config.php
+    * URL:
+        - /usr/share/apache2/phpldapadmin-1.1.0.7
+        - https://mail.example.com/phpldapadmin/
+        - https://mail.example.com/ldap/
+    * Login account:
+        - LDAP root account:
+            + Username: cn=Manager,dc=example,dc=com
+            + Password: iredmail
+        - Mail admin:
+            + Username: cn=vmailadmin,dc=example,dc=com
+            + Password: mdM7S6QoKM1mKcylLjUOp53UYscat1
+    * See also:
+        - /etc/apache2/conf.d/phpldapadmin.conf
+
+phpMyAdmin:
+    * Configuration files:
+        - /usr/share/apache2/phpMyAdmin-2.11.9.5-all-languages
+        - /usr/share/apache2/phpMyAdmin-2.11.9.5-all-languages/config.inc.php
+    * Login account:
+        - Username: root, password: iredmail
+        - Username: vmailadmin, password: lyTPOU3assz4VrcV7JuWlmHtVy4zmA
+    * URL:
+        - https://mail.example.com/phpmyadmin
+    * See also:
+        - /etc/apache2/conf.d/phpmyadmin.conf
+
+Awstats:
+    * Configuration files:
+        - /etc/awstats
+        - /etc/awstats/awstats.conf
+        - /etc/awstats/awstats.mail.example.com.conf
+        - /etc/awstats/awstats.mail.conf
+        - /etc/apache2/conf.d/awstats.conf
+    * Login account:
+        - Username: postmaster@example.com, password: iredmail
+    * URL:
+        - https://mail.example.com/awstats/awstats.pl
+        - https://mail.example.com/awstats/awstats.pl?config=mail.example.com
+        - https://mail.example.com/awstats/awstats.pl?config=mail
+    * Crontab job:
+        shell> crontab -l root
+    
+Official Web-based Admin Panel (iRedAdmin):
+    * Version: 0.1.1
+    * Configuration files:
+        - /usr/share/apache2/iRedAdmin-0.1.1/
+        - /usr/share/apache2/iRedAdmin-0.1.1/settings.ini*
+    * URL:
+        - https://mail.example.com/iredadmin/
+    * Login account:
+        - Username: postmaster@example.com, password: iredmail
+    * MySQL database and account:
+        - Database name: iredadmin
+        - Database user: iredadmin
+        - Database password: 96R7BjhvJoYOaKWrLHNJ4hAWGEIf02
+    * See also:
+        - /etc/apache2/conf.d/iredadmin.conf
+
+#
+# Kickstart file used to customize iRedOS. Provided by iRedMail project:
+# http://code.google.com/p/iredmail/
+#
+
+# Used for interactive installation.
+#interactive
+
+# Install OS instead of upgrade
+install
+
+# Installation method.
+cdrom
+
+# For RHEL 5.x
+#key --skip
+
+# System authorization information
+auth  --useshadow  --enablemd5
+
+# System keyboard
+#keyboard us
+
+# System language. It will affect both installation interface and
+# system after installation complete.
+#lang en_US
+
+# Installation logging level: debug, info, warning, error, critical.
+#logging --level=debug
+logging --level=critical
+
+# SELinux configuration
+selinux --disabled
+
+# Do not configure the X Window System
+skipx
+
+# System timezone. Do not use '--utc' option here.
+#timezone Asia/Hong_Kong
+
+# Use graphical/text install
+graphical
+
+# Enable/Disable services, seperated by comma.
+# Options: --enabled/disabled
+services --enabled=network
+
+# -------------------
+# ---- Test only ----
+# -------------------
+# System bootloader configuration
+#bootloader --location=mbr
+
+# Clear the Master Boot Record
+#zerombr
+
+# Partition clearing information
+#clearpart --all --initlabel 
+
+#Root password: redhat
+#rootpw --iscrypted $1$h7EtIFv4$R9JQ4aCOVN7E9ml3A2SXv.
+
+# Run the Setup Agent on first boot
+firstboot --disable
+
+# Network information
+network --onboot=yes --bootproto=query --hostname='iredos.iredmail.org'
+
+# Disk partitioning information
+#part swap --bytes-per-inode=4096 --fstype="swap" --size=512
+#part / --bytes-per-inode=4096 --fstype="ext3" --grow --size=1
+
+# -------------------
+
+# For more kickstart options, please refer:
+# http://www.redhat.com/docs/manuals/enterprise/RHEL-5-manual/Installation_Guide-en-US/s1-kickstart2-options.html
+# -------------------------------------------
+# Packages.
+# -------------------------------------------
+%packages --excludedocs
+basesystem
+kernel
+
+-rmt
+-dump
+-amtu
+-anacron
+-acpid
+-apmd
+-at
+-ftp
+-redhat-lsb
+-atk
+-gtk2
+-GConf2
+-bluez-gnome
+-bluez-utils
+-notification-daemon
+-libwnck
+-libnotify
+-attr
+-audit
+-audit-libs-python
+-setools
+-authconfig
+-firstboot-tui
+-autofs
+-bc
+-bluez-libs
+-cairo
+-pango
+-paps
+-cups
+-ccid
+-coolkey
+-cpuspeed
+-Deployment_Guide-en-US
+-dhcpv6_client
+-finger
+-hdparm
+-dmraid
+-NetworkManager
+-smartmontools
+-ppp
+-rp-pppoe
+-ecryptfs-utils
+#-rhn-client-tools
+#-rhn-check
+#-yum-rhn-plugin
+#-rhnsd
+#-rhn-setup
+-hesiod
+-sendmail
+-ifd-egate
+-pcsc-lite
+-gpm
+-ipsec-tools
+-libselinux-python
+-ksh
+-mailcap
+-nano
+-nc
+-mtools
+-syslinux
+-mkbootdisk
+-net-snmp-libs
+-OpenIPMI
+-redhat-menus
+-htmlview
+-pinfo
+-mgetty
+-specspo
+-nscd
+-nss_ldap
+-nfs-utils-lib
+-nfs-utils
+-portmap
+-ypbind
+-yp-tools
+-quota
+-lsof
+-irqbalance
+-system-config-securitylevel-tui
+-crash
+-conman
+-cryptsetup-luks
+-dbus-python
+-yum-updatesd
+-dosfstools
+-gnu-efi
+-iptstate
+-microcode_ctl
+-mtr
+-pam_smb
+-parted
+-pax
+-pm-utils
+-psacct
+-pygobject2
+-rdate
+-rdist
+-rhel-instnum
+-rsh
+-sos
+-talk
+-tcsh
+-telnet
+-exim
+# ------------------------
+# Required packages.
+# ------------------------
+# Required by postfix (/etc/pam.d/smtp.postfix)
+policycoreutils
+selinux-policy
+selinux-policy-targeted
+
+ntp
+man
+man-pages
+lynx
+wget
+mailx
+openssh-server
+openssh-clients
+unzip
+bzip2
+dhclient
+vim-minimal
+system-config-network-tui
+iptables
+tmpwatch
+acl
+createrepo
+vixie-cron
+crontabs
+dialog
+patch
+yum
+which
+kbd
+dos2unix
+logwatch
+
+# Post macro.
+%post --nochroot
+# Mount CD-ROM, will be used after chroot.
+mkdir -p /mnt/sysimage/mnt/
+mount -t iso9660 /tmp/cdrom /mnt/sysimage/mnt
+
+%post
+
+# Change tty, we need interactive mode.
+chvt 3
+
+exec < /dev/tty3 > /dev/tty3
+
+echo -e "\n\n* ---- Starting iRedMail Installation ----"
+
+# Set LC_ALL.
+echo "* Export LC_ALL"
+export LC_ALL=C
+
+# Set PATH.
+echo "* Set PATH"
+export PATH="/usr/kerberos/sbin:/usr/kerberos/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin"
+
+# Repo file.
+echo "* Set yum repository related variables: REPOFILE, REPOFILE, REPOURL"
+export REPOFILE='/etc/yum.repos.d/iRedMail.repo'
+export REPONAME='iRedMail'
+export REPOURL='http://iredmail.org/yum/rpms/5/'
+
+# Get hostname from file.
+echo "* Get HOSTNAME via cmd 'hostname --fqdn'."
+export HOSTNAME="$(hostname --fqdn)"
+
+# Copy /etc/skel/.*
+echo "* Copy /etc/skel/*"
+cp -rf /etc/skel/.bash* /root/ >/dev/null 2>&1
+
+# We need network, but loopback device is enough.
+echo "* Active loop back network interface: lo."
+/sbin/ifconfig lo up
+
+# Create yum repo file for iRedMail.
+echo "* Generate temp yum repo file: ${REPOFILE}"
+cat > ${REPOFILE} <<EOF
+[${REPONAME}]
+name=${REPONAME}
+baseurl=file:///mnt/
+enabled=1
+gpgcheck=0
+priority=1
+EOF
+
+# We need write-access.
+echo "* Copy iRedMail from CDROM to disk: /root/iRedMail"
+cp -rf /mnt/iRedMail/ /root/
+
+# Change directory.
+echo "* Change directory to /root/iRedMail/"
+cd /root/iRedMail/
+
+#
+# Run iRedMail.sh:
+#
+
+echo "* Set necessary variables for iRedMail."
+# Skip some steps.
+export status_get_all="DONE"
+# Don't create a new yum repo.
+export status_create_yum_repo="DONE"
+# Don't disable iredmail repo.
+export status_disable_iredmail_repo="DONE"
+# Don't run freshclam.
+export status_run_freshclam_now="DONE"
+# Don't start postfix.
+export status_start_postfix_now="DONE"
+# Don't upgrade php-pear now.
+export status_cleanup_upgrade_php_pear="DONE"
+
+# Setting command used to install pkgs.
+export YUM="yum -d 2 --disablerepo=os,base,updates,addons,extras,centosplus,c5-media --enablerepo=${REPONAME}"
+
+echo "* Sleeping 10 seconds before starting iRedMail installation wizard."
+for i in 10 9 8 7 6 5 4 3 2 1; do
+    echo -n " ${i}s" && sleep 1
+done
+echo '.'
+
+echo "* Start iRedMail installation."
+# Answer some questions automatic:
+#   - Y: Continue install packages after configure complete.
+#   - Y: Use iptables rule file shipped within iRedMail?
+#   - N: Restart iptables now?
+#   - Y: Use MySQL config file (/etc/my.cnf) shipped within iRedMail?
+#   - N: Start postfix now?
+sh iRedMail.sh <<EOF
+Y
+Y
+N
+Y
+N
+EOF
+
+# Read iRedMail config.
+. config
+
+if [ X"${BACKEND}" == X"OpenLDAP" ]; then
+    echo "* Install php pear package: Net_LDAP2."
+    pear install /root/iRedMail/pkgs/misc/Net_LDAP2-2.0.9.tgz
+fi
+
+# Clear yum repo metadata.
+yum clean all 2>/dev/null
+
+# Re-generate yum repo file, used for softwares update.
+cat > ${REPOFILE} <<EOF
+[${REPONAME}]
+name=${REPONAME}
+baseurl=${REPOURL}
+enabled=1
+gpgcheck=0
+priority=1
+EOF
+
+# Return to default installation tty.
+grep '\<text\>' /proc/cmdline >/dev/null 2>&1
+if [ X"$?" == X"0" ]; then
+    # For text installation mode.
+    chvt 1
+    exec < /dev/tty1 > /dev/tty1
+else
+    # For graphical installation mode.
+    chvt 6
+    exec < /dev/tty6 > /dev/tty6
+fi

extra/migration/convert_winmail_mailbox.sh

+#!/usr/bin/env bash
+
+# Author:   Zhang Huangbin (michaelbibby <at> gmail.com )
+# Purpose:  Convert WinMail user mailboxs to standard IMAP directory
+#           structure (mailbox format).
+
+# Migration guide wrote in Chinese:
+#   http://code.google.com/p/iRedMail/wiki/iRedMail_tut_Migration
+
+# Description:
+#   WinMail stores all mails in user mailbox with email address as mailbox
+#   name, such as:
+#
+#       /path/to/mail/store/user@example.com/
+#                           |- xxxxxx.in    # Received (Inbound)
+#                           |- xxxxxx.out   # Sent (Outbound)
+#                           |- xxxxxx.del   # Deleted
+#
+#   What this script do is:
+#
+#       * Creates standard IMAP directory structure (mailbox format).
+#       * Copies mails to correct directories.
+#
+
+# Usage:
+#   1) Specify these variables below:
+#
+#       * source_dir    -> Where you store WinMail user mailboxes.
+#       * target_dir    -> Where you want to store converted mailboxes.
+#       * vmail_user    -> Owner (user) of your user mailboxes.
+#       * vmail_group   -> Owner (group) of your user mailboxes.
+#
+#       Default file localtion looks like below:
+#
+#           /path/to/mail/store/
+#                           |- user1@example.com/
+#                           |- user2@example.com/
+#                           |- user3@example.com/
+#                           |- convert_winmail_mailbox.sh   # <- we are here.
+#
+#   2) Execute command:
+#
+#       # sh convert_winmail_mailbox.sh
+#
+#      It will create new directory named as domain name, and user
+#      mailbox is named as username (without domain part), such as:
+#
+#           example.com/
+#               |- user1/
+#                   |- cur/     # Received, read.
+#                   |- new/     # Received, unread.
+#                   |- tmp/
+#                   |- .Drafts/ # Drafts.
+#                   |- .Sent/   # Sent.
+#                   |- .Trash/  # Trash, deleted.
+#               |- user2/
+#
+#   3) Copy the 'example.com/' to the location where you store user
+#      mailboxes.
+
+# Your original WinMail user mailboxes.
+source_dir='./'
+# Copy emails to another directory, it will be standard IMAP directory
+# structure (mailbox format).
+target_dir='./'
+
+# vmail user name/uid.
+vmail_user='vmail'
+# vmail group name/uid.
+vmail_group='vmail'
+
+for i in $(ls -d *@w-ibeda.com)
+do
+    username="$(echo $i | awk -F'@' '{print $1}')"
+    domain="$(echo $i | awk -F'@' '{print $2}')"
+    mailbox="${target_dir}/$domain/$username/"
+    
+    #mailbox="$(echo $i | awk -F'@' '{print $1"/"$2"/"}')"
+
+    # Create necessary directories as mailbox format.
+    # Inbox.
+    mkdir -p ${mailbox}/{cur,new,tmp}
+    # Sent,Junk,Drafts,Trash
+    mkdir -p ${mailbox}/.{Sent,Junk,Drafts,Trash}/{cur,new,tmp}
+
+    find_dir="${source_dir}/$i/"
+
+    # Copy inbox.
+    for email in $(find ${find_dir} -iname '*.in')
+    do
+        cp -f $email ${mailbox}/cur/
+    done
+
+    # Copy deleted mails.
+    for email in $(find ${find_dir} -iname '*.del')
+    do
+        cp -f $email ${mailbox}/.Trash/
+    done
+
+    # Copy sent mails.
+    for email in $(find ${find_dir} -iname '*.out')
+    do
+        cp -f $email ${mailbox}/.Sent/
+    done
+
+    chown -R ${vmail_user}:${vmail_group} ${target_dir}/${domain}
+done

extra/migration/migrate_extmail_mailbox.sh

+#!/usr/bin/env bash
+
+# Author:   Zhang Huangbin (michaelbibby <at> gmail.com )
+# Purpose:  Migrate ExtMail MySQL 'mailbox' table to iRedMail format.
+# Project:  iRedMail (http://www.iredmail.org/)
+#
+# Migration guide wrote in Chinese:
+#   http://www.iredmail.org/wiki/index.php?title=Migrate_from_ExtMail_Solution
+
+# Usage:
+#   English:
+#   * Run into MySQL command line with privilege user, e.g. root.
+#       # mysql -uroot -p extmail
+#   * Select some column from mailbox table:
+#       mysql> SELECT username,password,name,maildir,quota,netdiskquota,domain,createdate,active
+#            > INTO OUTFILE '/tmp/mailbox.sql'
+#            > FROM mailbox;
+#   * Run this script:
+#       # sh migrate_extmail_mailbox.sh /tmp/mailbox.sql
+#     It will create a new file: /tmp/mailbox.sql.new
+#   * Import this new file in MySQL command line:
+#       mysql> USE vmail;
+#       mysql> SOURCE /tmp/mailbox.sql.new;
+
+usage()
+{
+    echo -e "\nUsage: sh $0 script\n"
+}
+
+[ X"$#" != X"1" ] && usage && exit 255 
+
+OUTPUT_SQL="$1.iRedMail"
+echo ''> ${OUTPUT_SQL}
+
+while read line; do
+    username="$(echo $line | awk '{print $1}')"
+    password="$(echo $line | awk '{print $2}')"
+    maildir="$(echo $line | awk '{print $3}' | awk -F'Maildir/' '{print $1}' | tr [A-Z] [a-z] )"
+    quota="$(echo $line | awk '{print $4}')"
+    netdiskquota="$(echo $line | awk '{print $5}')"
+    domain="$(echo $line | awk '{print $6}')"
+    createdate="$(echo $line | awk '{print $7, $8}')"
+    active="$(echo $line | awk '{print $9}')"
+
+    echo $quota | grep -i 'S$' >/dev/null 2>&1
+    if [ X"$?" == X"0" ]; then
+        quota="$(echo $quota | sed 's/S$//')"
+        quota="$(expr \( $quota / 1024 \) )"
+    else
+        :
+    fi
+
+    cat >> ${OUTPUT_SQL} <<EOF
+INSERT INTO mailbox (username, password, maildir, quota, netdiskquota, domain, created, active) values ("$username", "$password", "$maildir", $quota, $quota, "$domain", "$createdate", "$active");
+EOF
+done < $1
+
+cat <<EOF
+Warning: you may want to change 'mail_location' setting in /etc/dovecot.conf like below:
+
+    mail_location = maildir:/%Lh/Maildir/:INDEX=/%Lh/Maildir/
+
+EOF

extra/pureftpd.schema

+#
+# pureftpd.schema
+#
+# Pure-FTPd User LDAP Schema
+# See README.LDAP in the Pure-FTPd documentation for more information.
+#
+# Written by Ben Gertzfield <che =AT= debian -DOT- org>
+#
+
+## Pure-FTPd-related LDAP attributes
+
+attributetype ( 1.3.6.1.4.1.6981.11.3.1 NAME 'FTPQuotaFiles'
+        DESC 'Quota (in number of files) for an FTP user'
+        EQUALITY integerMatch
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )
+
+attributetype ( 1.3.6.1.4.1.6981.11.3.2 NAME 'FTPQuotaMBytes'
+        DESC 'Quota (in megabytes) for an FTP user'
+        EQUALITY integerMatch        
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )
+
+attributetype ( 1.3.6.1.4.1.6981.11.3.3 NAME 'FTPUploadRatio'
+        DESC 'Ratio (compared with FTPRatioDown) for uploaded files'
+        EQUALITY integerMatch        
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )
+
+attributetype ( 1.3.6.1.4.1.6981.11.3.4 NAME 'FTPDownloadRatio'
+        DESC 'Ratio (compared with FTPRatioUp) for downloaded files'
+        EQUALITY integerMatch        
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )
+
+attributetype ( 1.3.6.1.4.1.6981.11.3.5 NAME 'FTPUploadBandwidth'
+        DESC 'Bandwidth (in KB/s) to limit upload speeds to'
+        EQUALITY integerMatch        
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )
+
+attributetype ( 1.3.6.1.4.1.6981.11.3.6 NAME 'FTPDownloadBandwidth'
+        DESC 'Bandwidth (in KB/s) to limit download speeds to'
+        EQUALITY integerMatch        
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )
+
+attributetype ( 1.3.6.1.4.1.6981.11.3.7 NAME 'FTPStatus'
+        DESC 'Account status: enabled or disabled'
+        EQUALITY caseIgnoreIA5Match
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE )
+
+attributetype ( 1.3.6.1.4.1.6981.11.3.8 NAME 'FTPuid'
+        DESC 'System uid (overrides uidNumber if present)'
+        EQUALITY integerMatch
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )
+
+attributetype ( 1.3.6.1.4.1.6981.11.3.9 NAME 'FTPgid'
+        DESC 'System uid (overrides gidNumber if present)'
+        EQUALITY integerMatch
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE )
+
+attributetype ( 1.3.6.1.4.1.6981.11.3.10 NAME 'FTPHomeDir'
+        DESC 'FTP directory'
+        EQUALITY caseIgnoreIA5Match
+        SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 SINGLE-VALUE )
+
+## New Pure-FTPd object type
+
+objectclass ( 1.3.6.1.4.1.6981.11.2.3 NAME 'PureFTPdUser'
+        DESC 'PureFTPd user with optional quota, throttling and ratio'
+        SUP top AUXILIARY
+        MAY ( FTPStatus $ FTPQuotaFiles $ FTPQuotaMBytes $ FTPUploadRatio $ 
+              FTPDownloadRatio $ FTPUploadBandwidth $ FTPDownloadBandwidth $
+              FTPuid $ FTPgid $ FTPHomeDir ) )

extra/samples/pureftp/ldap.conf

+
+#############################################
+#                                           #
+# Sample Pure-FTPd LDAP configuration file. #
+# See README.LDAP for explanations.         #
+#                                           #
+#############################################
+
+
+# Optional : name of the LDAP server. Default : localhost
+
+#LDAPServer ldap.c9x.org
+LDAPServer localhost
+
+# Optional : server port. Default : 389
+
+LDAPPort   389
+
+
+# Mandatory : the base DN to search accounts from. No default.
+
+#LDAPBaseDN cn=Users,dc=c9x,dc=org
+LDAPBaseDN o=domains,dc=example,dc=com
+
+# Optional : who we should bind the server as.
+#            Default : binds anonymously
+
+#LDAPBindDN cn=Manager,dc=c9x,dc=org
+LDAPBindDN cn=vmail,dc=example,dc=com
+
+# Password if we don't bind anonymously
+# This configuration file should be only readable by root
+
+#LDAPBindPW r00tPaSsw0rD
+LDAPBindPW xjlE6sfKWy6CNmVXIfa4iwkmun0MTJ
+
+# Optional : default UID, when there's no entry in an user object
+
+# LDAPDefaultUID 500
+LDAPDefaultUID 1000
+
+# Optional : default GID, when there's no entry in an user object
+
+# LDAPDefaultGID 100
+LDAPDefaultGID 1000
+
+# Filter to use to find the object that contains user info
+# \L is replaced by the login the user is trying to log in as
+# The default filter is (&(objectClass=posixAccount)(uid=\L))
+
+# LDAPFilter (&(objectClass=posixAccount)(uid=\L))
+LDAPFilter (&(objectClass=PureFTPdUser)(mail=\L)(FTPStatus=enabled))
+
+# Attribute to get the home directory
+# Default is homeDirectory (the standard attribute from posixAccount)
+
+# LDAPHomeDir homeDirectory
+LDAPHomeDir FTPHomeDir
+
+# LDAP protocol version to use
+# Version 3 (default) is mandatory with recent releases of OpenLDAP.
+
+# LDAPVersion 3
+LDAPVersion 3

extra/trackLastLogin.sh

+#!/bin/sh
+
+# =========================================================
+# Author:   Zhang Huangbin (michaelbibby@gmail.com)
+# Date:     2009.07.28
+# Purpose:  Track user last login date & ip address with Dovecot.
+# Project:  iRedMail open source mail server solution.
+#           http://www.iredmail.org/
+# =========================================================
+
+# $USER -> login username. It should be a valid email address.
+# $IP   -> remote ip address (IPv4).
+# ${1}  -> mail protocol: imap, pop3
+
+# ------------------------------------------------------------------
+# Update to plain text file..
+# Note: user 'dovecot' should have write permission on this file.
+# ------------------------------------------------------------------
+#echo "$(date +%Y.%m.%d-%H:%M:%S), $USER, $IP, ${1}" >> /tmp/tracking.log 2>&1
+
+# ------------------------------------------------------------------
+# Update to MySQL database.
+# Note: ${MYSQL_USER} must have SELECT and UPDATE privileges.
+# ------------------------------------------------------------------
+#MYSQL_USER='vmailadmin'
+#PASSWD='plain_passwd'
+#VMAIL_DB_NAME='vmail'
+#
+#if [ X"${USER}" != X"dump-capability" ]; then
+#   mysql -u${MYSQL_USER} -p${PASSWD} ${VMAIL_DB_NAME} >/dev/null 2>&1 <<EOF
+#       UPDATE mailbox SET \
+#       lastloginipv4=INET_ATON('$IP'), \
+#       lastlogindate=NOW(), \
+#       lastloginprotocol="${1}" \
+#       WHERE username='$USER';
+#EOF
+#fi
+
+# ------------------------------------------------------------------
+# Update to LDAP (OpenLDAP) directory server.
+# ------------------------------------------------------------------
+# Convert username to LDAP dn.
+# -c         continuous operation mode (do not stop on errors)
+# -x            Simple authentication
+# -H URI        Uniform Resource Identifier(s)
+# -D binddn     Bind dn. Default is 'cn=vmailadmin,dc=iredmail,dc=org'
+# -w bindpw     Bind password (for simple authentication)
+
+LDAP_URI='ldap://127.0.0.1:389'
+LDAP_BASEDN='o=domains,dc=iredmail,dc=org'
+BIND_DN='cn=vmailadmin,dc=iredmail,dc=org'
+BIND_PW='plain_passwd'
+
+if [ X"${USER}" != X"dump-capability" ]; then
+    ldapmodify -c -x \
+        -H "${LDAP_URI}" \
+        -D "${BIND_DN}" \
+        -w "${BIND_PW}" >/dev/null 2>&1 <<EOF
+dn: mail=${USER},ou=Users,domainName=$(echo ${USER} | awk -F'@' '{print $2}'),${LDAP_BASEDN}
+changetype: modify
+replace: lastLoginDate
+lastLoginDate: $(date +%Y%m%d%H%M%SZ)
+-
+replace: lastLoginIP
+lastLoginIP: ${IP}
+-
+replace: lastLoginProtocol
+lastLoginProtocol: ${1}
+EOF
+
+fi
+
+# Execute POP3/IMAP process.
+if [ -f /etc/redhat-release ]; then
+    # RHEL/CentOS.
+    exec /usr/libexec/dovecot/${1} $*
+elif [ -f /etc/debian_version ]; then
+    # Debian & Ubuntu:
+    exec /usr/lib/dovecot/${1} $*
+fi

extra/update/updateLDAPValues_050_to_051.py

+#!/usr/bin/env python
+# encoding: utf-8
+
+# Author:   Zhang Huangbin <michaelbibby (at) gmail.com>
+# Purpose:  Add three new services name in 'enabledService' attribute.
+#           Required in iRedMail-0.5.1.
+
+import sys
+import ldap
+
+# Note:
+#   * bind_dn must have write privilege on LDAP server.
+uri = 'ldap://127.0.0.1:389'
+basedn = 'o=domains,dc=iredmail,dc=org'
+bind_dn = 'cn=vmailadmin,dc=iredmail,dc=org'
+#bind_dn = 'cn=Manager,dc=iredmail,dc=org'
+bind_pw = 'passwd'
+
+# Initialize LDAP connection.
+conn = ldap.initialize(uri=uri, trace_level=0,)
+
+# Bind.
+conn.bind_s(bind_dn, bind_pw)
+
+# Get all mail users.
+allUsers = conn.search_s(
+        basedn,
+        ldap.SCOPE_SUBTREE,
+        "(objectClass=mailUser)",
+        ['dn', 'mail', 'enabledService'],
+        )
+
+# Debug.
+#print >> sys.stderr, allUsers
+
+# Values which need to be added.
+services = ['pop3secured', 'imapsecured', 'managesievesecured',]
+
+# Counter.
+count = 1
+
+for user in allUsers:
+    dn = user[0]
+    mail = user[1]['mail'][0]
+    enabledService = user[1]['enabledService']
+
+    # Get missing values.
+    values = [ s for s in services if s not in enabledService ]
+
+    # Update it if there are something missed..
+    if len(values) != 0:
+        print >> sys.stderr, """Updating user (%d): %s""" % (count, mail)
+
+        mod_attrs = [ (ldap.MOD_ADD, 'enabledService', values) ]
+        conn.modify_s(dn, mod_attrs)
+
+        count += 1
+
+# Unbind connection.
+conn.unbind()
+
+print >> sys.stderr, 'Updated.'

extra/update/updateLDAPValues_051_to_060.py

+#!/usr/bin/env python
+# encoding: utf-8
+
+# Author:   Zhang Huangbin <zhb@iredmail.org>
+# Purpose:  Add three new services name in 'enabledService' attribute.
+#           Required in iRedMail-0.6.0.
+# Date:     2010-05-31
+
+import sys
+import ldap
+
+# Note:
+#   * bind_dn must have write privilege on LDAP server.
+uri = 'ldap://127.0.0.1:389'
+basedn = 'o=domains,dc=iredmail,dc=org'
+bind_dn = 'cn=vmailadmin,dc=iredmail,dc=org'
+bind_pw = 'passwd'
+
+# Initialize LDAP connection.
+print >> sys.stderr, "* Connecting to LDAP server: %s" % uri
+conn = ldap.initialize(uri=uri, trace_level=0,)
+conn.bind_s(bind_dn, bind_pw)
+
+# Get all mail users.
+print >> sys.stderr, "* Get all mail accounts..."
+allUsers = conn.search_s(
+        basedn,
+        ldap.SCOPE_SUBTREE,
+        "(objectClass=mailUser)",
+        ['dn', 'mail', 'enabledService', 'objectClass',],
+        )
+
+total = len(allUsers)
+print >> sys.stderr, "* Total %d user(s)." % (total)
+
+# Values of 'enabledService' which need to be added.
+services = ['sieve', 'sievesecured', 'internal',]
+
+# Counter.
+count = 1
+
+for user in allUsers:
+    dn = user[0]
+    mail = user[1]['mail'][0]
+    enabledService = user[1]['enabledService']
+    objectClasses = user[1]['objectClass']
+
+    # Get missing values.
+    values = [s for s in services if s not in enabledService]
+
+    mod_attrs = []
+
+    # Add missing values of 'enabledService'.
+    if len(values) > 0:
+        mod_attrs += [(ldap.MOD_ADD, 'enabledService', values)]
+
+    # Add missing values of 'objectClass'.
+    if 'amavisAccount' not in objectClasses:
+        mod_attrs += [(ldap.MOD_ADD, 'objectClass', 'amavisAccount')]
+
+    # Update.
+    if len(mod_attrs) > 0:
+        print >> sys.stderr, "* Updating user (%d/%d): %s" % (count, total, mail)
+        conn.modify_s(dn, mod_attrs)
+    else:
+        print >> sys.stderr, "* Updating user (%d/%d): %s. [SKIP. No update required.]" % (count, total, mail)
+
+    count += 1
+
+# Unbind connection.
+print >> sys.stderr, "* Unbind LDAP server."
+conn.unbind()
+
+print >> sys.stderr, "* Update completed."

extra/update/updateLDAPValues_061_to_070.py

+#!/usr/bin/env python
+# encoding: utf-8
+
+# Author:   Zhang Huangbin <zhb@iredmail.org>
+# Purpose:  Add three service name in 'enabledService' attribute.
+#           Required in iRedMail-0.7.0.
+# Date:     2011-01-28
+
+import sys
+import ldap
+
+# Note:
+#   * bind_dn must have write privilege on LDAP server.
+uri = 'ldap://127.0.0.1:389'
+basedn = 'o=domains,dc=iredmail,dc=org'
+bind_dn = 'cn=vmailadmin,dc=iredmail,dc=org'
+bind_pw = 'passwd'
+
+# Initialize LDAP connection.
+print >> sys.stderr, "* Connecting to LDAP server: %s" % uri
+conn = ldap.initialize(uri=uri, trace_level=0,)
+conn.bind_s(bind_dn, bind_pw)
+
+# Get all mail users.
+print >> sys.stderr, "* Get all mail accounts..."
+allUsers = conn.search_s(
+        basedn,
+        ldap.SCOPE_SUBTREE,
+        "(objectClass=mailUser)",
+        ['dn', 'mail', 'enabledService', 'objectClass',],
+        )
+
+total = len(allUsers)
+print >> sys.stderr, "* Total %d user(s)." % (total)
+
+# Values of 'enabledService' which need to be added.
+services = ['smtpsecured']
+
+# Counter.
+count = 1
+
+for user in allUsers:
+    (dn, entry) = user
+    mail = entry['mail'][0]
+    if entry.has_key('enabledService'):
+        enabledService = entry['enabledService']
+    else:
+        continue
+    objectClasses = entry['objectClass']
+
+    # Get missing values.
+    values = [str(s).lower() for s in services if s not in enabledService]
+
+    mod_attrs = []
+
+    # Add missing values of 'enabledService'.
+    if len(values) > 0:
+        mod_attrs += [(ldap.MOD_ADD, 'enabledService', values)]
+
+    # Add missing values of 'objectClass'.
+    if 'amavisAccount' not in objectClasses:
+        mod_attrs += [(ldap.MOD_ADD, 'objectClass', 'amavisAccount')]
+
+    # Update.
+    if len(mod_attrs) > 0:
+        print >> sys.stderr, "* Updating user (%d/%d): %s" % (count, total, mail)
+        conn.modify_s(dn, mod_attrs)
+    else:
+        print >> sys.stderr, "* Updating user (%d/%d): %s. [SKIP. No update required.]" % (count, total, mail)
+
+    count += 1
+
+# Unbind connection.
+print >> sys.stderr, "* Unbind LDAP server."
+conn.unbind()
+
+print >> sys.stderr, "* Update completed."

extra/update/updateLDAPValues_072_to_073.py

+#!/usr/bin/env python
+# encoding: utf-8
+
+# Author:   Zhang Huangbin <zhb@iredmail.org>
+# Purpose:  Add enabledService=lda for all mail users.
+#           Required in iRedMail-0.7.3.
+# Date:     2011-07-12
+
+import sys
+import ldap
+
+# Note:
+#   * bind_dn must have write privilege on LDAP server.
+uri = 'ldap://127.0.0.1:389'
+basedn = 'o=domains,dc=iredmail,dc=org'
+bind_dn = 'cn=vmailadmin,dc=iredmail,dc=org'
+bind_pw = 'passwd'
+
+# Initialize LDAP connection.
+print >> sys.stderr, "* Connecting to LDAP server: %s" % uri
+conn = ldap.initialize(uri=uri, trace_level=0,)
+conn.bind_s(bind_dn, bind_pw)
+
+# Get all mail users.
+print >> sys.stderr, "* Get all mail accounts..."
+allUsers = conn.search_s(
+        basedn,
+        ldap.SCOPE_SUBTREE,
+        "(objectClass=mailUser)",
+        ['dn', 'mail', 'enabledService', 'objectClass',],
+        )
+
+total = len(allUsers)
+print >> sys.stderr, "* Total %d user(s)." % (total)
+
+# Values of 'enabledService' which need to be added.
+services = ['lda']
+
+# Counter.
+count = 1
+
+for user in allUsers:
+    (dn, entry) = user
+    mail = entry['mail'][0]
+    if entry.has_key('enabledService'):
+        enabledService = entry['enabledService']
+    else:
+        continue
+    objectClasses = entry['objectClass']
+
+    # Get missing values.
+    values = [str(s).lower() for s in services if s not in enabledService]
+
+    mod_attrs = []
+
+    # Add missing values of 'enabledService'.
+    if len(values) > 0:
+        mod_attrs += [(ldap.MOD_ADD, 'enabledService', values)]
+
+    # Update.
+    if len(mod_attrs) > 0:
+        print >> sys.stderr, "* (%d of %d) Updating user: %s" % (count, total, mail)
+        conn.modify_s(dn, mod_attrs)
+    else:
+        print >> sys.stderr, "* (%d of %d) [SKIP] No update required: %s" % (count, total, mail)
+
+    count += 1
+
+# Unbind connection.
+print >> sys.stderr, "* Unbind LDAP server."
+conn.unbind()
+
+print >> sys.stderr, "* Update completed."

extra/updateLDAPQuota.py

+#!/usr/bin/env python
+# encoding: utf-8
+
+# Author:   Zhang Huangbin <michaelbibby (at) gmail.com>
+# Purpose:  Add three new services name in 'enabledService' attribute.
+#           Required in iRedMail-0.5.1.
+
+import sys
+import ldap
+
+# Note:
+#   * bind_dn must have write privilege on LDAP server.
+uri = 'ldap://127.0.0.1:389'
+basedn = 'o=domains,dc=iredmail,dc=org'
+bind_dn = 'cn=vmailadmin,dc=iredmail,dc=org'
+bind_pw = 'passwd'
+
+new_quota = 2048   # quota size in MB
+
+# Convert quota to KB.
+quota = str(int(new_quota) * 1024 * 1024)
+
+# Initialize LDAP connection.
+conn = ldap.initialize(uri=uri, trace_level=0,)
+
+# Bind.
+conn.bind_s(bind_dn, bind_pw)
+
+# Get all mail users.
+allUsers = conn.search_s(
+        basedn,
+        ldap.SCOPE_SUBTREE,
+        "(objectClass=mailUser)",
+        ['mail', 'mailQuota', ],
+        )
+
+# Debug.
+#print >> sys.stderr, allUsers
+
+# Counter.
+count = 1
+
+for user in allUsers:
+    dn = user[0]
+    mail = user[1]['mail'][0]
+    cur_quota = user[1].get('mailQuota', ['unlimited'])[0]
+
+    print >> sys.stderr, """Updating user (%d): %s, %s""" % (count, mail, cur_quota)
+
+    mod_attrs = [ (ldap.MOD_REPLACE, 'mailQuota', quota) ]
+    try:
+        conn.modify_s(dn, mod_attrs)
+    except Exception, e:
+        print >> sys.stderr, str(e)
+
+    count += 1
+
+# Unbind connection.
+conn.unbind()
+
+print >> sys.stderr, 'Updated.'

extra/updateUserPasswordsUnderDomain.py

+#!/usr/bin/env python
+# encoding: utf-8
+
+# Author:   Zhang Huangbin <michaelbibby (at) gmail.com>
+# Purpose:  Change password of ALL users under domain.
+
+# Usage:
+#   - Change LDAP related settings below:
+#       + uri
+#       + basedn
+#       + bind_dn
+#       + bind_pw
+#   - Run this script with domain name and new password:
+#
+#       # python updateUserPasswordsUnderDomain.py DOMAIN_NAME NEW_PASSWD
+#
+
+import sys
+import ldap
+
+domain = sys.argv[1]
+newpw = sys.argv[2]
+
+# Note:
+#   * bind_dn must have write privilege on LDAP server.
+uri = 'ldap://127.0.0.1:389'
+basedn = 'ou=Users,domainName=%s,o=domains,dc=iredmail,dc=org' % sys.argv[1]
+bind_dn = 'cn=vmailadmin,dc=iredmail,dc=org'
+bind_pw = 'A807AiXxdjJ7CQWWORc49RIbub0W4d'
+
+# Initialize LDAP connection.
+conn = ldap.initialize(uri=uri, trace_level=0,)
+
+# Bind.
+conn.bind_s(bind_dn, bind_pw)
+
+# Get all mail users.
+allUsers = conn.search_s(
+        basedn,
+        ldap.SCOPE_SUBTREE,
+        "(objectClass=mailUser)",
+        ['mail', 'userPassword',],
+        )
+
+# Debug.
+#print >> sys.stderr, allUsers
+
+# Counter.
+count = 1
+
+for user in allUsers:
+    dn = user[0]
+    mail = user[1]['mail'][0]
+
+    try:
+        #conn.modify_s(dn, [(ldap.MOD_ADD, 'userPassword', '')])
+        conn.passwd_s(dn, None, newpw)
+        print >> sys.stderr, """Updated user (%d): %s""" % (count, mail)
+    except ldap.TYPE_OR_VALUE_EXISTS:
+        pass
+    except Exception, e:
+        print >> sys.stderr, """Error while updating user (%s): %s""" % (mail, str(e))
+
+    count += 1
+
+# Unbind connection.
+conn.unbind()
+
+print >> sys.stderr, 'Updated.'

iRedMail/ChangeLog

+iRedMail-0.7.3:
+    * Add enabledService=lda for newly created LDAP mail user. Required by
+      Dovecot 2.x.
+    * Works on CentOS 6.0, RHEL 6.x, Scientific Linux 6.x.
+    * Mbox format mailbox is not supported anymore.
+    * Add smtp-amavis_destination_recipient_limit=1 in Postfix for concurrency
+      per-recipient limit. Thanks beez <jason@indo.net.id>.
+    * Package update:
+        + iRedAdmin -> 0.1.6
+        + phpMyAdmin -> 3.4.3.1
+
+iRedMail-0.7.2:
+    * Works on Ubuntu 11.04.
+    * Enable LDAPS on FreeBSD by default. Thanks Markus Wyrsch <W-Chi@>.
+    * Improvements:
+        + Add alias domain support in postfix virtual_mailbox_domains (MySQL
+          backend special).
+    * Fixed:
+        + Set 'ServerTokens' to 'ProductOnly' in Apache on Debian/Ubuntu.
+          Thanks c33s@forum.
+    * Package update:
+        + Roundcube webmail -> 0.5.3
+        + phpLDAPadmin -> 1.2.1.1
+        + phpMyAdmin -> 3.4.1
+        + iRedAPD -> 1.3.6. Fix two issues for MySQL backend.
+        + iRedAdmin -> 0.1.5. Security fix edition.
+
+iRedMail-0.7.1:
+    * Fix incorrect icon path in awstats. Thanks <rannal@> for the feedback.
+    * Use 2048 as default SSL key length. Thanks mike.f@forum <m.fresel@>.
+    * Increase Postfix timeout seconds: smtp_data_init_timeout (120s -> 240s),
+      and smtp_data_xfer_timeout (180s -> 600s). Hope to avoid some timeout
+      issues. Thanks write4saini@forum, mbsouth@forum.
+    * Integrate Fail2ban. Note: It doesn't work on FreeBSD yet.
+    * Support domain alias in postfix relay_domains (MySQL backend special).
+      Thanks atros@forum.
+    * Support domain alias in mail alias, catch-all account.
+    * Package update/changes:
+        + Roundcube -> 0.5.2
+        + iRedAPD -> 1.3.5
+
+iRedMail-0.7.0:
+    * Append '-f /path/to/slapd.conf' to slapcat in tools/backup_openldap.sh.
+      Thanks Enrico Cotti <enrico.cotti@>.
+    * Save date of password last change while updating password in roundcube.
+
+iRedMail-0.7.0-rc3:
+    * Make IMAP share folder work with LDAP backend. Thanks alexp@forum.
+    * Update phpMyAdmin to 3.3.10.
+
+iRedMail-0.7.0-rc2:
+    * Check domain status in dovecot MySQL lookup and postfix
+      virtual_mailbox_maps, virtual_alias_maps, sender_login_maps, per-user
+      transport_maps, per-user sender_bcc_maps and recipient_bcc_maps (MySQL
+      backend).
+
+iRedMail-0.7.0-rc1:
+    * Make catch-all account work as expected with MySQL backend.
+    * Create indexes for some columns in MySQL backend.
+
+iRedMail-0.7.0-beta6:
+    * Enable iRedAPD for MySQL backend. Used for mail alias deliver
+      restrictions. Reference:
+      http://www.iredmail.org/wiki/index.php?title=Install/iRedAPD/MySQL
+
+iRedMail-0.7.0-beta5:
+    * Reverse Amavisd LDAP query base dn.
+    * Install python-xml on OpenSuSE 11.4.
+
+iRedMail-0.7.0-beta4:
+    * Works on OpenSuSE 11.4.
+    * Improvements:
+        + Alias domain support for catchall account in LDAP backend.
+
+    * Package update/changes:
+        + phpMyAdmin -> 3.3.9.2.
+
+iRedMail-0.7.0-beta3:
+    * New features:
+        + Enable personal LDAP address book for OpenLDAP backend.
+        + New column for MySQL backend: domain.defaultpasswordscheme. Used
+          to store per-domain password scheme.
+
+    * Improvements:
+        + Check domain status in virtual_mailbox_maps, virtual_alias_maps
+          for MySQL backend.
+        + Don't allow user to view ldap attributes: domainAdmin,
+          domainGlobalAdmin.
+
+    * Fixed:
+        + Remove unique index (primary key) on table amavisd.msgrcpt to avoid
+          duplicate entries.
+        + Incorrect path of phpLDAPadmin on Ubuntu 10.04.x/10.10.x.
+          Thanks xulingyun@bbs for the feedback.
+
+    * Package update/changes:
+        + PostfixAdmin -> Removed.
+        + iRedAdmin -> 0.1.4.
+        + Roundcube webmail -> 0.5.1. Remove 3rd-party plugin: imap_acl.
+
+iRedMail-0.7.0-beta2:
+    * Improvements:
+        + Auto create default IMAP folders with dovecot plugin: autocreate.
+        + Add plugin 'imap_acl' for roundcube to let users manage their
+          mailbox sharing, but disabled by default.
+        + Mailbox sharing support with dovecot 1.2. Disabled by default.
+        + Show realtime quota usage with dovecot-1.2 dict quota in
+          PostfixAdmin.
+        + Don't quarantine mails with bad header in Amavisd.
+          '$bad_header_quarantine_method=undef;'
+        + Increase dovecot "mail_process_size" to 1024MB by default. Hope to
+          avoid a dovecot "out of memory" issue when processing large mailbox.
+          Thanks James Kong.
+        + Enable whitelising sender (WHITELISTSENDER=1) in policyd by default.
+    * Fixed:
+        + Make sure apache wsgi module is loaded on RHEL/CentOS.
+          Thanks Murat Uğur Eminoğlu for the feedback.
+        + Fix incorrect file localtion of php.ini on OpenSuSE.
+    * Package Update:
+        + Roundcube webmail -> 0.5
+        + phpMyAdmin -> 3.3.9.1
+
+iRedMail-0.7.0-beta1:
+    * Works on OpenSuSE 11.3. Tested on 11.3, but it should work well on
+      11.2, 11.1 too.
+    * Improvements:
+        + Store realtime quota usage in MySQL with Dovecot-1.2. Reference:
+          http://www.iredmail.org/wiki/index.php?title=IRedMail/FAQ/Store.Realtime.Quota.In.MySQL
+        + Use repository 'backports.debian.org' on Debian 5.
+        + Bypass shadow address in postfix sender login checking.
+        + Improve postfix ldap lookup to make mail list of alias domain work.
+          Thanks for Andrea Di Dato's feedback and testing.
+        + Integrate MySQL in Amavisd: @storage_sql_dsn.
+        + Improve backup mx support with MySQL backend. Thanks tiangangnet@bbs
+        + Replaced ldap attribute:
+            - gn (old) -> givenName
+            - fax (old) -> facsimileTelephoneNumber
+    * New backup scripts: tools/backup_openldap.sh, tools/backup_mysql.sh.
+      Reference: http://www.iredmail.org/wiki/index.php?title=IRedMail/FAQ/Backup
+    * Upgrade packages:
+        + Dovecot -> 1.2.x. On RHEL/CentOS & Debian 5 (with backports).
+        + PostfixAdmin -> 2.3.2
+        + phpMyAdmin -> 3.3.7
+        + Roundcube webmail -> 0.4.2
+    * Fixed:
+        + Fix incorrect file location of awstats.pl on Debian/Ubuntu.
+
+iRedMail-0.6.1:
+    * Add missing mail log files (mail.info, mail.err, mail.warn) in logrotate.
+      Thanks to BigMichi1@forum.
+    * Catch-all account support in MySQL backend.
+    * Run iRedAdmin as a low privilege user (iredadmin).
+    * Improve Ubuntu 10.04 support.
+    * Update iRedAPD to 1.3.3. Run iRedAPD as a low privilege user (iredapd).
+
+iRedMail-0.6.0:
+    * Disallow to use multiple identities in postfix and roundcube.
+    * Update iRedAPD to 1.3.0.
+    * Add missing table on Debian 5 and Ubuntu 9.04:
+      postfixpolicyd.blacklist_dnsname.
+    * Upgrade phpMyAdmin to 2.11.10.
+    * Add 'enableinternal=1' in vmail.mailbox and 'enabledService: internal'
+      in OpenLDAP.
+    * Not allow to login with shadow address. It may cause login failed due
+      to duplicate ldap query result (normal user, another normal user with
+      shadow address).
+    * Fix shabang line of dovecot quota warning script. Thanks Alex Stanciu.
+    * Fix loading awstats issue on FreeBSD. Thanks dbetts22@forum.
+    * New LDAP attributes: mailWhitelistRecipient, mailBlacklistRecipient.
+      Used for per-user recipient restrictions.
+    * Fix: freshclam can't start after update to 0.96. Fixed by removing inline
+      comment in freshclam setting. Thanks wildweasel@forum.