User Tools

Site Tools


ubuntu:email:install_a_full_mail_server_for_multi-user_hosting_environments

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 ISP mail tutorial by C. Haas. Usually it is a setup on one, or more, 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 SQL database is used for user information.
  • SMTP, for the receipt and delivery of mails.
  • POP3 and IMAP for retrieving mail.
  • Exim configuration, whereby my configuration should be adopted with minor adjustment.
  • 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:

  • Exim4, accepts mail from the Internet via SMTP counter and allows it to send mails authenticated users
  • Dovecot, represents the mailboxes on the server using POP3 and IMAP for retrieval
  • MySQL, manages the user information
  • SpamAssassin, rated an upcoming news on a point system to the spam content.
  • Greylistd, makes many simple-minded
  • (Optional) Apache 2, for Webmail
  • (Optional) 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.

iddomainactiveserver
0domain.deyes1
1domain.comno2
2domain.netyes1
3server.tldyes3
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 userLocation 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.

serverFQDN
server1server1.domain.tld
server2server2.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:

fieldTypedescription
idint(9)Primary key auto_increment,
local_partvarchar(255)The user part of the address
domainint(16)The domain part of the address, points to the table domains
forwardvarchar(255)The goal of forwarding
ccvarchar(255)All messages to this address are copied here
namevarchar(255)A custom name
pwclearvarchar(255)The password in the plain text
pwcryptvarchar(255)The password in UNIX Crypt format
is_awayenum('yes', 'no')Auto-Responder active?
away_textenum ('yes', 'no')Text for the auto responder
spam_checkenum'yes', 'no')Run SpamAssassin?
spam_purgeenum('yes', 'no')Delete spam mails directly?
virus_checkenum('yes', 'no')Run the virus scan?
is_enabledenum('yes', 'no')Account active?
created_atint(16)Time stamp of creation
updated_atint(16)Time stamp of the last modification

domains:

fieldTypedescription
idint(16)Primary key auto_increment,
domainvarchar(255)Domain name (FQDN)
is_enabledenum('yes', 'no')Active?
mail_hostint(16)The responsible mailserver
created_atint(16)Time stamp of creation
updated_atint(16)Timestamp of the last modification

hosts:

fieldTypedescription
idint(16)Primary key auto_increment,
namevarchar(255)Hostname
fqdnvarchar(255)Full name (FQDN)
created_atint(16)Time stamp of creation
updated_atint(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.

/etc/exim4/exim4.conf
# 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.

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.

UserPasswordHomeUIDGID
user @ domain. tld<Pass>/srv/mail/domain.tld/user88

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 PKI and 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 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 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 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 = <ip> 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 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: <jane@domain.tld>

A positive status code (2xx)? Good. Then further.

250 OK

Specify the recipient.

RCPT TO: <john@domain.tld>
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.

/var/log/exim4/mainLog
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 <john@domain.tld> 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 <ip> which simulates an SMTP session using the <ip> 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/<domain>/<local_part>/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 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 "<CEO.20080417.564403.001.1208404960@ceo.org>"))
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.

/etc/default/spamassassin
ENABLED = 0

to:

/etc/default/spamassassin
ENABLED = 1

After that the needs OPTIONS line to be adjusted. Change the line as follows:

/etc/default/spamassassin
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.

/etc/spamassassin/local.cf
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 Roundcube.

cd /var/www
wget <URL>
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.

db.inc.php
$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'].

main.inc.php
$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 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 <ip>
  • 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

Download

Here you can download the entire configuration as a package: 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

ubuntu/email/install_a_full_mail_server_for_multi-user_hosting_environments.txt · Last modified: 2020/07/15 10:30 by 127.0.0.1

Donate Powered by PHP Valid HTML5 Valid CSS Driven by DokuWiki