====== Ubuntu - Exim4 - Install a full mail server for multi-user hosting environments ====== Mail Server with Exim 4, Dovecot, MySQL and SpamAssassin ===== Introduction ===== How to set up an e-mail server for shared hosting environments on a system with a fixed IP address. The aim of this document is to create a system that has the following characteristics: * Receive and store mail for users, including SSL, as well as through the Message Submission protocol * Allow users to retrieve messages via IMAP and POP3 (also SSL) * Provide a webmail service * Reject or at least minimize spam mails * Accessibility via IPv6 * A backup MX for more fail-protection The original Exim configuration is based on information from http://www.xmn-berlin.de/~marte/exim/exim4_mysql_amavis_spamassasin.html , the structure of this document is based on the [[http://workaround.org/ispmail/lenny|ISP mail]] tutorial by C. Haas. Usually it is a setup on one, or more, [[http://developer.gauner.org/rootserver-raid-etch/|root servers]]. **NOTE**: For a postfix installation see: http://developer.gauner.org/ispmail-vboxadm-squeeze/ The following techniques and protocols will be touched during the setup, so you should be thoroughly familiar with them. * An [[https://en.wikipedia.org/wiki/SQL|SQL]] database is used for user information. * [[https://en.wikipedia.org/wiki/Simple_Mail_Transfer_Protocol|SMTP]], for the receipt and delivery of mails. * [[https://en.wikipedia.org/wiki/Post_Office_Protocol|POP3]] and [[https://de.wikipedia.org/wiki/Internet_Message_Access_Protocol|IMAP]] for retrieving mail. * Exim configuration, whereby my configuration should be adopted with minor adjustment. * [[https://www.debian.org/|Debian GNU / Linux]], package management, administration, etc. ---- ===== Components ===== This configuration builds on the following components, almost all are contained as Debian packages in the official repositories: * [[http://packages.debian.org/etch/exim4-daemon-heavy|Exim4]], accepts mail from the Internet via SMTP counter and allows it to send mails authenticated users * [[http://packages.debian.org/etch/dovecot-common|Dovecot]], represents the mailboxes on the server using POP3 and IMAP for retrieval * [[http://packages.debian.org/etch/mysql-server-5.0|MySQL]], manages the user information * [[http://packages.debian.org/etch/spamassassin|SpamAssassin]], rated an upcoming news on a point system to the spam content. * [[http://packages.debian.org/etch/greylistd|Greylistd]], makes many simple-minded * (Optional) Apache 2, for Webmail * (Optional) [[http://www.roundcube.net/|Roundcube]] Webmail * (Optional) Administration of the mailboxes via a web browser ---- ===== Administration of virtual domains and addresses ===== On classic UNIX systems, exactly one hostname (e.g. server) is assigned to a system (e.g. sharewiz.net), which is followed by an FQDN (fully qualified domain name) (e.g. server1.sharewiz.net). The user accounts existing on this system form together with the FQDN and a @ as a separator the public email address. So something like john @ sharewiz. net . On these systems, the incoming messages are usually stored under /var/mail/user or in the user's home. Since the users on a classic web hosting system but no system accounts should have this approach is in this case impractical. Many hosters prefer to store the user accounts in a database, which is something like MySQL, PostgreSQL or LDAP. Since these users are not known to the system, one has to teach the mailserver. One approach would be to enter user accounts manually into a text file. Since this would be too complicated and too time-consuming, it is desirable that the mailserver can query the user database in real time in order to read the user accounts. In addition, the mailserver still needs a database of the domains for which it is responsible. It is suitable for storing these in the same format as the user data. ^id^domain^active^server^ |0|domain.de|yes|1| |1|domain.com|no|2| |2|domain.net|yes|1| |3|server.tld|yes|3| |n|...|...|...| Since the database in this setup stores only the information about the mailboxes, but not the mails, the mailserver still needs information about the location of the mailbox in the file system. There are two popular formats for storing mailboxes - and a few not so widely used - formats. This is on the one hand the classic Mbox format and the somewhat newer Maildir format. Both formats have advantages and disadvantages, I prefer here Maildir. Among other things because it cooperates better with my backup system. I use an incremental backup that builds on rsync. Since the Mbox format stores all messages of a mailbox in a file, this would mean that the entire mailbox would be saved again if the changes were minor. Maildir saves me here simply storage space. There is the developer of Dovecot a new format with the name dbox which resembles the Maildir. This format is still very new, but an interesting option for the future. The storage of the mailboxes takes place in my setup under the path /srv/mail/domain.tld/user. The structure of the path is given to Exim and Dovecot fixed in the configuration and the variable parts, i.e domain and user, are then supplemented at runtime by the information from the database. ^Virtual user^Location of the mailbox^ |john @ example. com|/srv/mail/example.com/john| |adam @ example. com|/srv/mail/example.com/adam| |bob @ example. com|/srv/mail/example.com/bob| The table hosts stores the information on the existing server. This can either be a single one, or several. ^server^FQDN^ |server1|server1.domain.tld| |server2|server2.domain.tld| ---- ===== Why MySQL? ===== Storing the data in an SQL database allows easy administration of the data via a Web front-end, which does not require extended privileges. MySQL was only chosen because it can be easily accessed by all relevant programs. It would also be possible to use PostgreSQL or another SQL database. ---- ===== Greylisting - Pros and Cons ===== There are many opposing opinions about greylisting. Some people praise it as a miracle against spam but others question its effectiveness and some users can not live with the resulting delays. The fact is that the spam load of my system has dropped by over 90% after the deployment. In the meantime it is observed, however, that more spam comes through the greylisting, but as long as I can still see a positive effect, I will continue to use Greylisting. Whilst the disadvantages of greylisting - delayed delivery and additional resource requirements - can interfere with the described set-up without problem even without greylisting. ---- ===== The database schemas ===== There are three relevant database schemas for storing user data and domains. Two of these are used to store the domains responsible, one for the information about the mailboxes and the forwarding. As far as the database schema is concerned, one is basically very flexible. It would also be possible to use separate schemes for mailboxes and forwarding and to store the domains in a database. mail_accounts: ^field^Type^description^ |id|int(9)|Primary key auto_increment,| |local_part|varchar(255)|The user part of the address| |domain|int(16)|The domain part of the address, points to the table domains| |forward|varchar(255)|The goal of forwarding| |cc|varchar(255)|All messages to this address are copied here| |name|varchar(255)|A custom name| |pwclear|varchar(255)|The password in the plain text| |pwcrypt|varchar(255)|The password in UNIX Crypt format| |is_away|enum('yes', 'no')|Auto-Responder active?| |away_text|enum ('yes', 'no')|Text for the auto responder| |spam_check|enum'yes', 'no')|Run SpamAssassin?| |spam_purge|enum('yes', 'no')|Delete spam mails directly?| |virus_check|enum('yes', 'no')|Run the virus scan?| |is_enabled|enum('yes', 'no')|Account active?| |created_at|int(16)|Time stamp of creation| |updated_at|int(16)|Time stamp of the last modification| domains: ^field^Type^description^ |id|int(16)|Primary key auto_increment,| |domain|varchar(255)|Domain name (FQDN)| |is_enabled|enum('yes', 'no')|Active?| |mail_host|int(16)|The responsible mailserver| |created_at|int(16)|Time stamp of creation| |updated_at|int(16)|Timestamp of the last modification| hosts: ^field^Type^description^ |id|int(16)|Primary key auto_increment,| |name|varchar(255)|Hostname| |fqdn|varchar(255)|Full name (FQDN)| |created_at|int(16)|Time stamp of creation| |updated_at|int(16)|Time stamp of the last modification| ---- ==== Setting up the environment ==== Before setting up the required packages, you should first ensure that your system has a correct host name. This can be set in the /etc/hostname and /etc/hosts files. If the hostname - fqdn command prints the correct, fully qualified hostname, then this setting is fine. The following entry would be incorrect: 192.168.0.1 server server.example.com The correct entry: 192.168.0.1 server.example.com server ---- ===== Create location ===== First, create the directory /srv/mail and give it proper access rights: mkdir -p /srv/mail chown mail:mail /srv/mail chmod 700 /srv/mail ---- ===== Install the required packages ===== Most of the required packages can be easily installed via Debian's package management. Manually only the webmailer and the management interface have to be installed. Since these two packages are written in PHP5, a web server - preferably Apache 2 - and a PHP5 installation are required. It is important in this context that the web server does not necessarily have to run on the mailserver system. It is therefore possible to set up a system which only acts as a mailserver. First, Exim4 is now installed with MySQL support: aptitude install exim4-daemon-heavy If the Mailserver also offer POP3 and IMAP we still need Dovecot with POP3 and IMAP support. aptitude install dovecot-imapd dovecot-pop3d It is also possible to support only one of the two protocols. If you do not have enough resources for an IMAP server, for example, then simply don't install **dovecot-imapd**. In the following, I assume that you want to support both protocols. If you want to run the database server on the same system, install the corresponding package: aptitude install mysql-server-5.0 In my experience, there is nothing against it. However, if you already have a powerful database server in your network, it may make sense to use it instead. Then of course the installation of this package is omitted. If you want to use SpamAssassin to classify incoming mail, install the following packages: aptitude install pyzor razor spamassassin spamc dcc-client Here are the packages pyzor, razor and dcc-client optional, but can thereby recognition performance will be greatly improved. If you want to use greylisting, you still need the Greylistd package: aptitude install greylistd If you want to install the PHP-based packages, you should install the Apache webserver and PHP5. aptitude install libapache2-mod-php5 php5-mysql phpmyadmin The package **libapache2-mod-php5** draws on its dependencies automatically by the Apache web server with the appropriate (prefork) Worker. PhpMyAdmin is completely optional, but it can make setting up and managing the database much easier. In order to secure the connections of the mail server, the OpenSSL package is also required to generate the appropriate certificates: aptitude install openssl ---- ===== Connection to the database ===== The corresponding connection information must be communicated to each of the programs involved, which requires access to the database. First, however, the database and the users must be created. After installing the database, MySQL root allows you to log in without a password. You should change it. mysql -uroot After that you should get a MySQL console, where you can set a password for root with the following command. SET PASSWORD = PASSWORD('yourcomplicatedpassword'); Remember to change the password. Do not use the password suggested here, but a good and secure password that you can remember. Now the database and a corresponding user must be created first. This is very easy via PhpMyAdmin or alternatively by hand. mysql -uroot -p You are now prompted for the newly created root password. In the MySQL console, please create the database and a user. CREATE DATABASE maildb; GRANT ALL PRIVILEGES ON maildb. * TO 'maildb_user' @ 'localhost' IDENTIFIED BY 'password'; FLUSH PRIVILEGES; First, Exim is equipped with the database information. To do this, adjust the exim4.conf. The information is at the beginning of the file. # MySQL defines MYSQL_SERVER = localhost MYSQL_USER = DBUSER MYSQL_PASSWORD = DBPASS MYSQL_DB = DBNAME MYSQL_EMAILTABLE = mail_accounts MYSQL_DOMAINTABLE = domains MYSQL_HOSTTABLE = hosts # MySQL connection Hide mysql_servers = "MYSQL_SERVER / MYSQL_DB / MYSQL_USER / MYSQL_PASSWORD" Then Dovecot must know how to connect to the database. This information is entered in the dovecot-sql.conf. Driver = mysql Connect = host = localhost dbname = DBNAME user = DBUSER password = DBPASS ---- ===== Initialization of the database ===== After the database and the users are created, the database tables must now be created. To do this, simply import the given schemas. As described above, the mail_accounts table contains all information about the mailboxes and forwarding: CREATE TABLE IF NOT EXISTS `mail_accounts` ( `id` int(9) NOT NULL auto_increment, `local_part` varchar(255) NOT NULL default '', `domain` int(16) NOT NULL, `forward` varchar(255) NOT NULL, `cc` varchar(255) default NULL, `name` varchar(255) NOT NULL default '', `pwclear` varchar(255) NOT NULL default '', `pwcrypt` varchar(255) NOT NULL default '', `is_away` enum('yes', 'no') NOT NULL default 'no', `away_text` text, `spam_check` enum('yes', 'no') NOT NULL default 'no', `spam_purge` enum('yes', 'no') NOT NULL default 'no', `virus_check` enum('yes', 'no') NOT NULL default 'no', `is_enabled` enum('yes', 'no') NOT NULL default 'yes', `created_at` int(16) NOT NULL default '0', `updated_at` int(16) NOT NULL default '0', PRIMARY KEY (`id`), UNIQUE KEY `UNIQUE_EMAIL` (`domain`, `local_part`) ) ENGINE = InnoDB; ALTER TABLE `mail_accounts` ADD CONSTRAINT `mail_accounts_ibfk_1` FOREIGN KEY (`domain`) REFERENCES `domains` (`id`) ON DELETE CASCADE; The tables for the domains are almost identical: CREATE TABLE IF NOT EXISTS `domains` ( `id` int (16) NOT NULL auto_increment, `domain` varchar(255) NOT NULL, `is_enabled` enum('yes', 'no') NOT NULL, `mail_host` int(16) NOT NULL, `created_at` int(16) NOT NULL, `updated_at` int(16) NOT NULL, PRIMARY KEY (`id`), KEY `domain` (`domain`), KEY `mail_host` (`mail_host`) ) ENGINE = InnoDB; ALTER TABLE `domains` ADD CONSTRAINT `domains_ibfk_3` FOREIGN KEY (`mail_host`) REFERENCES `hosts` (`id`) ON DELETE CASCADE; The host table holds the assignments to the servers. CREATE TABLE IF NOT EXISTS `hosts` ( `id` int(16) NOT NULL auto_increment, `name` varchar(255) NOT NULL, `fqdn` varchar(255) NOT NULL, `notes` text NOT NULL, `created_at` int(16) NOT NULL, `updated_at` int(16) NOT NULL, PRIMARY KEY (`id`) ) ENGINE = InnoDB; The Foreign Key Constraints ensure that the database is always in a consistent state. If, for example, a domain is deleted, the database ensures that all dependent mail accounts are also removed. Or if a host is deleted, both the dependent domains and the accounts dependent on them are deleted. Therefore, be careful when deleting entries from the parent tables. ---- ===== Create database queries ===== The database queries for Exim are defined as macros so that they can be changed centrally and the remaining configuration files are not unnecessarily inflated. I will briefly go into the individual queries here. Of course, the SQL queries can be adjusted at will if a different database schema is used. Only the return values ​​must remain unchanged. The WHERE condition that polls the host is to be replaced or removed by an appropriate specification. This is because the setup is designed for the operation of several independent mail servers in a database. This means that it is possible to run several mail servers with their own domains and mailboxes with a database and an administrative interface. This feature is not discussed in the current version of this document. In the queries below, replace the placeholder 'HOST' with the name of the current host. This name must also exist in the host table. This query determines whether the user is marked as absent (leave notification): MYSQL_Q_ISAWAY = SELECT d.domain FROM MYSQL_EMAILTABLE AS ma, domains AS d, hosts AS h WHERE ma.domain = d.id AND d.mail_host = h.id AND ma.local_part = '${quote_mysql: $local_part}' AND d.domain = '${quote_mysql: $domain}' AND h.name = 'HOST' AND ma.is_away = 'yes' The AWAYTEXT query returns the matching absence message that is sent to the sender: MYSQL_Q_AWAYTEXT = SELECT ma.away_text FROM MYSQL_EMAILTABLE AS, MYSQL_DOMAINTABLE AS d, MYSQL_HOSTTABLE AS h WHERE ma.domain = d.id AND d.mail_host = h.id AND ma.local_part = '${quote_mysql: $local_part}' AND d.domain = '${quote_mysql: $domain}' AND h.name = 'HOST' This query returns a positive result if a given address has a forwarding target, which is an alias: MYSQL_Q_FORWARD = SELECT ma.forward FROM MYSQL_EMAILTABLE AS, MYSQL_DOMAINTABLE AS d, MYSQL_HOSTTABLE AS h WHERE ma.domain = d.id AND d.mail_host = h.id AND ma.local_part = '${quote_mysql: $local_part}' AND d.domain = '${quote_mysql: $domain}' AND h.name = 'HOST' AND ma.forward != '' AND ma.is_enabled = 'yes' The query CC returns the address to which a copy of the current message should go: MYSQL_Q_CC = SELECT cc FROM MYSQL_EMAILTABLE AS ma, MYSQL_DOMAINTABLE AS d, MYSQL_HOSTTABLE AS h WHERE ma.domain = d.id AND d.mail_host = h.id AND ma.local_part = '${quote_mysql: $ local_part}' AND d.domain = '${quote_mysql: $domain}' AND h.name = 'HOST' AND ma.is_enabled = 'yes' Probably the most frequently called query determines whether a given address is a local mailbox. This query is sent to each incoming message: MYSQL_Q_LOCAL = SELECT d.domain FROM MYSQL_EMAILTABLE AS, MYSQL_DOMAINTABLE AS d, MYSQL_HOSTTABLE AS h WHERE ma.domain = d.id AND d.mail_host = h.id AND ma.local_part = '${quote_mysql: $local_part}' AND d.domain = '${quote_mysql: $domain}' AND h.name = 'HOST' AND ma.is_enabled = 'yes' AND ma.forward = '' The same query for wildcards: MYSQL_Q_WCLOCAL = SELECT d.domain FROM MYSQL_EMAILTABLE AS ma, MYSQL_DOMAINTABLE AS d, MYSQL_HOSTTABLE AS h WHERE ma.domain = d.id AND d.mail_host = h.id AND ma.local_part = '*' AND d.domain = '${quote_mysql: $domain} 'AND h.name =' HOST 'AND ma.is_enabled =' yes' AND ma.forward = '' And the wildcard query again for forwarding: MYSQL_Q_WCLOCFW = SELECT d.domain FROM MYSQL_EMAILTABLE AS ma, MYSQL_DOMAINTABLE AS d, MYSQL_HOSTTABLE AS h WHERE ma.domain = d.id AND d.mail_host = h.id AND ma.local_part = '*' AND d.domain = '${quote_mysql: $domain} 'AND h.name =' HOST 'AND ma.is_enabled =' yes' AND ma.forward != '' Deactivated accounts are rejected at the beginning of the routing process and are therefore determined with their own query. The sender then receives a corresponding note: MYSQL_Q_DISABLED = SELECT d.domain FROM MYSQL_EMAILTABLE AS ma, MYSQL_DOMAINTABLE AS d, MYSQL_HOSTTABLE AS h WHERE ma.domain = d.id AND d.mail_host = h.id AND ma.local_part = '${quote_mysql: $local_part}' AND d.domain = '${quote_mysql: $domain}' AND h.name = 'HOST' AND ma.is_enabled = 'no' With the LDOMAIN query, the mail server determines which domains it is responsible for, i.e. which domains it delivers locally: MYSQL_Q_LDOMAIN = SELECT d.domain FROM MYSQL_DOMAINTABLE AS d, MYSQL_HOSTTABLE AS h WHERE d.mail_host = h.id AND h.name = 'HOST' AND d.domain = '${quote_mysql: $domain}' For all other domains in the database, messages are accepted but not delivered locally: MYSQL_Q_RDOMAIN = SELECT d.domain FROM MYSQL_DOMAINTABLE AS d, MYSQL_HOSTTABLE AS h WHERE d.mail_host = h.id AND h.name != 'HOST' AND d.domain = '${quote_mysql: $domain}' With the query **MYSQL_Q_BOXPATH** the path of the mailbox is determined. This query is only necessary if Dovecot omitted deliver: MYSQL_Q_BOXPATH = SELECT CONCAT (d.domain, '/', ma.local_part) AS boxpath FROM MYSQL_EMAILTABLE AS, MYSQL_DOMAINTABLE AS d, MYSQL_HOSTTABLE AS h WHERE ma.domain = d.id AND d.mail_host = h.id AND ma. Local_part = '${quote_mysql: $local_part}' AND d.domain = '${quote_mysql: $domain}' AND h.name = 'HOST' Since not all addresses may be checked for spam, e.g. if the customer does not want this or if this service is not included in his tariff, this is also queried: MYSQL_Q_SPAMC = SELECT d.domain FROM MYSQL_EMAILTABLE AS ma, MYSQL_DOMAINTABLE AS d, MYSQL_HOSTTABLE AS h WHERE ma.domain = d.id AND d.mail_host = h.id AND ma.local_part = '${quote_mysql: $local_part}' AND d.domain = '${quote_mysql: $domain}' AND h.name = 'HOST' AND ma.spam_check = 'yes' The option to delete spam directly is very dangerous, but the option is provided in the database schema and therefore accessible with a separate query. Whether you want to offer these options to users is up to you: MYSQL_Q_SPAMPURGE = SELECT d.domain FROM MYSQL_EMAILTABLE AS, MYSQL_DOMAINTABLE AS d, MYSQL_HOSTTABLE AS h WHERE ma.domain = d.id AND d.mail_host = h.id AND ma.local_part = '${quote_mysql: $local_part}' AND d.domain = '${quote_mysql: $domain}' AND h.name = 'HOST' AND ma.spam_purge = 'yes' The next three queries are used to authenticate the user for SMTP AUTH: MYSQL_Q_AUTHPLAIN = SELECT if (count (ma.id), "1", "0") FROM MYSQL_EMAILTABLE AS, MYSQL_DOMAINTABLE AS d, MYSQL_HOSTTABLE AS WHERE ma.domain = d.id AND d.mail_host = h.id AND CONCAT (ma.local_part, '@', d.domain) = '${quote_mysql: $2}' AND h.name = 'HOST' AND ma.pwclear = '${quote_mysql: $3}' MYSQL_Q_AUTHLOGIN = SELECT if (count (ma.id), "1", "0") FROM MYSQL_EMAILTABLE AS, MYSQL_DOMAINTABLE AS d, MYSQL_HOSTTABLE AS WHERE ma.domain = d.id AND d.mail_host = h.id AND CONCAT (ma.local_part, '@', d.domain) = '${quote_mysql: $1}' AND h.name = 'HOST' AND ma.pwclear = '${quote_mysql: $2}' MYSQL_Q_AUTHCRAM = SELECT ma.pwclear FROM MYSQL_EMAILTABLE AS, MYSQL_DOMAINTABLE AS d, MYSQL_HOSTTABLE AS h WHERE ma.domain = d.id AND d.mail_host = h.id AND h.name = 'HOST' AND CONCAT (ma.local_part, @ ', d.domain) = ' $1 ' This completes the definition of MySQL queries for Exim. The concrete use of the individual queries is discussed below. Here are the two relevant queries for the POP3 and IMAP servers for Dovecot. On the one hand, it requires the possibility to query the user's password and, on the other hand, to determine the location of the maildir. Because the prefetch feature is used for Dovecot, see below, the password query also returns the same as the location of the maildir and other information. Thus a separate UserQuery would actually be superfluous when using dovecots LDA deliver but this is necessary. The two queries are identical and return a result of the following form. ^User^Password^Home^UID^GID^ |user @ domain. tld||/srv/mail/domain.tld/user|8|8| The actual queries differ only in the names of the fields: User_name = password_query = SELECT concat (ma.local_part, '@', d.domain) AS user, pwclear AS password, concat ('/srv/mail/', d.domain, '/', ma.local_part) AS userdb_home , '8' AS userdb_uid, '8' AS userdb_gid FROM mail_accounts AS ma, domains AS d, hosts AS h WHERE ma.domain = d.id AND d.mail_host = h.id AND ma.local_part = '%n' AND d.domain = '%d' AND h.name = 'HOST' User_query = SELECT concat (ma.local_part, '@', d.domain) AS user, pwclear AS password, concat ('/srv/mail/', d.domain, '/', ma.local_part), 8 'AS uid,' 8 'AS gid FROM mail_accounts AS ma, domains AS d, hosts AS h WHERE ma.domain = d.id AND d.mail_host = h.id AND ma.local_part ='%n 'AND d.Domain = '%d' AND h.name = 'HOST' It is necessary to replace the placeholder **HOST** with the host name as it is entered in the **hosts** table; or alternatively to remove the entire phrase **AND h.name = 'HOST'** if you use only one server and have no use for the hosts table. ---- ===== SSL: Create key pair and certificates ===== In order to secure the transmission between the mailserver and the users on the one hand as well as other mail servers on the other side, it is useful to use encrypted connections using a secure-socket layer (SSL). The programs already offer this functionality, only the corresponding keys and certificates still have to be created. For details see [[https://en.wikipedia.org/wiki/Public_key_infrastructure|PKI]] and [[http://tools.ietf.org/html/rfc3280|RFC3280]]. To generate the required key pairs **openssl** is required. First, a private key is created under the name private.key. Of course, you can also choose a different name. The key length is 1024 or 2048 or 4096: openssl genrsa -out private.key 2048 Then the Certificate Signing Request (CSR) is generated: openssl req -new -key private.key -out server.domain.csr OpenSSL will request various bits of X.509 information from you. You are about to be asked to enter information that will be incorporated into your certificate request. What you are about to enter is what is called a Distinguished Name or a DN. There are quite a few fields but you can leave some blank For some fields there will be a default value, If you enter '.', the field will be left blank. ----- Country Name (2 letter code) [AU]:DE State or Province Name (full name) [Some-State]:Hesse Locality Name (eg, city) []:Frankfurt Organization Name (eg, company) [Internet Widgits Pty Ltd]:Internet Widgits Pty Ltd Organizational Unit Name (eg, section) []:CA Common Name (eg, YOUR name) []:server.domain.tld Email Address []: Please enter the following 'extra' attributes to be sent with your certificate request A challenge password []: An optional company name []: Depending on the policy of your CA, this information must be true and, if necessary, clearly verifiable. The common name is very Important. Here you have to enter the hostname (FQDN) of your mailserver. It is also important that this hostname is resolvable both via DNS and via reverse DNS. The password should be omitted. This is a possible way to attack, but if you enter a password here, you must either enter it into the configuration files, which does not provide additional security, or enter it manually each time you restart the services. It is your decision. This CSR can now be used to order a real certificate from a Certification Authority (CA). Depending on the purpose of the server, you can either purchase a self-signed certificate, a free certificate from CACert or StartSSL, or a paid certificate from VeriSign, Thawte, If you want to use a self-signed certificate, see the following [[http://www.knaupes.net/tutorial-ssl-zertifikat-selbst-erstellen-und-signieren/|tutorial]]. After you receive the certificate, place it under /etc/ssl/certs/server.domain.tld.Save the corresponding private key under /etc/ssl/private/server.key. Write down these paths, they are needed later. It may be necessary to adjust the access rights for the private key. Run chmod o+x /etc/ssl/private to change any users in this directory or save the private key in the Exim configuration directory under /etc/exim4. ---- ===== Configure Exim ===== Use the following provided template as a basis for your Exim4 configuration. All points that need to be changed by you are marked with a CHANGEMEM. Here is a step-by-step discussion of the relevant options. ---- ==== Basic settings ==== First, you need to set the //primary_hostname// with the name of the MailServer. This name should be resolvable consistently via DNS and reverse DNS. That is a DNS query to the primary hostname should return the IP address under which the mail server is operating and a reverse DNS query to this IP address should return the FQDN: primary_hostname = server.localdomain.tld In the Domain List //local_domains// we define all domains for which Exim is locally responsible, i.e. all domains whose mailboxes are delivered by the current Exim instance. Here the first MySQL query comes to use. At runtime, Exim will run the query, and then view the list of domains .: domainList local_domains = localhost:mysql;MYSQL_Q_LDOMAIN The //relay_to_domains// Domain List is for domains to deliver (forward) to which are not delivered locally. domainList relay_to_domains = mysql; MYSQL_Q_RDOMAIN //qualify_domain// specifies which domain is appended to addresses consisting of only one user name. Here the main domain should be registered: qualify_domain = server.tld Very important is the option //local_interfaces// which is set to which network interfaces the mail server will be available on. Important here is to a loopback interface and secondly, the public IP address of the mail server indicated. There is also the option here to specify an IPv6 address: local_interfaces = <; 127.0.0.1; 192.168.0.1; \ 2001: 0db8 :: 1 The default port for SMTP is 25, therefore, the mail server must listen here definitely if it wants to receive from other systems messages. Port 587 is a newer port, defined by [[http://xml.resource.org/public/rfc/html/rfc2476.html|Message Submission]] protocol that aims to provide a distinction between the exchange of messages between mail servers and the delivering clients. On port 587, the client should accept only authenticated communications from clients over SMTP: daemon_smtp_port = 25: 587 ---- ==== ACL configuration ==== The ACL configuration determines how Exim reacts during each phase of the SMTP protocol. Various checks and greylisting can be performed. The **acl_check_from** check is used after the **FROM:** command to ensure that port 587 is being used in accordance with [[http://tools.ietf.org/html/rfc4409|SMA]] only for authenticated connections: acl_check_from: # Drop connections on the SMA Port did did not auth drop condition = ${if = {$interface_port}{587}{1}{0}} ! Authenticated = * # Accept everything else (policy checks are in rcpt acl) accept Further checks are only after notification of the receiver, i.e. after the **RCPT TO:** command. Among other things the syntax of addresses, RBLs and greylisting be checked. ---- ==== routers ==== After the ACL section comes the configuration of the router. The order in which the routers are defined is important. Each message which has survived the input ACL checks will be presented to each router to accept the message. **NOTE**: The **fail_router** which rejects all messages that are entered in the database as inactive, may only come after the **dnslookup** router, since there may be problems with the deactivated accounts otherwise. The **dnslookup** router processes all messages that are not delivered locally, hence **domains =! + local_domains** ensures that the router will not be applied for local domains. dnslookup: driver = dnslookup domains =! + local_domains transport = remote_smtp ignore_target_hosts = 0.0.0.0: 127.0.0.0/8 no_more The **blacklist_router** ensures that the header **X-Spam-Flag: YES** is added if the sender is on the blacklist. The **spamcheck_director** passes the message to SpamAssassin and then continues processing. The **spampurge_director** ensures, with the above-discussed SQL query, that spam emails are possibly disposed of directly. The **vacation_director** generates a vacation_autoreply for an absent message, if it is enabled in the user database. The directors **virtual_cc_director** and **virtual_forward_director** ensure that the messages are duplicated or forwarded. It is interesting especially the **virtual_local_mailbox** director of all messages to local addresses that have not been treated to here from another router, the Dovecot transport thus passes these using dovecots deliver the message in the user's Maildir delivers. virtual_local_mailbox: driver = accept domains = ${lookup {mysql MYSQL_Q_LOCAL}{$ value}} transport = virtual_local_dovecot_delivery ---- ==== Transports ==== After the routers still have a brief meeting of the relevant tranports. The **remote_smtp** Transport ensures the delivery of messages to other hosts using SMTP. The parameter **interface = ** instructs for outgoing connections to use the correct address. Here the IP address of the mail server must be entered. This option is only needed when multiple IP addresses are set on the mail server. The **spamcheck** transport ensures that the appropriate messages are passed to SpamAssassin. For this, the **pipe** Driver is used by the issuing **transport_filter**. The option **spam-scanned** ensures the appropriate protocol is set so that Exim recognizes this message as scanned. spamcheck: driver = pipe command = /usr/sbin/exim4 -oMr spam-scanned -bS use_bsmtp = true transport_filter = "/usr/bin/spamc -u $local_part@$domain" home_directory = "/tmp" current_directory = "/tmp" user = mail group = mail log_output = true return_fail_output = true return_path_add = false message_prefix = message_suffix = The second interesting transport is **virtual_local_dovecot_delivery**. This transport is responsible for ensuring that news about the Dovecot LDA lands in the user's mailbox. The message to deliver uses the user information from the database - see Dovecot configuration - possibly executes Sieve scripts and subsequently delivers the message. At the same time it ensures that the internal data structures of Dovecot, such as additional indices are kept current. Another advantage over the internal exim functionality. virtual_local_dovecot_delivery: driver = pipe command = /usr/lib/dovecot/deliver -d $local_part@$domain message_prefix = "" message_suffix = "" delivery_date_add envelope_to_add return_path_add log_output user = mail group = mail ---- ==== Retry ==== The **Retry** configuration is used next. See the exim specifications for further information. It will not be discussed further here. In the rewrite configuration it is possible to make more information. ---- ===== Authentication ===== The last interesting section in the exim configuration is the section for authentication. Here the possible methods for SMTP AUTH are defined. The default is **PLAIN**, **LOGIN** and **CRAM-MD5**. ---- ==== Dovecot Local Delivery Agent (LDA) ==== Exim4 can directly serve messages to the local user, since it supports the Maildir format. It acts by default as both MTA (Mail Transfer Agent) as well as LDA (Local Delivery Agent). However Dovecot comes with its own LDA, which offers several advantages over the built-in functionality of exim. The main difference is probably the support of the Sieve filtering language that allows server-side filtering of messages. In particular, your IMAP users will appreciate this functionality. ## ## LDA specific settings ## protocol lda { # Address to use when sending rejection mails. postmaster_address = postmaster@server.tld # Hostname to use in various parts of sent mails, eg. in Message-Id. # Default is the system's real hostname. #hostname = # Support for dynamically loadable plugins. mail_plugins is a space separated # list of plugins to load. #mail_plugins = mail_plugin_dir = /usr/lib/dovecot/modules/lda # Binary to use for sending mails. sendmail_path = /usr/lib/sendmail # UNIX socket path to master authentication server to find users. auth_socket_path = /var/run/dovecot/auth-master # Enabling Sieve plugin for server-side mail filtering mail_plugins = cmusieve # Logging #log_path = /var/log/dovecot-deliver.log #info_log_path = /var/log/dovecot-deliver.log } ---- ==== Exim under high load ==== Although the present Exim setup can definitely cope with more than 6500 emails per hour, there are several options that may somewhat reduce the load on the system in environments with very high load: queue_only split_spool_directory queue_run_max = 1 remote_max_parallel = 1 These instructions ensure that all consigned messages are first placed in the queue, a maximum of one instance of this queue is processing, and the spool directory is shared with further subdirectories. More information can be found in the [[http://www.exim.org/eximwiki/FAQ/Performance/Q1002|Exim FAQ]]. ---- ==== Send a test email ==== Once you have configured the mail server, you should now test whether it works. For this you can manually simulate an SMTP session using telnet. telnet localhost 25 Thereupon, the server should display: Trying 127.0.0.1 ... Connected to localhost. Escape character is '^]'. 220 server.domain.tld ESMTP Exim 4.63 Now Exim is prepared to accept SMTP commands. First, we must by EHLO imagine. EHLO localhost.localdomain Then Exim displays what features it offers: 250-server.domain.tld Hello user at localhost [127.0.0.1] 250-SIZE 10240000 250-PIPELINING 250-AUTH PLAIN LOGIN CRAM-MD5 250-STARTTLS 250 HELP Specify the sender: MAIL FROM: A positive status code (2xx)? Good. Then further. 250 OK Specify the recipient. RCPT TO: 250 Accepted Another positive status code! Good. Did you notice the delay between pressing the Enter key and the feedback? During this time, Exim operates the **acl_check_rcpt** from ACL rule. Here is among others the greylisting daemon - if configured - and the SQL database query. That takes a while. Now use **DATA** to specify the data part if the message. DATA 354 Enter message, ending with "." on a line by itself Enter the text of the mail. Hello World! . 250 OK id = 1K4a1j-0004GI-FP So that's it. Another positive status code means that Exim has accepted the message. In the file **/var/log/exim4/mainLog** you can check whether the message has been delivered correctly. 2008-06-06 13:22:56 1K4a1j-0004GI-FP <= jane@domain.tld H = localhost (localhost.localdomain) [127.0.0.1] U = P = User esmtp S = 300 2008-06-06 13:22:59 1K4a24-0004R9-KZ <= jane@domain.tld U = P = mail spam-scanned S = 861 2008-06-06 13:22:59 1K4a24-0004R9-KZ => john R = T = virtual_local_mailbox virtual_local_dovecot_delivery 2008-06-06 13:22:59 1K4a24-0004R9-KZ Completed 2008-06-06 13:22:59 1K4a1j-0004GI-FP => john@domain.tld R = T = spamcheck_director spamcheck H = localhost 2008-06-06 13:22:59 1K4a1j-0004GI-FP Completed ---- ===== Having Problems? ===== exim -bh! Should the delivery of messages cause any problems you can run exim with parameter **-bh ** which simulates an SMTP session using the address. Here the SMTP session must be carried out as just described above by hand, however, note that the message won't be delivered. Instead supplied Exim the user so with very detailed information what he is doing. exim4 -bh 127.0.0.1 **NOTE**: It makes no sense to post to localhost (127.0.0.1) in testing, because exim mail has been configured to always assume delivery from that host. Instead, use as the current IP address. ---- ===== Configure Dovecot ===== The Dovecot configuration is very extensively documented by the author, but the amount of information can be confusing. Therefore, here I discuss the important sections. The section **protocols** should be added to the POP3 protocols: protocols = imap pop3 imaps pop3s In the lists instruction is determined with which to interface the server should listen. Specify a path to the log file otherwise logging is written to syslog which can be quite confusing quickly. log_path = /var/log/dovecot.log Ensure this log file has the right owner and permissions: chown dovecot:dovecot /var/log/dovecot.log> chmod 770 /var/log/dovecot.log If you have decided on a setup with SSL certificates, then select the appropriate option and set the **ssl_cert_file** and **ssl_key_file** the paths to your key pair. ssl_disable = no ssl_cert_file = /etc/ssl/certs/server.domain.tld.crt ssl_key_file = /etc/ssl/private/server.domain.tld.key You can simply accept The other SSL options. Next, you should set the **login_greeting** . login_greeting = server.tld Mail Server (powered by Dovecot) ready. It is suggested to enter the host name of your server. With the option **mail_location** inform Dovecot where your mailboxes are. If you have followed the directory structure described here, this line is as follows: mail_location = maildir: /srv/mail/%d/%n/Maildir Specifically, this means that you use **maildir** and the appropriate directories is under the path /srv/mail///Maildir. Dovecot replaces the variable **%d** with and **%n** with the local part of the address. Next, the following settings for namespace needs to be set. The **first_valid_uid** should be set to the lowest user uid. As the current setup has no real users on the server due to all mailboxes are being "owned" by the mail user. This user usually has the used-ID 8. Therefore, you need to adjust the range of valid UIDs as follows: first_valid_uid = 8 last_valid_uid = 8 The other settings for IMAP and POP3, can simply be accepted. See [[http://developer.gauner.org/ispmail-exim/#nachrichten-mit-dem-dovecot-delivery-agent-lda-zustellen|news about Dovecot Delivery Agent (LDA)]] for information on the options in the lda protocol. The next interesting section is **auth default**. Here you disable the section passdb, passwd file and any others up until passdb sql. The only option for this section is the path to the SQL configuration. Their configuration is considered later. passdb sql { args = /etc/dovecot/dovecot-sql.conf } Uncommented everyone else in the userdb Sections until the following: userdb passwd { } userdb sql { args = /etc/dovecot/dovecot-sql.conf } Thus dovecots LDA deliver can still work the corresponding socket must be activated: socket listen { master { path = / var / run / dovecot / auth-master mode = 0600 user = mail # user running Dovecot LDA group = mail # Or alternatively fashion 0660 + LDA user in this group } client { path = / var / run / dovecot / auth-client mode = 0600 user = mail group = mail } } Now, adjust the configuration of the SQL queries in dovecot-sql.conf. This was the section connecting to the database as discussed. The configuration of Dovecot is finished. ---- ===== Retrieving a test mail using POP3 ===== The POP3 protocol is quite simple, so you can test the reception of messages via POP3 easily by hand. telnet localhost 110 Once you have connected to, you will be greeted by dovecot. Trying 192.168.0.1... Connected to server.domain.tld. Escape character is '^]'. +OK server.domain.tld Mailserver (powered by Dovecot) ready. The server is now ready. Now you can log in. user john@domain.tld The server should accept the username. +OK Then use the password must be entered. pass pass If the server accepts the password you are logged in. +OK Logged in. Now you can view a list of messages in the mailbox. list Dovecot now shares with the number of messages are present. +OK 1 messages: 1 2958 . With Retriever you can retrieve the messages. Get the first message. retr 1 Now you with dovecot the message. +OK 2958 octets [Here follows the message] After work is finished, you can log out. quit What is confirmed by Dovecot again. +OK Logging out. Connection closed by foreignhost. ---- ===== Retrieving a test mail through IMAP ===== The IMAP protocol is slightly more complicated than SMTP or POP3 and therefore it is recommended to use a different client such as **mutt**. mutt -f ./Maildir But you can of course also like to try by hand. telnet localhost 143 Trying 127.0.0.1 ... Connected to server.domain.tld. Escape character is '^]'. * OK [CAPABILITY IMAP4rev1 SASL-IR SORT THREAD = REFERENCES MULTIAPPEND UNSELECT LITERAL + IDLE CHILDREN NAMESPACE LOGIN-REFERRALS STARTTLS AUTH = PLAIN] server.domain.tld Mail Server (powered by Dovecot) ready. We can now login. 1 login john@domain.tld password If username and password are correct, the server should provide an OK. 1 OK Logged in. Now you can display the existing messages. 2 list "" "*" * LIST (\HasNoChildren) "." "INBOX" 2 OK List completed. Now select the Inbox (INBOX) from: 3 select "INBOX" Then you will automatically receive some information about this folder: * FLAGS (\Answered \Flagged \Deleted \Seen \Draft Junk NonJunk $FORWARDED $TODO $WATCHED $IGNORED) * OK [PERMANENTFLAGS (\Answered \Flagged \Deleted \Seen \Draft Junk NonJunk $FORWARDED $TODO $WATCHED $IGNORED \*)] Flags permitted. * 1 EXISTS * 0 RECENT * OK [UIDVALIDITY 1158586288] UIDs valid * OK [UIDNEXT 136835] Predicted next UID 3 OK [READ-WRITE] Select completed. Based on the third line (*** 1 EXISTS**) you can see that there is a message. Call this from now. 4 fetch 1 all You will now receive at first only a few information about the message, not the message text. * 1 FETCH (FLAGS (\Seen) INTERNALDATE "17-Apr-2008 09:23:44 +0200" RFC822.SIZE 2958 ENVELOPE ("Thu, 17 Apr 2008 00:02:40 -0400" "Subject" (("Hello" NIL "Jeo" "jeo@ceo.org")) (("Hello" NIL "Jeo" "jeo@ceo.org")) (("Hello" NIL "Jeo" "jeo@ceo.org")) ((NIL NIL "ceo" "ceo.org")) NIL NIL NIL "")) 4 OK Fetch completed. The text you need to explicitly request: 5 fetch 1 body [] Now Dovecot provides you with the complete delivery contents back: * 1 FETCH (BODY [] {486} [Message] 5 OK Fetch completed. You may unsubscribe now. 6 logout Dovecot then closes the connection. * BYE Logging Out 6 OK Logout completed. Connection closed by foreign host. ---- ===== SpamAssassin from spam ===== The constant harassment is one of the largest problems in the use of the medium by email today. Luckily there with SpamAssassin a fairly effective classifier with which you can sort out most spam messages correctly. If you have followed the steps outlined thus far, SpamAssassin should already be installed and set up. What is still missing is a little tweaking. First off ensure that the SpamAssassin daemon is started by changing the following in the file **/etc/default/spamassassin**. ENABLED = 0 to: ENABLED = 1 After that the needs OPTIONS line to be adjusted. Change the line as follows: OPTIONS="--max-children 8 --helper-home-dir -u mail -x -q -s local5" Now please open the file **/etc/spamassassin/local.cf** and then verify that the following options with the given values are present. Complete or change the information if necessary. report_safe 1 use_bayes 1 bayes_auto_learn 1 bayes_auto_expire 0 bayes_ignore_header X-Bogosity bayes_ignore_header X-Spam-Flag bayes_ignore_header X-Spam-Status bayes_ignore_header Return-Path bayes_ignore_header Received bayes_ignore_header X-Spam-Level bayes_ignore_header X-purgate bayes_ignore_header X-purgate-ID bayes_ignore_header X-purgate-Ad bayes_ignore_header X-GMX-Antispam bayes_ignore_header X-Sieve bayes_ignore_header To bayes_ignore_header X-WEBDE-FORWARD bayes_path /var/mail/bayesdb skip_rbl_checks 0 use_razor2 1 use_dcc 1 use_pyzor 1 dns_available yes rbl_timeout 4 ok_locales all score DCC_CHECK 4.000 score SPF_FAIL 3.000 score SPF_HELO_FAIL 3.000 score DKIM_VERIFIED -1.3 score DKIM_POLICY_TESTING 0 score DK_VERIFIED -1.1 score USER_IN_DKIM_WHITELIST -4.0 score USER_IN_DK_WHITELIST -3.9 score RAZOR2_CHECK 2.500 score BAYES_99 5.000 score BAYES_90 4.500 score BAYES_80 3.500 After the configuration is completed reload the SpamAssassin daemon to enabled the changed settings. /etc/init.d/spamassassin reload ---- ===== Useful Tools ===== ==== greylistd ==== Greylisting is a method to ward off spam before posting. It makes use of the fact that most spam skidding implement the SMTP protocol is incorrect. Most spammers are simply trying to send the mail as soon as possible. However, the SMTP protocol also provides that a server returns the sender a temporary error and the sender should try again after some time. Most spam MTAs enter immediately and do not try again to deliver the message. However, the regular MTAs implement the protocol most correct and try again after a few minutes to deliver the message. The greylistd remembers all combinations of destination address and sender IP. In the first experiment, the MTA will provide a temporary error, after a certain waiting period, the message is accepted. This also applies to all other messages from the same sender within a certain period. The default is 60 days expire in the configuration. The waiting time before a message after the first attempt is accepted is preset for 10 minutes and retryMin can be adjusted. Unused combinations be discarded after 8 hours retryMax. The file **whitelist-hosts** can be used to specify mailservers that should never be block by Greylisting. Here, you can enter major customers or known problematic senders. ---- ==== Spam and ham (non-spam) learn ==== The spam classifier SpamAssassin combines different techniques to detect spam messages. These include classic text filter, real-time block lists (RBL) and Distributed Checksum Networks (Razor, Pyzor, dcc). Another is a Naive Bayes classifier that learns based on specific training examples where the more training data that is given produces better recognition performance. Your customers can make an active contribution by explicitly placing their spam messages in a spam folder. From this folder, you can then run the training script offered by SpamAssassin. From the training data, the classifier then calculated for each message a probability that it is spam based on the contained words. In the previous configuration of SpamAssassin, we have determined that SpamAssassin as a user mail runs its working directory under /var/mail. The Bayesian database is consequently under /var/mail/bayesdb_{journal, lakes, tokens} . To automatically train the naive Bayes classifier lends itself to a shell script via cron to be run regularly on selected directories. You must first specify which mailboxes contain actionable messages. Important here is that the messages are checked regularly by hand so that the classifier can not present false information. #!/bin/bash DBPATH=/var/mail/bayesdb SPAMFOLDERS="\ /srv/mail/domain.tld/important.customer/Maildir/.Spam/cur \ /srv/mail/domain.tld/john.doe/Maildir/.Spam/cur \ " HAMFOLDERS="\ /srv/mail/domain.tld/john.doe/Maildir/cur \ /srv/mail/domain.tld/important.customer/Maildir/cur \ " for sfolder in $SPAMFOLDERS ; do \ nice sa-learn --spam --dbpath /var/mail/bayesdb $sfolder done for hfolder in $HAMFOLDERS ; do \ nice sa-learn --ham --dbpath /var/mail/bayesdb $hfolder done Put this script below **/var/mail/satrain.sh**, make it executable and run it as a cron job for the user mail. su mail crontab -e In open end Editor Then enter the crontab. 15 4 * * * /bin/bash /var/mail/satrain.sh >/dev/null This line makes sure that the script runs every day at 4:15, with errors suppressed. You can control how many spam or ham messages have already been learned. Either through **sa-learn** or via **AutoLearn**. The line starting with nspam ends are the number of learned spam messages to while the line nham the number of messages indicating Ham. sa-learn --dbpath /var/mail/bayesdb --dump magic 0.000 0 813 0 non-token data: nspam 0.000 0 7737 0 non-token data: nham ---- ===== Webmail ===== Roundcube is recommended as the Webmail client due to the good functional scope and appealing interface. Of course you can also use other clients, such as Horde / IMP Webmail. The installation of Roundcube is simple and straightforward. First you go to the target directory, e.g. **/var/www**, and downloads the latest installation file. You find the link to the homepage of [[http://www.roundcube.net/downloads|Roundcube]]. cd /var/www wget tar xvfj roundcube-XXX.tar.bz2 Roundcube requires a database for settings and to store messages. It's probably best to its own database. Thereafter, the file **mysql.initial.sql** from directory **SQL** is imported into the database and the database information is added to the file **db.inc.php**. $> cd roundcube-XXX/SQL $> mysql -uDBUSER -pDBPASS DBNAME < mysql.initial.sql $> cd ../config $> cp db.inc.php.dist db.inc.php In the **db.inc.php** file, the parameter **$rcmail_config['db_dsnw']** need to be adjusted. $rcmail_config['db_dsnw'] = 'mysql://DBUSER:DBPASS@localhost/DBNAME'; The mail server must be entered in the **main.inc.php** file. For this purpose edit this file and update the parameter $rcmail_config['default_host']. $rcmail_config['default_host'] = 'mail.domain.tld'; Roundcube configuration is already completed and the webmail interface can be accessed via the web server. ---- ==== Setting Management Interface ==== To manage the users in the database it's great to provide a web frontend. These can be found in the archive with the configuration files in the folder scripts / backend / an archive named **ispmail_admin.zip** that provides the basic framework of a management frontends in PHP. With this interface the complete user management is possible, but it is not very comfortable. The interested reader with PHP Kent Nissen, however, can quickly create a pleasing surface based on the backbone. The installation of the management interface is very simple. After the archive is extracted in an accessible via browser folder on the Web server, only the file must **config/_conf.dba.inc.php** be adjusted. There in particular, the following lines are interesting. $dba->database = "ispmail"; $dba->server = "localhost"; $dba->user = "ispmail"; $dba->password = "ispmail"; The administration frontend required in addition to the table described above nor the table config in some settings are stored. For this please execute the following SQL code. DROP TABLE IF EXISTS `config`; CREATE TABLE IF NOT EXISTS `config` ( `Id` int (16) NOT NULL auto_increment, `Property` varchar (255) character set latin1 NOT NULL default '', `Value` text character set latin1 NOT NULL, `Created_at` int (16) NOT NULL default '0', `Updated_at` int (16) NOT NULL default '0', PRIMARY KEY ( `id`) KEY `property` (` property`) ) ENGINE = InnoDB DEFAULT CHARSET = utf8 AUTO_INCREMENT = 0; INSERT INTO `config` (` id`, `property`,` value`, `created_at`,` updated_at`) VALUES (0, 'url_protocol', 'http', 1201340788, 1216806584) (1, 'list_limit', '34', 1204548583, 1213956805), (2, 'site_name', 'ISP mail Admin', 0, 0); Here is the same data must be entered as used above for the configuration of other services. After that you should have the directory with a password protection via **.htaccess** provided and you can immediately start to create user. ---- ==== Sieve to filter out spam ==== Dovecot supports Sieve scripts on a plugin that one section protocol lda with the line mail_plugins = cmusieve must be activate. After that there is a file named is possible in the user directory .dovecot.sieve store. There you can filter rules define are executed during the delivery from the LDA. Example Sieve script: require [ "fileinto"]; # Move tagged spam mails into the spam folder if header: contains "X-Spam-Flag" [ "YES"] { fileinto "spam"; Stop; } This script can also be used to for all users automatically the spam mail presort. Given to Save the script as under **/srv/mail/globalsieve** and sets global_script_path = /srv/mail/globalsieve global script path to the script. In this context, it warned that user their mails exclusively via POP3 to retrieve only messages in your inbox, exclusive subdirectories, see. This provides users with access only via Webmail or IMAP messages in Spam. This can lead to confusion and anger when false positives in spam folder land at inexperienced users may. For more information about Sieve are in RFC3028 . ---- ==== Setting up Mailman mailing list ==== With Mailman there is a modern and powerful mailing list manager for Unix systems. Installation is as usual Debian fairly straightforward: aptitude install mailman Two parameters are interesting for integration into Exim. On the one hand, in the pipe command to be entered Mailman alias file and the Domain List for the Mailman feels responsible. If the data parameter of the path can /etc/aliases.mailman simply be imported, if you plan to store the corresponding aliases there. The data which the command is to be entered there newlist after setting up a new list on the command line. You have the information then just copy the file and the new list is ready for use. The parameter domains indicates which domains of these routers is applied, ie, here we define the domain part under which the lists are accessible. Take for instance the Domains lists.domain.tld has entered and a list with the name exim has created, then this list is under exim@lists.domain.tld reachable. mailman_aliases: driver = redirect allow_fail allow_defer data = $ {lookup {$ local_part} {lsearch /etc/aliases.mailman}} file_transport = address_file pipe_transport = address_pipe domains = lists.localdomain.tld user = list ---- ===== Backup Set up Mail Server ===== A backup MX, so an additional mail server, the reliability and the load balancing is used. Although the SMTP protocol provides one message from the sender up to 4 days is trying served, but if that is not enough, then one option is to set up a backup mail server. The DNS protocol allows for a domain to specify multiple mail servers. If you are thinking about setting up a backup MX, you should be aware that if your primary mail server fails, its users not send messages still can receive. The only thing that makes the backup MX, is to accept messages that can not accept their primary mail server at the moment, and then forwards them to the latter. The establishment of the required software packages is virtually identical to the primary MX, so here to the section [[http://developer.gauner.org/ispmail-exim/#installation-der-benotigten-pakete|Installation of required packages]] is referred. An important aspect when setting up a backup MX is to pay attention to the vulnerability to spam. It's inexcusable to use at the present time a backup MX, which is not as secure at least from spam as the primary mail server. Spammers send today usually news gefälschen Abesnder addresses. Often this existing addresses are of completely uninvolved. Would the backup MX accept without the local recipient to check these messages and the primary MX would find later that the user does not exist, he would be forced to send an error message (bounce) to the sender, according to RFC. This therefore has nothing to do. Thus, on the one hand would the burden on the primary MX rise and secondly other users would be bothered with unnecessary error messages. To work around this problem using the setup presented here a replica of the user database. This replica is accessed by means of a shell script every hour from the primary MX. When a message is admitted to the backup MX checks this using the SQL Query MYSQL_Q_RELAY in router smarthost if the user exists. This check is already after the RCPT TO instead step. Responsible for this is the option **verify = recipient** in **accept domains = +relay_to_domains** check. The router **dnslookup** is only required for the verification of sender. First, again the macros for the SQL queries are defined. MYSQL_SERVER=localhost MYSQL_USER=DBUSER MYSQL_PASSWORD=DBPASS MYSQL_DB=DBNAME MYSQL_EMAILTABLE=mail_accounts MYSQL_DOMAINTABLE=domains MYSQL_HOSTTABLE = hosts BL_WARN=zen.spamhaus.org BL_DENY=zen.spamhaus.org This query determines whether we accept this message. That is whether it is intended for a domain for which we are responsible and if the mailbox is active. MYSQL_Q_RELAY=SELECT d.domain FROM MYSQL_EMAILTABLE AS ma, MYSQL_DOMAINTABLE AS d WHERE d.domain='${quote_mysql:$domain}' AND ma.local_part='${quote_mysql:$local_part}' AND ma.is_enabled = 'yes' AND ma.domain = d.id This query determines whether the message is intended for a domain for which we accept mails (Relay). MYSQL_Q_RDOMAIN=SELECT domain FROM MYSQL_DOMAINTABLE WHERE domain='${quote_mysql:$domain}' AND is_enabled='yes' This query messages to disabled mailboxes are rejected at the outset. MYSQL_Q_DISABLED=SELECT d.domain FROM MYSQL_EMAILTABLE AS ma, MYSQL_DOMAINTABLE AS d WHERE d.domain='${quote_mysql:$domain}' AND ma.local_part='${quote_mysql:$local_part}' AND ma.is_enabled = 'no' AND ma.domain = d.id hide mysql_servers = "MYSQL_SERVER/MYSQL_DB/MYSQL_USER/MYSQL_PASSWORD" primary_hostname = backupmx.domain.tld domainlist relay_to_domains = mysql;MYSQL_Q_RDOMAIN hostlist relay_from_hosts = 127.0.0.1 acl_smtp_rcpt = acl_check_rcpt acl_smtp_mail = acl_check_from qualify_domain = domain.tld never_users = root host_lookup = * trusted_users = mail untrusted_set_sender = * local_from_check = false rfc1413_hosts = * rfc1413_query_timeout = 15s check_spool_space = 50M check_log_space = 20M return_size_limit = 20k message_size_limit = 20M ignore_bounce_errors_after = 2d timeout_frozen_after = 7d deliver_queue_load_max = 8 queue_only_load = 10 remote_max_parallel = 15 tls_certificate = /etc/ssl/certs/server.domain.tld.crt tls_privatekey = /etc/ssl/private/server.domain.tld.key tls_advertise_hosts = * The option **local_interfaces** the address can be defined in which Exim listens for connections. In this case, this is both localhost, and a public IPv4 and an IPv6 address. local_interfaces = <; 127.0.0.1 ; 192.168.0.2 ; \ 2001:0DB8::2 The port is in the case of backup MX only port 25, because it is not designed to accept messages from the delivering users. daemon_smtp_port = 25 begin acl acl_check_from: accept acl_check_rcpt: accept hosts = : deny domains = +relay_to_domains local_parts = ^[./|] : ^.*[@%!] : ^.*/\\.\\./ accept local_parts = postmaster domains = +relay_to_domains require verify = sender accept authenticated = * warn message = X-blacklisted-at: $dnslist_domain dnslists = BL_WARN deny dnslists = BL_DENY defer message = $sender_host_address is not yet authorized to \ deliver mail from <$sender_address> to <$local_part@$domain>. \ Please try later. log_message = greylisted. domains = +relay_to_domains !senders = : postmaster@* !hosts = : +relay_from_hosts : \ ${if exists {/etc/greylistd/whitelist-hosts}\ {net-lsearch;/etc/greylistd/whitelist-hosts}{}} : \ ${if exists {/var/lib/greylistd/whitelist-hosts}\ {net-lsearch;/var/lib/greylistd/whitelist-hosts}{}} set acl_m9 = $sender_host_address $sender_address $local_part@$domain set acl_m9 = ${readsocket{/var/run/greylistd/socket}{$acl_m9}{5s}{}{}} condition = ${if eq {$acl_m9}{grey}{true}{false}} accept domains = +relay_to_domains endpass verify = recipient accept hosts = +relay_from_hosts deny message = relay not permitted # Routers begin routers The Fail router sort out all the messages to disabled mailboxes. # Fail Router fail_router: driver = redirect domains = ${lookup mysql {MYSQL_Q_DISABLED}{$value}} data = ":fail:" allow_fail The smart host router takes care of the delivery to the primary mail server. When router List the IP address should be entered instead of a hostname. # Smarthost Router smarthost: driver = manualroute domains = ${lookup mysql {MYSQL_Q_RELAY}{$value}} transport = remote_smtp route_list = * 192.168.0.2 byname host_find_failed = defer same_domain_copy_routing = yes no_more The DNS lookup router for sender Verify required. # DNS Lookup Router - required for Sender Verify dnslookup: driver = dnslookup domains = ! +relay_to_domains transport = remote_smtp ignore_target_hosts = 0.0.0.0 : 127.0.0.0/8 no_more # Transports begin transports remote_smtp: driver = smtp interface = 192.168.0.2 devnull_delivery: driver = appendfile file = /dev/null group = mail disabled_bounce: driver = autoreply from = ${local_part}@${domain} to = ${sender_address} user = mail subject = "Re $h_Subject:" text = "Your message to ${local_part}@${domain} was rejected due to a\n\ disabled account. Please try again later\n" devnull_transport: driver = appendfile file = /dev/null user = mail begin retry * * F,2h,15m; G,16h,1h,1.5; F,4d,6h begin rewrite *@domain.tld ${lookup{$1}lsearch{/etc/email-addresses}\ {$value}fail} frFs begin authenticators The script for the synchronization of the user database is kept simple. The idea here is that the script with mysqldump, best reads via a secure VPN connection, the system database from the primary mail server and which records on the backup MX. #!/bin/sh mysqldump -hDBHOST -uDBUSER -pDBPASS DBNAME | mysql -uDBUSER -pDBPASS DBNAME In DBHOST the address of the primary mail server must be entered. ---- ===== Troubleshooting ===== * Check /var/log/exim4/mainlog * Check /var/log/dovecot.log * Use exim4 -bh * Ask in #debian (in English) or # debian.de (in German) on the Freenode * Make sure that they use Debian "etch" * Consult. To the author (German or English) Of course you can also use it for pay you to help. ---- ===== Alternatives ===== Who is not happy with my tutorial, which may help further the following links. * [[http://www.debianhowto.de/doku.php/de:howtos:sarge:exim4_vexim2_courier_mailman|Exim4, vexim2, spam / virus protection, Courier-POP3 / IMAP, Mailman]] * [[http://www.debianhowto.de/doku.php/de:howtos:sarge:postfix2_antispam_virenschutz|Postfix with AV and antispam]] * [[http://workaround.org/articles/ispmail-etch/|ISP-style Email Server with Debian-Etch and Postfix 2.3]] * [[http://stefans.datenbruch.de/rootserver/vexim.shtml|VEXIM and Debian GNU / Linux]] * [[http://struction.de/projects/HOWTO_VirtualMail_Exim-MySQL-Spamassassin-ClamAV-Dovecot/index?set_lang=en#greylisting|Howto Setup a Virtual Mail System with Exim, MySQL, SpamAssassin, ClamAV and Dovecot]] ---- ===== Download ===== Here you can download the entire configuration as a package: [[http://developer.gauner.org/ispmail-exim/ispmail-etch-config.tar.bz2|Exim]] configuration . ---- ===== FAQ ===== Q: What is exactly locked when you lock on the back a mail address or a domain? A: The address or domain is set to "is_enabled = no", ie messages for the respective accounts are rejected and a log from the outside is no longer possible. Q: Do you have to create the Maildir directories yourself or this is done automatically? A: The maildir directories automatically delivers the first message when delivering applied. Q: Can you use POP3 and POP3S in parallel? A: Yes, it is possible to activate in the featured configuration. Q: Is it possible to integrate ClamAV directly? A: Yes, in the exim configuration, see Section routers an annotated block named **amavis_director**. Amavis is relatively easy to integrate ClamAV possible. Q: Is it possible to operate with the presented setup a mail server on a LAN with fetchmail (or similar)? A: Yes, this is possible but not useful. There are certainly better instructions. This tutorial focuses on the operation of a (separate) mail server on the Internet (root servers, etc.). Q: Do I need a backup MX? A: No, not necessarily. There are even opinions that a backup MX has more problems than benefits. The SMTP protocol specifies that a mail server should try for about 3 days to deliver a message, if a server is unreachable. Q: Where are exim4.conf the needed files, for example? A: The exim configuration is under Debian /etc/exim4. The file exim4.conf not exists you on a Debian system normally and must be created. Find an example in the link archive. Q: How do you implement a catchall address? A: The catchall functionality is already included in the setup. The **virtual_wclocal_redirect** router has not matched mails be diverted to a domain if an alias with the local_part in the database * exists. ---- ===== References ===== http://developer.gauner.org/ispmail-exim/ http://www.xmn-berlin.de/~marte/exim/exim4_mysql_amavis_spamassasin.html [[http://workaround.org/articles/ispmail-etch/|Postfix Tutorial]] https://www.organicdesign.co.nz/Configure_mail_server