We will play through setting up, configuring and testing a mail server under Linux, this is the beginning of a series of articles in which the mail server serves only as an SMTP relay. But we will come to that later, here it is all about our Linux mailserver with webmail login.
It is important to us to explain the functioning and interaction of the mail server components in such a way that the mail system as such can be understood in its basic features. We assume basic knowledge of Linux servers; nevertheless, this guide is also suitable for beginners who are interested and have the time.
Mail server functions
To give you an impression of the functionality of the finished mail setup, here are some features:
- Sending and receiving e-mails for any domains
- Flexible setup of domains, mail accounts, aliases, forwarding and transport encryption rules via a MySQL backend at runtime
- User-specific limited mailbox volume
- Setup of general and user-specific Sieve filter rules for filtering and/or re-sorting incoming e-mails
- Reliable and modern spam detection via Rspamd (+ web interface for spam statistics)
- “Send only” accounts e.g. for NextCloud / forum software / …
- DKIM and DMARC signing of outgoing e-mails
- Mail client autoconfiguration
- Domain catch-all
- SPF – Sender Policy Framework
- DMARC CHECK
- Roundcube – Webmail Login
Software used
- Debian 10 “Buster”
- Postfix
- Dovecot
- Rspamd
- Redis
- MariaDB
- Nginx
- Roundcube
Conditions
The following domains occur in this guide:
testsys.de: parent, primary domain
mail.testsys.de: Subdomain under which the mail server should be available (FQDN of the mail system)
imap.testsys.tld: Alias to mail.testsys.de, is automatically searched for and found by many mail clients.
smtp.testsys.tld: the same for the SMTP service
testsystwo.de: A second domain besides testsys.de for which e-mails are to be sent and received
domain3.de: A third domain for which e-mails are to be sent and received.
These domains must of course be replaced by your own domains in the entire manual!
Domain2..de and domain3.de can be omitted if the mail server is only to be used for one domain (only for “@testsys.de” addresses).
The following IP addresses are given as examples in configurations and must also be replaced by the IP addresses of the respective server:
– 2001:db8::1
(IPv6-Mail server address)
– 203.0.113.1
(IPv4-Mail server address)
Basic requirements for the mail server
A virtual or dedicated server with Debian 10 Buster already installed.
(“Standard system tools” and “SSH” selected during installation)
At least one own domain + full control over the DNS zone
A small, virtual server based on KVM is quite sufficient in most cases. I recommend two CPU cores and 1-2 GB RAM for small, private setups. Virtual servers can be obtained cheaply from e.g. Servercow or Hetzner.
Components of a complete mail system
You already know which software components are used. But which software takes over which tasks?
Dovecot
Dovecot is a widely used MDA (Mail Delivery Agent) and IMAP server. It sorts incoming e-mails into the mailboxes of the respective recipients and provides an interface for retrieving the mailbox (IMAP). In addition, Dovecot is used in this setup by Postfix as a so-called SASL authentication server: Postfix asks Dovecot whether a certain user is authorised to log on to the system.
Postfix
Postfix is often used together with Dovecot. The popular MTA (Mail Transfer Agent) takes care of everything that has to do with the transport of the e-mail: From the email client to its own mail server, and from there to the respective destination server. Postfix also accepts e-mails from foreign servers and forwards them to the MDA Dovecot. Anti-spam software is usually integrated directly into Postfix to prevent incoming spam from reaching the user’s mailbox in the first place.
Note: Postfix is “the actual mail server”. Emails can be sent and received solely with Postfix. However, all other components such as Dovecot and Rspamd make our lives easier 😉
MariaDB (MySQL database)
Dovecot and Postfix are configured to use a MySQL database as a backend (database). Domains to be used, users, aliases and other data are stored in the database. By simply adding or removing records in or from database tables, new users or aliases can be created or deleted. The advantage of a database backend is that it makes it very easy to manage the mail server: for example, a web interface in PHP could be developed for user management that modifies the MySQL database. The server configuration then does not have to be changed manually.
Rspamd
Rspamd is a filter system that is integrated into Postfix and checks incoming e-mails. Spam mails are recognised by Rspamd and not delivered to the user or sorted out. In addition, Rspamd adds a DKIM signature to outgoing e-mails so that foreign mail servers do not classify their own mails as suspicious.
Nginx
Nginx is a widely used and lean web server / web proxy. In this setup it has several tasks: Firstly, it can serve as an endpoint for the Let’s Encrypt certificate issuing process, secondly as a proxy for the Rspamd web interface, or to provide the autoconfiguration file for mail clients.
Redis
Redis is a high-performance in-memory key-value store, i.e. a very simple, fast database that can store key-value pairs efficiently in memory. Rspamd uses Redis to cache some data (such as last checked mail servers).
Preparations
Tip: Clear the table
If you have used the server before for something else (or even another mail setup), make sure that leftovers from old installations do not hinder the new setup. Especially previous mail server attempts should be removed without leaving any residue (incl. the associated configuration files). Of course, the best thing to do – if possible – is a complete reinstallation of the server. I recommend running the mail server as a stand-alone system and not installing any other services on the same host to ensure the integrity of the mail system.
In the following I assume a freshly installed Debian 10 Buster (additionally only “standard system tools” and SSH installed).
Login as root
During the installation of Debian, a normal user account, e.g. “thomas”, is set up to which you can connect via password. The root account is not directly accessible by default, but only via “su”. Root rights are permanently required for these instructions. So after logging in to the server, it is best to open a root command line via
su -
Then enter the password for your root user.
Updating the system
Before you install new software packages, you should update your system using
apt update && apt upgrade
to make sure your system is up to date. This is also a good opportunity to reboot your system to load a possibly updated Linux kernel.
Set host name and server FQDN
Local host name: For identifying the server within your own infrastructure, e.g. “mail”.
FQDN (Fully Qualified Domain Name): For worldwide identification on the Internet, e.g. “mail.testsys.de”.
The FQDN does not necessarily have to have anything to do with the domains for which e-mails will later be sent and received. It is only important that your future mail server has such a name, which can also be resolved to the server IP address via the DNS (more on this in the section “Setting up the DNS”). Set the local host name as follows:
hostnamectl set-hostname --static mail
The FQDN and local host name should be stored in the hosts file /etc/hosts. The file may look like this, for example:
127.0.0.1 localhost
127.0.1.1 mail.testsys.de mail
::1 localhost ip6-localhost ip6-loopback
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
The output of the hostname and hostname –fqdn commands should look like the following after the changes:
root@mail:~# hostname
mail
root@mail:~# hostname --fqdn
mail.testsys.de
The FQDN (in this example “mail.testsys.de”) is also written to /etc/mailname:
echo $(hostname -f) > /etc/mailname
(The host name in the shell prompt, e.g. root@myhost: only adjusts after a new login).
Install Unbound DNS Resolver
The mail system needs a functioning DNS server (resolver) so that the origin of e-mails can be checked. The Rspamd spam filter also relies on DNS services to evaluate spam mails. Fast name resolution therefore brings performance advantages for the entire mail system. For accessing spam house blocklists, it may even be necessary to use one’s own DNS resolver because, for example, accesses via Google DNS are blocked. For this reason (and to improve security with regard to dependencies on foreign systems), I recommend using your own local DNS resolver.
Install Unbound:
apt install unbound
A dig @::1 denic.de +short +dnssec should produce output similar to the following:
# dig @::1 denic.de +short +dnssec
A 8 2 3600 20170814090000 20170731090000 26155 denic.de. Jo90qnkLkZ6gI4qNHj19BMguFuGof9hCPhdeSh/fSePSQ/WXlWMmfjW1 sNDJ/bcITRMyz8DQdDzmWPDIeSJ/qPyfoZ+BjUZxtaXcs0BAl4KX8q7h R05TGmAbgPhrYBoUKJkU/q8T+jWKHAJRUeWbCd8QOJsJbneGcUKxRAPe i6Rq51/OL/id6zUCtalhclah2TfLLaqku9PmKwjbGdZm11BXSr8b56LB WX/rdLIrKWNpE+jHGAUMmDsZL84Kx3Oo
If the dig command worked, the local resolver can be set as the primary resolver:
apt install resolvconf
echo "nameserver ::1" >> /etc/resolvconf/resolv.conf.d/head
an nslookup denic.de | grep server should now
Server: ::1
back. This makes the local DNS resolver ready for use as the main resolver.
DNS Server Setup
At the beginning of this manual, the FQDN “mail.testsys.de” was set for the mail server. A-records are now created for this domain name in the DNS zone file of the domain “testsys.de”. Log in to your domain provider and create the following entries – the first for the IPv4 IP address of the mail server, the second for the IPv6 address. (Example!):
In the following, pay particular attention to the final dot in the domain names!
mail.testsys.de. 86400 IN A 203.0.113.1
mail.testsys.de. 86400 IN AAAA 2001:db8::1
“mail.testsys.de” is thus known in the DNS. If no IPv6 address is used, the second record can be omitted. This leaves “imap.testsys.de” and “smtp.testsys.de”, which are created as alias domains for “mail.testsys.de”. They are not absolutely necessary, but are searched for by many mail clients and are therefore common:
imap.testsys.de. 86400 IN CNAME mail.testsys.de.
smtp.testsys.de. 86400 IN CNAME mail.testsys.de.
Mail clients can already connect to the mail server via imap.testsys.de and smtp.testsys.de. Other mail servers, however, do not look for A or CNAME records when transmitting e-mails, but for MX records. An MX record shows which mail server is responsible for the e-mails to a domain. In my example, our mail server is supposed to take care of the e-mails for domain2.tld and domain3.tld in addition to the e-mails for testsys.de.
This record is created in the zone file of the domain “testsys.de”:
testsys.de. 86400 IN MX 0 mail.testsys.de.
In the zone files of the other domains, the following records are entered accordingly
testsystwo.de. 86400 IN MX 0 mail.testsys.de.
and:
domain3.de. 86400 IN MX 0 mail.testsys.de.
created.
Furthermore, a so-called reverse DNS record / PTR must be created for the FQDN of the mail server. This corresponds to the reverse of a normal DNS record and assigns a host name to an IP address. Only the owner of the network from which your IP address originates can create this record. You may be able to set a reverse DNS record in the administration interface of your server provider, or you can ask support to do so. The domain name that needs to be associated with the IP address is the FQDN of your mail server. In my example, mail.testsys.de. Remember to create such a record for all public IP addresses used by the mail server. In these instructions, one IPv4 and one IPv6 address is used.
Reverse DNS
SPF records
In the fight against spam and phishing, the so-called Sender Policy Framework was developed (“We will soon be writing an article on the precondition that one’s own mail server is not classified as a spam slinger.”). Although it has proven to be of limited use, most mail providers expect and check valid SPF records for other mail servers. SPF records are created in the zone file of all domains for which a mail server sends e-mail and indicate which servers are authorised to send for a domain. For our domain testsys.de, the following record is created in the zone file of testsys.de:
testsys.de. 3600 IN TXT v=spf1 a:mail.testsys.de mx ?all
Only the server named “mail.testsys.de” in the A-record for testsys.de receives send authorisation. The neutral setting “?all” ensures that e-mails from other servers are nevertheless accepted. This avoids problems with mail forwarding. We actually only create the SPF record so that other mail servers evaluate our server positively because of the existing record – not because it is supposed to be useful.
This record is created in the zone files of the two domains “domain2.tld” and “domain3.tld” (adapted to the domain):
testsystwo.de. 3600 IN TXT v=spf1 testsys.de ?all
The first record of the domain testsys.de is included via the “include”.
DMARC Record
DMARC entries determine what a foreign mail server should do if a mail it receives does not appear to come from the correct mail server after SPF and DKIM checks (i.e. if the sender has been forged). It is reasonable to instruct other mail servers not to accept such mail:
_dmarc.testsys.de. 3600 IN TXT v=DMARC1; p=reject;
The record is also set accordingly for the other domains:
_dmarc.testsystwo.de. 3600 IN TXT v=DMARC1; p=reject;
You can generate a DMARC record with a different policy yourself at https://elasticemail.com/dmarc/.
Initial configuration Nginx web server
As already mentioned, Nginx takes over various tasks in this setup. For now, however, it only serves as an HTTP endpoint to request Let’s Encrypt certificates. In principle, this is also possible without Nginx in standalone mode, but it makes life easier for us if we have it in operation anyway (=> ports occupied by Nginx, ACME client …).
To do this, Nginx is installed …
apt install nginx
… and created a new configuration with this content under /etc/nginx/sites-available/mail.testsys.de:
server {
listen 80;
listen [::]:80;
# listen 443 ssl http2;
# listen [::]:443 ssl http2;
server_name mail.testsys.de imap.testsys.de smtp.testsys.de;
# ssl_certificate /etc/acme.sh/mail.testsys.de/fullchain.pem;
# ssl_certificate_key /etc/acme.sh/mail.testsys.de/privkey.pem;
# add_header Strict-Transport-Security max-age=15768000;
# if ($ssl_protocol = "") {
# return 301 https://$server_name$request_uri;
# }
}
Some lines are deliberately commented out at this stage and will be reactivated later as soon as TLS certificates are available.
The new vHost can now be activated:
ln -s /etc/nginx/sites-available/mail.testsys.de /etc/nginx/sites-enabled/mail.testsys.de
systemctl reload nginx
Application for TLS certificates (via Let’s Encrypt)
Valid TLS certificates from recognised certification authorities (CAs) are a “must” for every mail server today. More and more mail systems are rightly refusing reception via unsecured connections. What used to be a significant cost factor (especially for private use) can now be obtained free of charge and very easily thanks to Let’s Encrypt. In the following, I therefore refer to the generation of Let’s Encrypt certificates. Of course, certificates from other CAs can also be used instead.
For Postfix and Dovecot we need certificates for the following domains:
mail.testsys.de
imap.testsys.de
smtp.testsys.de
To fetch the certificates from the Let’s Encrypt certificate authority, I use the slim acme.sh script. This has an “Nginx-Mode” in which the script automatically configures the Nginx webserver so that the domains can be verified by LE.
Install acme.sh:
curl https://get.acme.sh | sh
After installation, the shell profile must be reloaded so that the “acme.sh” command is made available:
source ~/.profile
Apply for and download certificates:
acme.sh --issue --nginx \
-d mail.testsys.de \
-d imap.testsys.de \
-d smtp.testsys.de
Install certificates:
mkdir -p /etc/acme.sh/mail.testsys.de
acme.sh --install-cert -d mail.testsys.de \
--key-file /etc/acme.sh/mail.testsys.de/privkey.pem \
--fullchain-file /etc/acme.sh/mail.testsys.de/fullchain.pem \
--reloadcmd "systemctl reload nginx; systemctl restart dovecot; systemctl restart postfix;"
As a result of our reload command, Acme.sh will try to reload Dovecot and Postfix. Since both software packages are not yet installed, you will get errors. You can ignore them for the time being.
The lines in /etc/nginx/sites-available/mail.testsys.de that were previously commented out in Nginx can now be activated by removing the hash characters and Nginx can be activated using
nginx -t
systemctl reload nginx
tested and restarted.
For the autoconfiguration of the mail clients, a certificate for another domain will be requested later – but that can wait for now.
In order for the automatic certificate renewal to work, the cronjob for acme.sh is activated:
acme.sh --install-cronjob
Set up MySQL database
Information about domains to be managed, users, forwardings and other settings is to be drawn by the mail server from a MySQL database. This has the advantage that the server can be flexibly adapted during operation without having to change the configuration files. The database also allows us to have a virtualised mail server setup: The users on the mail servers no longer have to be registered as real Linux users in the system, but only have to be entered in the database.
The new Debian standard MySQL database “MariaDB” is installed as DBMS:
apt install mariadb-server
After the installation, MariaDB should already be started. You can check the status with systemctl status mysql (not “mariadb!”). If this is not the case, start the database server: systemctl start mysql.
By default, only the root system user can log on to the database server. He is automatically authenticated via PAM, so that no additional password entry is necessary. The simple entry of
mysql
brings you to a MySQL root shell. A few SQL commands are now executed via this shell.
An SQL command always ends with a semicolon ;. You can easily break multi-line commands with ENTER, as they are shown below. Note the difference between “tick” (‘) and “backtick” ( \ `) – the backtick is created with Shift + 2x Accent key. It is best to copy the SQL statements directly into your intermediate system instead of laboriously typing them out.
In the first step, a new database “vmail” is created.
create database vmail
CHARACTER SET 'utf8';
A new DB user vmail with the password vmaildbpass gets access to this new database (Choose your own password instead of “vmaildbpass”!):
grant select on vmail.* to 'vmail'@'localhost' identified by 'vmaildbpass';
All further commands for creating the database tables should refer to the database just created:
use vmail;
The mail setup should use 4 different tables. Copy the SQL statements one by one into the MySQL command line and confirm each time with [Enter]. Adjustments are not necessary.
Domain-Table
CREATE TABLE `domains` (
`id` int unsigned NOT NULL AUTO_INCREMENT,
`domain` varchar(255) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY (`domain`)
);
Account-Table
CREATE TABLE `accounts` (
`id` int unsigned NOT NULL AUTO_INCREMENT,
`username` varchar(64) NOT NULL,
`domain` varchar(255) NOT NULL,
`password` varchar(255) NOT NULL,
`quota` int unsigned DEFAULT '0',
`enabled` boolean DEFAULT '0',
`sendonly` boolean DEFAULT '0',
PRIMARY KEY (id),
UNIQUE KEY (`username`, `domain`),
FOREIGN KEY (`domain`) REFERENCES `domains` (`domain`)
);
The account table contains all mail server accounts. The field “quota” contains the volume limit for the mailbox in MB (megabytes). In the “enabled” field, a boolean value determines whether an account is active or not. This allows individual users to be temporarily deactivated without having to be deleted. “sendonly” is set to “true” if the account is only to be used for sending e-mails – but not for receiving them. This can be useful, for example, for forum or blog software that should only send e-mails with its account.
Fast Fact
Alias-Table
CREATE TABLE `aliases` (
`id` int unsigned NOT NULL AUTO_INCREMENT,
`source_username` varchar(64),
`source_domain` varchar(255) NOT NULL,
`destination_username` varchar(64) NOT NULL,
`destination_domain` varchar(255) NOT NULL,
`enabled` boolean DEFAULT '0',
PRIMARY KEY (`id`),
UNIQUE KEY (`source_username`, `source_domain`, `destination_username`, `destination_domain`),
FOREIGN KEY (`source_domain`) REFERENCES `domains` (`domain`)
);
The alias table contains all forwarding addresses / aliases and is actually self-explanatory. For temporary deactivation of forwarding addresses there is again an “enabled” field.
TLS Policy Table
CREATE TABLE `tlspolicies` (
`id` int unsigned NOT NULL AUTO_INCREMENT,
`domain` varchar(255) NOT NULL,
`policy` enum('none', 'may', 'encrypt', 'dane', 'dane-only', 'fingerprint', 'verify', 'secure') NOT NULL,
`params` varchar(255),
PRIMARY KEY (`id`),
UNIQUE KEY (`domain`)
);
The TLS policy table can be used to specify which recipient domains are to be subject to certain security restrictions during mail transport. For individual domains, e.g. “gmx.de”, it can be specified that these e-mails may only be transmitted in encrypted form. More on this later.
The database will be filled with data records as soon as the servers are configured. Until then, you can quit the MySQL command line with quit;.
Set up vmail user and directory
All mailboxes are stored directly in the file system of the Debian server. For access to the mailbox directories, a separate user “vmail” (“Virtual Mail”) is created, under which the accesses of Dovecot and other components of the mail server should happen. On the one hand, this prevents mail server components from accessing sensitive system directories, and on the other hand, it allows us to protect the mailboxes from outside access. Only vmail (and root) are allowed to access the mailboxes.
The directory /var/vmail/ should contain all mailserver-relevant files (i.e. mailboxes and filter scripts) and is set as the home directory for the vmail user.
Create vmail user:
useradd --create-home --home-dir /var/vmail --user-group --shell /usr/sbin/nologin vmail
Create vmail subdirectories:
mkdir /var/vmail/mailboxes
mkdir -p /var/vmail/sieve/global
Recursively assign the directory /var/vmail to the vmail user and set the appropriate directory rights:
chown -R vmail /var/vmail
chgrp -R vmail /var/vmail
chmod -R 770 /var/vmail
Install and configure Dovecot
After the database and the vmail user have been created, we now turn to the Dovecot server. As already mentioned, this server manages the mailboxes and therefore gets exclusive access to /var/vmail/ (in the form of the vmail user). First, however, all server components must be installed:
apt install dovecot-core dovecot-imapd dovecot-lmtpd dovecot-mysql dovecot-sieve dovecot-managesieved
- dovecot-core: Dovecot core
- dovecot-imapd: Adds IMAP functionality.
- dovecot-lmtp: Adds LMTP (Local Mail Transfer Protocol) functionality; LMTP is used as the MTP protocol between Postfix and Dovecot.
- dovecot-mysql: Lets Dovecot work with the MySQL database.
- dovecot-sieve: Adds filter functionality
- dovecot-managesieved: Provides an interface to set up the filters via mail client.
After installation, Dovecot is started automatically. Stops Dovecot as long as we do not have a finished configuration:
systemctl stop dovecot
Now it’s time for the configuration. The Dovecot configuration files are located in the /etc/dovecot/ directory. There you can already see some configurations that were created during the installation. We will set up the configuration from scratch – therefore the entire Dovecot configuration will be deleted first:
rm -r /etc/dovecot/*
cd /etc/dovecot
For Dovecot, the following two configuration files (dovecot.conf and dovecot-sql.conf) are sufficient. Create the two files in the /etc/dovecot/ directory.
Mainconfiguration/etc/dovecot/dovecot.conf
##
## Aktivierte Protokolle
##
protocols = imap lmtp sieve
##
## TLS Config
## Quelle: https://ssl-config.mozilla.org/#server=dovecot&version=2.3.9&config=intermediate&openssl=1.1.1d&guideline=5.4
##
ssl = required
ssl_cert = </etc/acme.sh/mail.testsys.de/fullchain.pem
ssl_key = </etc/acme.sh/mail.testsys.de/privkey.pem
ssl_dh = </etc/dovecot/dh4096.pem
ssl_min_protocol = TLSv1.2
ssl_cipher_list = ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384
ssl_prefer_server_ciphers = no
##
## Dovecot services
##
service imap-login {
inet_listener imap {
port = 143
}
}
service managesieve-login {
inet_listener sieve {
port = 4190
}
}
service lmtp {
unix_listener /var/spool/postfix/private/dovecot-lmtp {
mode = 0660
group = postfix
user = postfix
}
user = vmail
}
service auth {
### Auth socket für Postfix
unix_listener /var/spool/postfix/private/auth {
mode = 0660
user = postfix
group = postfix
}
### Auth socket für LMTP-Dienst
unix_listener auth-userdb {
mode = 0660
user = vmail
group = vmail
}
}
##
## Protocol settings
##
protocol imap {
mail_plugins = $mail_plugins quota imap_quota imap_sieve
mail_max_userip_connections = 20
imap_idle_notify_interval = 29 mins
}
protocol lmtp {
postmaster_address = postmaster@testsys.de
mail_plugins = $mail_plugins sieve notify push_notification
}
##
## Client authentication
##
disable_plaintext_auth = yes
auth_mechanisms = plain login
auth_username_format = %Lu
passdb {
driver = sql
args = /etc/dovecot/dovecot-sql.conf
}
userdb {
driver = sql
args = /etc/dovecot/dovecot-sql.conf
}
##
## Address tagging
##
recipient_delimiter = +
##
## Mail location
##
mail_uid = vmail
mail_gid = vmail
mail_privileged_group = vmail
mail_home = /var/vmail/mailboxes/%d/%n
mail_location = maildir:~/mail:LAYOUT=fs
##
## Mailbox configuration
##
namespace inbox {
inbox = yes
mailbox Spam {
auto = subscribe
special_use = \Junk
}
mailbox Trash {
auto = subscribe
special_use = \Trash
}
mailbox Drafts {
auto = subscribe
special_use = \Drafts
}
mailbox Sent {
auto = subscribe
special_use = \Sent
}
}
##
## Mail plugins
##
plugin {
sieve_plugins = sieve_imapsieve sieve_extprograms
sieve_before = /var/vmail/sieve/global/spam-global.sieve
sieve = file:/var/vmail/sieve/%d/%n/scripts;active=/var/vmail/sieve/%d/%n/active-script.sieve
###
### Spam learning
###
# From elsewhere to Spam folder
imapsieve_mailbox1_name = Spam
imapsieve_mailbox1_causes = COPY
imapsieve_mailbox1_before = file:/var/vmail/sieve/global/learn-spam.sieve
# From Spam folder to elsewhere
imapsieve_mailbox2_name = *
imapsieve_mailbox2_from = Spam
imapsieve_mailbox2_causes = COPY
imapsieve_mailbox2_before = file:/var/vmail/sieve/global/learn-ham.sieve
sieve_pipe_bin_dir = /usr/bin
sieve_global_extensions = +vnd.dovecot.pipe
quota = maildir:User quota
quota_exceeded_message = Benutzer %u hat das Speichervolumen überschritten. / User %u has exhausted allowed storage space.
}
Points to be adjusted:
Please adapt to your own config
– ssl_cert: Path to the certificate file
– ssl_key: Path to the certificate file
– postmaster_address: Adapt domain
Explanation
dovecot.conf is the main configuration file of the Dovecot server:
Dovecot Services: In the following section, the Dovecot Services are configured. This includes, for example, the service “imap-login”, which listens for incoming connections from email clients on port 143. Also “managesieve-login” communicates with the mail client if it has a function for processing server-side filter scripts. The other services are used internally: The lmtp service provides an interface through which Postfix can pass received mail to the mailbox. The “auth” service is used by the LMTP service to check the existence of users, but also by Postfix to check the login at the Postfix server. Mode”, “user” and “group” are used to determine which system user should have access to the service (analogous to file rights – the socket for the service is nothing other than a file).
Protocol settings: Additional settings can be made for the protocols used – including which extensions are to be used in connection with the protocol. “quota” and “imap_quota” are necessary to set the maximum volume of a mailbox. With the lmtp protocol, these extensions can be dispensed with: Here, only the Sieve extension is needed to filter e-mails.
Client Authentication: The Lines
disable_plaintext_auth = yes
auth_mechanisms = plain login
seem to contradict each other, after all, plain-text authentication will be disabled. But in fact it will only for unencrypted connections. TLS-encrypted connections are unaffected, so “plain” authentication with plaintext passwords can be offered again in the next line. This is done for two reasons:
- “Plain text” doesn’t hurt us here – after all, the connection is (compulsorily) encrypted anyway.
- All mail clients support plain text authentication. Other login mechanisms are less well supported and more complex.
We therefore concentrate on classic plain text authentication. As already mentioned: Since our connection is encrypted anyway, this is not security-relevant in this case.
For passdb and userdb, the path to the SQL file is set. There is a suitable SQL query in each case. The “passdb” is queried when users need to be authenticated, the “userdb” when the existence of a certain e-mail account needs to be checked or user-defined settings need to be loaded, e.g. the mailbox quota.
Mail location: This section defines the system user under which Dovecot should handle emails at file system level. In addition, a path scheme is defined that determines the structure according to which the mailbox directories are to be created. %d stands for the domain of the account and %n for the user name before the @. The path to a user mailbox is e.g.: /var/vmail/mailboxes/testsys.de/admin/mail/
Mailbox Configuration: By default, there should be a “Spam” folder in each user’s mailbox, into which a suitable Sieve filter script should move suspicious e-mails.
Mail Plugins: Here the details of the extensions sieve, quota and imapsieve are defined. The script under sieve_before is always executed for all users (regardless of their own settings). It has the task of moving mails marked by Rspamd to the spam folder. sieve_dir defines the scheme for the location where user-defined scripts are stored. A user’s active script should be accessible via the symbolic link active-script.sieve. The imapsieve settings let the IMAP server detect moves between mailbox folders so that Rspamd can learn from a reordering.
Generate Diffie-Hellman parameters for Dovecot
In newer versions, Dovecot no longer generates the Diffie-Hellman parameters for TLS connections itself. So we have to do it ourselves and generate the parameters using the OpenSSL tool:
openssl dhparam -out /etc/dovecot/dh4096.pem 4096
Depending on the load on the mail server, this may well take a quarter of an hour or longer. To speed up the curtain, a so-called entropy harvester such as haveged can be installed (apt install haveged).
SQL-Config /etc/dovecot/dovecot-sql.conf
driver=mysql
connect = "host=localhost dbname=vmail user=vmail password=vmaildbpass"
default_pass_scheme = SHA512-CRYPT
password_query = SELECT username AS user, domain, password FROM accounts WHERE username = '%Ln' AND domain = '%Ld' and enabled = true;
user_query = SELECT concat('*:storage=', quota, 'M') AS quota_rule FROM accounts WHERE username = '%Ln' AND domain = '%Ld' AND sendonly = false;
iterate_query = SELECT username, domain FROM accounts where sendonly = false;
Anzupassende Stellen:
Please choose your own password
– Database password “vmaildbpass
chmod 440 dovecot-sql.conf
Explanation
The configuration file dovecot-sql.conf contains all SQL-relevant settings:
- driver: Which database driver should be used?
- connect: Information about the database connection
- default_pass_scheme: Hash scheme assumed by default if not explicitly specified in the database, e.g. prefixed with {SHA512-CRYPT}.
- password_query: SQL query for checking the user login. Do the user name and password match? Does the user exist and is it activated?
- user_query: SQL query to retrieve all user-specific settings. In this case: Maximum mailbox volume (“quota”).
- iterate_query: SQL query to retrieve all available users. Users who cannot receive mails (sendonly=true) are not interesting for Dovecot and are not output.
Global Sieve Filter Script for Spam
Under /var/vmail/sieve/global/
, the Sieve filter script spam-global.sieve is created, which sorts detected spam mails into the “Spam” subfolder of each mailbox. Rspamd marks detected emails with a special spam header that the script recognises. Contents of spam-global.sieve:
require "fileinto";
if header :contains "X-Spam-Flag" "YES" {
fileinto "Spam";
}
if header :is "X-Spam" "Yes" {
fileinto "Spam";
}
Spam learning with Rspamd
When moving spam mails to the spam folder or moving wrongly judged mails out to the inbox, a learning process should be triggered by Rspamd so that the filter learns from wrong assessments and thus becomes better and better over time.
For this purpose, two sieve scripts are created in /var/vmail/sieve/global/:
learn-spam.sieve
require ["vnd.dovecot.pipe", "copy", "imapsieve"];
pipe :copy "rspamc" ["learn_spam"];
learn-ham.sieve
require ["vnd.dovecot.pipe", "copy", "imapsieve", "environment", "variables"];
if environment :matches "imap.mailbox" "*" {
set "mailbox" "${1}";
}
if string "${mailbox}" "Trash" {
stop;
}
pipe :copy "rspamc" ["learn_ham"];
The learn-ham.sieve
script also has a check that checks whether an email has been moved from spam to the trash. In this case, the affected e-mails should not be marked as “Ham” again, so the execution of the learning process is prevented in such a case.
Install and configure Postfix
For our postfix server we only need two packages: The core package postfix and the component postfix-mysql, which lets Postfix communicate with the MySQL database.
apt install postfix postfix-mysql
During the installation you will be asked for the “General type of configuration”. Select “No configuration” at this point and stop the Postfix server again:
systemctl stop postfix
In the Postfix configuration directory /etc/postfix, despite our choice of “No configuration”, there are a few configuration files that are removed first:
cd /etc/postfix
rm -r sasl
rm master.cf main.cf.proto master.cf.proto
Then create the following files in the /etc/postfix directory:
/etc/postfix/main.cf
##
## Network settings
##
mynetworks = 127.0.0.0/8 [::ffff:127.0.0]/104 [::1]/128
inet_interfaces = 127.0.0.1, ::1, 203.0.113.1, 2001:db8::1
myhostname = mail.testsys.de.tld
##
## Mail queue settings
##
maximum_queue_lifetime = 1h
bounce_queue_lifetime = 1h
maximum_backoff_time = 15m
minimum_backoff_time = 5m
queue_run_delay = 5m
##
## TLS settings
## Source: https://ssl-config.mozilla.org/#server=postfix&version=3.4.8&config=intermediate&openssl=1.1.1d&guideline=5.4
##
### General
tls_preempt_cipherlist = no
tls_ssl_options = NO_COMPRESSION
tls_medium_cipherlist = ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384: ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384
### Outgoing SMTP connections (Postfix as sender)
smtp_tls_security_level = dane
smtp_dns_support_level = dnssec
smtp_tls_policy_maps = proxy:mysql:/etc/postfix/sql/tls-policy.cf
smtp_tls_session_cache_database = btree:${data_directory}/smtp_scache
smtp_tls_ciphers = medium
smtp_tls_CAfile = /etc/ssl/certs/ca-certificates.crt
### Incoming SMTP connections
smtpd_tls_security_level = may
smtpd_tls_auth_only = yes
smtpd_tls_ciphers = medium
smtpd_tls_mandatory_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1
smtpd_tls_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1
smtpd_tls_session_cache_database = btree:${data_directory}/smtpd_scache
smtpd_tls_cert_file=/etc/acme.sh/mail.testsys.de/fullchain.pem
smtpd_tls_key_file=/etc/acme.sh/mail.testsys.de/privkey.pem
smtpd_tls_dh1024_param_file = /etc/postfix/dh2048.pem
##
## Local mail delivery to Dovecot
##
virtual_transport = lmtp:unix:private/dovecot-lmtp
##
## Spam filter and DKIM signatures via Rspamd
##
smtpd_milters = inet:localhost:11332
non_smtpd_milters = inet:localhost:11332
milter_protocol = 6
milter_mail_macros = i {mail_addr} {client_addr} {client_name} {auth_authen}
milter_default_action = accept
##
## Server Restrictions for Clients, Recipients and Relaying
## (in relation to S2S connections. Mail client connections are configured in master.cf in the submission section).
##
### Conditions for Postfix to work as a relay (for clients)
smtpd_relay_restrictions = reject_non_fqdn_recipient
reject_unknown_recipient_domain
permit_mynetworks
reject_unauth_destination
### Conditions for Postfix to accept incoming e-mails as recipient server (in addition to relay conditions)
### check_recipient_access checks if an account is sendonly
smtpd_recipient_restrictions = check_recipient_access proxy:mysql:/etc/postfix/sql/recipient-access.cf
### Conditions that SMTP clients must meet (sending servers)
smtpd_client_restrictions = permit_mynetworks
check_client_access hash:/etc/postfix/without_ptr
reject_unknown_client_hostname
### If unknown servers connect, they must have a valid hostname in the HELO.
smtpd_helo_required = yes
smtpd_helo_restrictions = permit_mynetworks
reject_invalid_helo_hostname
reject_non_fqdn_helo_hostname
reject_unknown_helo_hostname
# Block clients if they try to send too early
smtpd_data_restrictions = reject_unauth_pipelining
##
## Restrictions for MUAs (mail user agents)
##
mua_relay_restrictions = reject_non_fqdn_recipient,reject_unknown_recipient_domain,permit_mynetworks,permit_sasl_authenticated,reject
mua_sender_restrictions = permit_mynetworks,reject_non_fqdn_sender,reject_sender_login_mismatch,permit_sasl_authenticated,reject
mua_client_restrictions = permit_mynetworks,permit_sasl_authenticated,reject
##
## MySQL queries
##
proxy_read_maps = proxy:mysql:/etc/postfix/sql/aliases.cf
proxy:mysql:/etc/postfix/sql/accounts.cf
proxy:mysql:/etc/postfix/sql/domains.cf
proxy:mysql:/etc/postfix/sql/recipient-access.cf
proxy:mysql:/etc/postfix/sql/sender-login-maps.cf
proxy:mysql:/etc/postfix/sql/tls-policy.cf
virtual_alias_maps = proxy:mysql:/etc/postfix/sql/aliases.cf
virtual_mailbox_maps = proxy:mysql:/etc/postfix/sql/accounts.cf
virtual_mailbox_domains = proxy:mysql:/etc/postfix/sql/domains.cf
local_recipient_maps = $virtual_mailbox_maps
##
## Other
##
### Maximum size of the entire mailbox (to be set by Dovecot, 0 = unlimited)
mailbox_size_limit = 0
### Maximum size of incoming emails in bytes (50 MB)
message_size_limit = 52428800
### No system notification for user when new e-mail is received
biff = no
### Users must always provide full email address - not just hostname
append_dot_mydomain = no
### Separator for address tagging
recipient_delimiter = +
### Do not allow conclusions about used mail addresses
disable_vrfy_command = yes
To be adapted:
- inet_interfaces: IP addresses 203.0.113.1, 2001:db8::1 must be replaced by own IPv4 (and optionally IPv6) address.
myhostname: Replace with own hostname - smtpd_tls_cert_file: Path to the certificate file
- smtpd_tls_key_file: Path to the certificate file
Generate Diffie-Hellman parameters for Postfix
Besides Dovecot, Postfix also gets “hand-generated” DH parameters. Here, however, only 2048 bit strong, in order to remain compatible with older mail servers.
openssl dhparam -out /etc/postfix/dh2048.pem 2048
By the way, don’t be surprised about the 1024 in the smtpd_tls_dh1024_param_file setting – it’s just part of the name and has no meaning for the key length.
Explanation Network settings:
– mynetworks: Requests from these IP addresses / from these IP address ranges are handled separately by Postfix (use for “mynetworks” in the restrictions). Usually, the local address ranges and IP addresses from one’s own network are entered here, e.g. from other own, trustworthy servers.
– net_interfaces: Postfix should open its ports on these IP addresses. The IP addresses must be adapted to your own server.
– myhostname: The host name of the mail server as it is to be used for mail processing.
Mail-Queue Settings:
E-mails in Postfix are “queued”, i.e. entered in a queue that is regularly processed. If mails are undeliverable, they remain in the queue for a certain time until their lifetime has expired and they are removed from the queue. The sender of the e-mail then receives a corresponding message informing him/her of the undeliverability.
- maximum_queue_lifetime: Lifetime of a normal message in the queue. If an e-mail could not be delivered within one hour, it is removed from the queue and the sender is notified.
bounce_queue_lifetime: Lifetime of an undeliverable notification in the queue. - maximum_backoff_time: Maximum time that may elapse before a new delivery attempt is started for an e-mail.
- minimum_backoff_time: Minimum time that must elapse before a new delivery attempt is started.
- queue_run_delay: Interval in which the queue is searched for undeliverable e-mails.
TLS settings:
Compression is switched off and (as with Dovecot) a cipher list is specified so that the best possible encryption between client and server is used. In the first section, the “smtp”-specific TLS settings are defined – i.e. the settings that affect Postfix as the sending communication partner (mail client).
- smtp_tls_security_level: Standard TLS policy, if not otherwise specified in the database for the recipient domain: “dane” first checks whether there is a TLSA entry (DANE) in the DNS for the recipient server. If this is the case, an encrypted connection is forced and the server certificate shown is verified by means of a TLSA entry. If no TLSA entry is available, Postfix falls back to the policy “may” and only encrypts if the other server supports it. Certificates are not validated in this case. If existing TLSA entries are invalid, the “encrypt” policy is used instead, which encrypts compulsorily but does not validate certificates either. More about the TLS policies will follow later.
- smtp_dns_support_level: Activate and use DNSSEC-secured DNS lookups if possible
- smtpd_tls_policy_maps: References the SQL queries used to load recipient domain-specific TLS settings.
- smtp_tls_protocols: Deprecated SSL/TLS protocols are deactivated.
Now to the second TLS block: This applies to incoming connections. Both for other servers and mail clients. Again, SSL v2 and 3 are deactivated and a strong cipherlist is selected. Incoming connections can be encrypted, but do not have to be.
LMTP service:
virtual_transport transmits processed incoming emails to Dovecot’s LMTP service, which then takes care of putting the mail into the appropriate mailbox.
Spam filter and DKIM signatures via Rspamd:
This section defines the Rspam daemon as a milter for incoming and outgoing emails. Incoming e-mails are checked by Rspamd for their seriousness – outgoing ones are signed with a DKIM key.
Server Restrictions:
The blocks under “Server restrictions” are particularly important for the security of the mail server. If set incorrectly, they allow the unauthorised sending of e-mails (keyword “Open Relay”). The mail server is then misused as a spam slinger and very quickly ends up on a blacklist. To prevent this from happening, the restrictions should be carefully set and checked with a suitable open relay detector.
The restrictions are processed one after the other in the direction of reading. At the end of each processing there is always a “permit” or “reject”. For a better understanding, here is an example:
smtpd_relay_restrictions = reject_non_fqdn_recipient
reject_unknown_recipient_domain
permit_mynetworks
reject_unauth_destination
smtpd_relay_restrictions
determines the conditions under which Postfix works as a mail relay (“switch”). Our postfix should only react to incoming emails in three cases:
- When a mail client wants to send an e-mail to the Internet via Postfix
- When a foreign mail server sends an e-mail to our Postfix
- When a mail is to be sent from the mail server itself
The first case is taken care of in the master.cf file. There, the relay restrictions in the submission area are overwritten so that mail clients are not prevented from sending freely. Currently, only the last two request types are of interest. The first line of the restriction is reject_non_fqdn_recipien. If the recipient’s address is not a fully-fledged e-mail address, the request to Postfix is rejected directly. All other checks will then no longer take place. As a result, Postfix will only accept further processing if the e-mail to be processed has a valid recipient. The same applies to reject_unknown_recipient_domain: If the recipient domain does not have a valid MX or A record in the DNS (and the destination server is thus not fixed), the e-mail is rejected.
The following line contains the “Restriction” permit_mynetwork. If the requester is local (or his IP is noted in mynetworks), he is waved through with a permit and the e-mail is processed further. No further checks will then take place. If the sender is not registered in mynetworks, the last check is carried out: reject_unauth_destination can only be passed if the e-mail to be processed goes to a recipient address of this mail system. If no permit or reject has been triggered by the end of the restriction definition, a permit is automatically triggered and the respective action is allowed.
All other restriction definitions function similarly: The criteria are checked one after the other. If a criterion begins with a reject, a reject is triggered if it is true; if it begins with a permit, a permit is triggered. In both cases, the subsequent criteria are no longer checked.
- smtpd_relay_restrictions: Criteria that are checked when requests arrive at the Postfix server (From foreign mail servers or from the own server, e.g. via sendmail).
- smtpd_recipient_restrictions: Criteria that are checked in addition to the relay_restrictions. An e-mail is only accepted on the local system and sent to the recipient’s mailbox if the checks are passed. At this point, an SQL query asks whether a certain recipient should be able to receive e-mails (=> see option in the database to enable accounts for sending only).
- smtpd_client-restrictions: Criteria for which other servers are checked when contact is made with the postfix server. (Must have valid hostname and reverse DNS entry).
- smtpd_helo_restrictions: Foreign servers must state their valid host name at the beginning.
- smtpd_data_restrictions: Impatient servers are often spammers.
MySQL queries:
Here are the paths to the remaining SQL files that Postfix needs to be able to query data from the database.
/etc/postfix/master.cf
# ==========================================================================
# service type private unpriv chroot wakeup maxproc command + args
# (yes) (yes) (no) (never) (100)
# ==========================================================================
###
### SMTP server connections from the Internet
### Authentication not allowed here (logon only via smtps/submission!)
smtp inet n - y - 1 smtpd
-o smtpd_sasl_auth_enable=no
###
### SMTPS Service (Submission with implicit TLS - without STARTTLS) - Port 465
### Different rules apply for mail clients than for other mail servers (see smtpd_ in main.cf)
###
smtps inet n - y - - smtpd
-o syslog_name=postfix/smtps
-o smtpd_tls_wrappermode=yes
-o smtpd_tls_security_level=encrypt
-o smtpd_sasl_auth_enable=yes
-o smtpd_sasl_type=dovecot
-o smtpd_sasl_path=private/auth
-o smtpd_sasl_security_options=noanonymous
-o smtpd_client_restrictions=$mua_client_restrictions
-o smtpd_sender_restrictions=$mua_sender_restrictions
-o smtpd_relay_restrictions=$mua_relay_restrictions
-o milter_macro_daemon_name=ORIGINATING
-o smtpd_sender_login_maps=proxy:mysql:/etc/postfix/sql/sender-login-maps.cf
-o smtpd_helo_required=no
-o smtpd_helo_restrictions=
-o cleanup_service_name=submission-header-cleanup
###
### Submission access for clients (with STARTTLS - for backwards compatibility) - port 587
###
submission inet n - y - - smtpd
-o syslog_name=postfix/submission
-o smtpd_tls_security_level=encrypt
-o smtpd_sasl_auth_enable=yes
-o smtpd_sasl_type=dovecot
-o smtpd_sasl_path=private/auth
-o smtpd_sasl_security_options=noanonymous
-o smtpd_client_restrictions=$mua_client_restrictions
-o smtpd_sender_restrictions=$mua_sender_restrictions
-o smtpd_relay_restrictions=$mua_relay_restrictions
-o milter_macro_daemon_name=ORIGINATING
-o smtpd_sender_login_maps=proxy:mysql:/etc/postfix/sql/sender-login-maps.cf
-o smtpd_helo_required=no
-o smtpd_helo_restrictions=
-o cleanup_service_name=submission-header-cleanup
###
### Other important services for server operation
###
pickup unix n - y 60 1 pickup
cleanup unix n - y - 0 cleanup
qmgr unix n - n 300 1 qmgr
tlsmgr unix - - y 1000? 1 tlsmgr
rewrite unix - - y - - trivial-rewrite
bounce unix - - y - 0 bounce
defer unix - - y - 0 bounce
trace unix - - y - 0 bounce
verify unix - - y - 1 verify
flush unix n - y 1000? 0 flush
proxymap unix - - n - - proxymap
proxywrite unix - - n - 1 proxymap
smtp unix - - y - - smtp
relay unix - - y - - smtp
showq unix n - y - - showq
error unix - - y - - error
repeat unix - - y - - error
discard unix - - y - - discard
local unix - n n - - local
virtual unix - n n - - virtual
lmtp unix - - y - - lmtp
amvil unix - - y - 1 amvil
scache unix - - y - 1 scache
###
### Cleanup service to remove MUA headers
###
submission-header-cleanup unix n - n - 0 cleanup
-o header_checks=regexp:/etc/postfix/submission_header_cleanup
I will only explain the /etc/postfix/master.cf file in general terms. It is important to know that the definition and configuration of the various Postfix services such as smtpd (incoming SMTP connections) and smtp (outgoing SMTP connections) happens here. It is easy to see that further parameters are passed to a service via an -o. This is the case, for example, with the smtps service, which is available on port 465 for SMTP communication with the mail clients: The settings specified here, e.g. for smtpd_relay_restrictions, overwrite the settings in main.cf – but only for this one specific service! A good example is the setting smtpd_tls_security_level=encrypt, which is in the submission block. In the main.cf we had defined “may” here in order not to exclude servers that do not know TLS. Since smtpd settings apply to other servers as well as to mail clients, this would also say to the mail clients: “You can establish encrypted connections – but you don’t have to”. Of course we don’t want that! Mail clients should have to establish an encrypted connection! Therefore, the smtpd setting specifically for the smtps service is overwritten using the -o option and set to “encrypt”.
The smtps service at the beginning of the file is the SMTP service to which mail clients are to connect later. A connection here is only possible via direct TLS (not StartTLS!). For clients that want to connect to port 587, the submission service below is still available (even if it should no longer be necessary in many cases).
For better data protection, the “Received” header (+ other privacy-relevant headers) is removed from incoming e-mails when they arrive via the smtps port. Most email clients send their name and version as well. In addition, Postfix notes which IP address the e-mail comes from for incoming e-mails. We can do without this information, so it is deleted from the e-mail with the help of a small additional service submission-header-cleanup (at the end of the configuration). In the smtps and submission area, cleanup_service_name is used to specify that the filter is to be applied to incoming mails on these services. The filter rules are located in the file /etc/postfix/submission_header_cleanup.
Header Cleanup Rules:
A file with the following content is created under /etc/postfix/submission_header_cleanup:
### Removes privacy-relevant headers from e-mails from MTUAs
/^Received:/ IGNORE
/^X-Originating-IP:/ IGNORE
/^X-Mailer:/ IGNORE
/^User-Agent:/ IGNORE
SQL configuration:
In addition to the main configuration main.cf and the service configuration master.cf, a few configuration files are created within the subdirectory sql/, which contain the SQL queries for the data queries to the database:
mkdir /etc/postfix/sql && cd $_
Then create the following configuration files with the associated content:
accounts.cf
user = vmail
password = vmaildbpass
hosts = unix:/run/mysqld/mysqld.sock
dbname = vmail
query = select 1 as found from accounts where username = '%u' and domain = '%d' and enabled = true
aliases.cf
user = vmail
password = vmaildbpass
hosts = unix:/run/mysqld/mysqld.sock
dbname = vmail
query = SELECT DISTINCT concat(destination_username, '@', destination_domain) AS destinations FROM aliases
WHERE (source_username = '%u' OR source_username IS NULL) AND source_domain = '%d'
AND enabled = true
AND NOT EXISTS (SELECT id FROM accounts WHERE username = '%u' and domain = '%d');
domains.cf
user = vmail
password = vmaildbpass
hosts = unix:/run/mysqld/mysqld.sock
dbname = vmail
query = SELECT domain FROM domains WHERE domain='%s';
recipient-access.cf
user = vmail
password = vmaildbpass
hosts = unix:/run/mysqld/mysqld.sock
dbname = vmail
query = select if(sendonly = true, 'REJECT', 'OK') AS access from accounts where username = '%u' and domain = '%d' and enabled = true LIMIT 1;
sender-login-maps.cf
user = vmail
password = vmaildbpass
hosts = unix:/run/mysqld/mysqld.sock
dbname = vmail
query = select concat(username, '@', domain) as 'owns' from accounts where username = '%u' AND domain = '%d' and enabled = true union select
concat(destination_username, '@', destination_domain) AS 'owns' from aliases
where source_username = '%u' and source_domain = '%d' and enabled = true;
tls-policy.cf
user = vmail
password = vmaildbpass
hosts = unix:/run/mysqld/mysqld.sock
dbname = vmail
query = SELECT policy, params FROM tlspolicies WHERE domain = '%s';
Don’t forget to replace vmaildbpass in each of the files with your own password!
All SQL configuration files in /etc/postfix/sql are protected from access by unauthorised users:
Other Postfix configuration files
There is also another file /etc/postfix/without_ptr, which can be left empty for the time being:
touch /etc/postfix/without_ptr
The file may later contain entries like the following:
[2001:db8::beef] OK
The server with the IP 2001:db8::beef must then no longer have a valid PTR record (reverse DNS) and will still be accepted. The without_ptr file must then be converted into a database file after each change and Postfix must be reloaded:
postmap /etc/postfix/without_ptr
systemctl reload postfix
At the moment, however, it is sufficient to simply generate an empty database file:
postmap /etc/postfix/without_ptr
Finally, once
newaliases
to generate the alias file /etc/aliases.db that Postfix expects by default.
Rspamd
Since the Rspamd packages for Debian are not particularly up-to-date and it is officially discouraged to use them, we use the Debian repository of the Rspamd project here:
apt install -y lsb-release wget
wget -O- https://rspamd.com/apt-stable/gpg.key | apt-key add -
echo "deb http://rspamd.com/apt-stable/ $(lsb_release -c -s) main" > /etc/apt/sources.list.d/rspamd.list
echo "deb-src http://rspamd.com/apt-stable/ $(lsb_release -c -s) main" >> /etc/apt/sources.list.d/rspamd.list
Update package sources and install Rspamd
apt update
apt install rspamd
Stop Rspamd:
systemctl stop rspamd
Mainconfig:
The configuration of Rspamd is stored in the directory /etc/rspamd/local.d/. The following configuration files are created in it:
/etc/rspamd/local.d/worker-controller.inc: Setting of the worker controller: Password for access via web interface, e.g.:
password = "$2$qecacwgrz13owkag4gqcy5y7yeqh7yh4$y6i6gn5q3538tzsn19ojchuudoauw3rzdj1z74h5us4gd3jj5e8y";
The password hash ($2$qecacwg…) is entered via
rspamadm pw
and inserted into the file. Do not forget the final “;!
/etc/rspamd/local.d/logging.inc: Error logging
type = "syslog";
level = "warning";
Milter Headers /etc/rspamd/local.d/milter_headers.conf
use = ["x-spamd-bar", "x-spam-level", "authentication-results"];
authenticated_headers = ["authentication-results"];
Use Redis for the Bayesian filter: /etc/rspamd/local.d/classifier-bayes.conf
autolearn = true;
If an email is already rejected upon receipt because it obviously comes from a spammer due to the metadata, Rspamd takes the opportunity and learns that the text in this email is to be classified as spam. In this way, the detection rate improves with each spam email. (https://rspamd.com/doc/configuration/statistic.html)
Manually maintained black-/whitelists:
Via the Multimap module, the behaviour of Rspamd can be controlled in a personalised way for certain email characteristics. Characteristics can be, for example, the sender IP address or the sender email address. For both, we register a blacklist and a whitelist in /etc/rspamd/local.d/multimap.conf:
WHITELIST_IP {
type = "ip";
map = "$CONFDIR/local.d/whitelist_ip.map";
description = "Local ip whitelist";
action = "accept";
}
WHITELIST_FROM {
type = "from";
map = "$CONFDIR/local.d/whitelist_from.map";
description = "Local from whitelist";
action = "accept";
}
BLACKLIST_IP {
type = "ip";
map = "$CONFDIR/local.d/blacklist_ip.map";
description = "Local ip blacklist";
action = "reject";
}
BLACKLIST_FROM {
type = "from";
map = "$CONFDIR/local.d/blacklist_from.map";
description = "Local from blacklist";
action = "reject";
}
List files are now created for all four lists:
cd /etc/rspamd/local.d
touch whitelist_ip.map
touch whitelist_from.map
touch blacklist_ip.map
touch blacklist_from.map
cd -
“IP” lists can contain IPv6 and IPv4 addresses or address ranges – one entry in each line. “From” lists contain complete sender mail addresses. The lists can be left empty at first. They are well suited if you later want to set exceptions for individual senders or servers.
DKIM Signing:
The signing key (/var/lib/rspamd/dkim/2020.key)
has a matching public key, which is stored in the form of a prepared DNS record in the file /var/lib/rspamd/dkim/2020.txt.
Have the DKIM record output:
2020._domainkey IN TXT ( "v=DKIM1; k=rsa; "
"p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2/al5HqXUpe+HUazCr6t9lv2VOZLR369PPB4t+dgljZQvgUsIKoYzfS/w9NagS32xZYxi1dtlDWuRfTU/ahHO2MYzE0zHE4lMfwb6VkNCG+pM6bAkCwc5cFvyRygwxAPEiHAtmtU5b0i9LY25Z/ZWgyBxEWZ0Wf+hLjYHvnvMqewPsduUqKVjDOdUqeBb1VAu3WFErOAGVUYfKqFX"
"+yfz36Alb7/OMAort8A5Vo5t5k0vxTHzkYYg5KB6tLS8jngrNucGjyNL5+k0ijPs3yT7WpTGL3U3SEa8cX8WvOO1fIpWQz4yyZJJ1Mm62+FskSc7BHjdiMHE64Id/UBDDVjxwIDAQAB"
) ;
The value section of the record (starting with v=DKIM1 to the end of the character string – here AQAB) must be planted in a new DNS record. In the process, line breaks and inverted commas are removed. Depending on the DNS hoster, a new entry must be formatted slightly differently. I have carried out the step in the screenshot as an example for the hoster Core-Networks.de with the selector “2020” and my example domain “testsys.de”:
Important: The selector “2020” is used in the DNS record together with ._domainkey as name! The DKIM record must be created for each domain used (testsystwo.de, domain3.de) in the respective zone file!
path = "/var/lib/rspamd/dkim/$selector.key";
selector = "2020";
### Enable DKIM signing for alias sender addresses
allow_username_mismatch = true;
This configuration is copied into the file /etc/rspamd/local.d/arc.conf so that the ARC module can work correctly. It uses the same settings:
cp -R /etc/rspamd/local.d/dkim_signing.conf /etc/rspamd/local.d/arc.conf
Redis as cache and key-value store for Rspamd modules
Rspamd uses Redis as a cache. The installation is trivial:
apt install redis-server
In the Rspamd configuration, Redis has already been entered as a caching database.
Launch Rspamd:
Rspamd can now be started
systemctl start rspamd
Nginx proxy for Rspamd web interface
For convenient and secure access to the Rspamd web interface, an Nginx HTTP proxy can be connected upstream. Nginx then takes care of securing the connection via HTTPS. If you rarely access the Rspamd web interface, you can do without this step and instead access the interface via an SSH tunnel (see below).
For the Rspamd web proxy, a location block is added in /etc/nginx/sites-available/mail.testsys.de as follows:
server {
listen 80;
listen [::]:80;
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name mail.testsys.de imap.testsys.de smtp.testsys.de;
ssl_certificate /etc/acme.sh/mail.testsys.de/fullchain.pem;
ssl_certificate_key /etc/acme.sh/mail.testsys.de/privkey.pem;
add_header Strict-Transport-Security max-age=15768000;
To be adapted:
- ssl_certificate: Path to certificate
- ssl_certificate_key: Path to certificate
- server_name
Test configuration and reload Nginx:
nginx -t
systemctl reload nginx
Call up the web interface
The Rspamd web interface is now accessible at https://mail.testsys.de/rspamd/. The password created above for the web interface is used as the password.
Connecting to the web interface via SSH tunnel (alternative)
Instead of using Nginx, you can also use an SSH tunnel to establish a secure connection to the Rspamd web interface. However, this requires an SSH client on the local computer. The SSH command
ssh -L 8080:localhost:11334 username@mail.testsys.de -N
links the port of the web interface (11334) with port 8080 of the local system. The interface can now be reached in the local web browser at http://localhost:8080. The connection is terminated again with CTRL+C.
Train Rspamd with existing spam emails (optional)
If you have some mails in maildir format (each e-mail is a file), you can train Rspamd with the rspamc tool. It is advantageous to train not only spammail examples, but also examples of wanted emails. In the following example, the mailbox directory of an older mail server was imported:
Train e-mails in a directory as spam:
find ./oldserver/var/vmail/mailboxes/*/*/mail/Spam/cur -type f -exec /usr/bin/rspamc learn_spam {} \;
Train e-mails in a directory as Ham (harmless):
Autoconfig for Mozilla Thunderbird (Optional)
Mozilla Thunderbird (and other mail clients) automatically try to determine the correct addresses and settings for IMAP and SMTP servers when setting up a new mail account. Autoconfiguration gives us the option of storing information about the mail server at a specified address https://autoconfig..de/mail/config-v1.1.xml so that the user does not need to enter anything other than their mail address and password when linking their mail account. Thunderbird obtains all other information, such as the type of encryption or port, from the XML file.
Since the server settings in this setup are identical for all domains, the XML file should be made available centrally on the mail server at https://autoconfig.testsys.de/mail/config-v1.1.xml. If, in addition to the “testsys.de” domain, the domains “domain1.tld” and “testsystwo.de” are also used for e-mail, HTTP proxies on the target servers of these domains can be used to forward to the central address. But for now, we will only deal with the mail.testsys.de mail server …
Create DNS record
For the new autoconfig.testsys.de subdomain, a suitable CNAME record is created in the DNS, which points to the mail server:
autoconfig.testsys.de. 86400 IN CNAME mail.testsys.de.
Set up Autoconfig on the mail server
To offer the file on the server, another virtual host is created for the Nginx web server:
/etc/nginx/sites-available/autoconfig.testsys.de
server {
listen 80;
listen [::]:80;
# listen 443 ssl http2;
# listen [::]:443 ssl http2;
server_name autoconfig.testsys.de;
# ssl_certificate /etc/acme.sh/autoconfig.testsys.ded/fullchain.pem;
# ssl_certificate_key /etc/acme.sh/autoconfig.testsys.de/privkey.pem;
# add_header Strict-Transport-Security max-age=15768000;
As with the first Nginx configuration, a few lines are initially commented out here because no suitable TLS certificates are yet available.
Activate configuration, check Nginx Config and reload:
ln -s /etc/nginx/sites-available/autoconfig.testsys.de /etc/nginx/sites-enabled/autoconfig.testsys.de
nginx -t
systemctl reload nginx
A Webroot directory is created for the new vHost:
mkdir -p /var/www/testsys.de /autoconfig.testsys.de/mail/
and the XML configuration is stored in it:
config-v1.1.xml
<?xml version="1.0" encoding="UTF-8"?>
<clientConfig version="1.1">
<emailProvider id="testsys.de">
<domain>testsys.de</domain>
<displayName>testsys.de Mail</displayName>
<displayShortName>testsys.de</displayShortName>
<incomingServer type="imap">
<hostname>imap.testsys.de</hostname>
<port>993</port>
<socketType>SSL</socketType>
<authentication>password-cleartext</authentication>
<username>%EMAILADDRESS%</username>
</incomingServer>
<outgoingServer type="smtp">
<hostname>smtp.testsys.de</hostname>
<port>465</port>
<socketType>SSL</socketType>
<authentication>password-cleartext</authentication>
<username>%EMAILADDRESS%</username>
</outgoingServer>
</emailProvider>
</clientConfig>
Now a DNS record is created for autoconfig.testsys.de:
autoconfig.testsys.de IN CNAME mail.testsys.de.
Apply for and install TLS certificate:
acme.sh --issue --nginx -d autoconfig.testsys.de
mkdir -p /etc/acme.sh/autoconfig.testsys.de
acme.sh --install-cert -d autoconfig.testsys.de \
--key-file /etc/acme.sh/autoconfig.testsys.de/privkey.pem \
--fullchain-file /etc/acme.sh/autoconfig.testsys.de/fullchain.pem \
--reloadcmd "systemctl reload nginx"
The commented out lines can now be removed and Nginx reloaded:
Optional: Set up autoconfig proxy for additional mail domains
On the (web) servers to which the additional domains “domain1.tld” and “domain2.tld” point, a vHost is created in Nginx for “autoconfig.domain1.tld” and “autoconfig.domain2.tld” respectively:
/etc/nginx/sites-available/autoconfig.domain1.tld
Server {
listen 80;
listen [::]:80;
# listen 443 ssl http2;
# listen [::]:443 ssl http2;
server_name autoconfig.testsystwo.de;
# ssl_certificate /etc/acme.sh/autoconfig.testsys.de/fullchain.pem;
# ssl_certificate_key /etc/acme.sh/autoconfig.testsys.de/key.pem;;
# add_header Strict-Transport-Security max-age=15768000;
To be adapted:
- server_name
- IP address of the mail system mail.testsys.de at proxy_pass
The proxy_pass statement uses the IPv6 address fd::80 instead of the hostname of our mail server, because Nginx does not yet have a DNS resolver available for name resolution directly after booting.
A DNS entry for the new subdomain must not be missing:
autoconfig.domain1.tld IN CNAME testsystwo.de.
This VirtualHost should also be secured with a suitable TLS certificate:
acme.sh --issue --nginx -d autoconfig.testsystwo.de
mkdir -p /etc/acme.sh/autoconfig.testsystwo.de
acme.sh --install-cert -d autoconfig.testsystwo.de\
--key-file /etc/acme.sh/autoconfig.testsystwo.de/privkey.pem \
--fullchain-file /etc/acme.sh/autoconfig.testsystwo.de/fullchain.pem \
--reloadcmd "systemctl reload nginx"
The commented out lines in the Nginx configuration can now be commented out.
Activate the configuration and reload the web server:
ln -s /etc/nginx/sites-available/autoconfig.testsystwo.de /etc/nginx/sites-enabled/autoconfig.testsystwo.de
nginx -t
systemctl reload nginx
A call to https://autoconfig.testsystwo.de/mail/config-v1.1.xml should now display the same XML file that has already been stored on the mail server under autoconfig.testsys.de. This XML file must now be extended by domain1.tld in the same way as testsys.de, e.g. like this:
?xml version="1.0" encoding="UTF-8"?>
<clientConfig version="1.1">
<emailProvider id="testsys.de">
<domain>testsys.de</domain>
<displayName>testsys.de Mail</displayName>
<displayShortName>testsys.de</displayShortName>
<incomingServer type="imap">
<hostname>imap.testsys.de</hostname>
<port>993</port>
<socketType>SSL</socketType>
<authentication>password-cleartext</authentication>
<username>%EMAILADDRESS%</username>
</incomingServer>
<outgoingServer type="smtp">
<hostname>smtp.testsys.de</hostname>
<port>465</port>
<socketType>SSL</socketType>
<authentication>password-cleartext</authentication>
<username>%EMAILADDRESS%</username>
</outgoingServer>
</emailProvider>
<emailProvider id="testsystwo.de">
<domain>testsystwo.de</domain>
<displayName>testsystwo.de Mail</displayName>
<displayShortName>testsystwo.de</displayShortName>
<incomingServer type="imap">
<hostname>imap.testsys.de</hostname>
<port>993</port>
<socketType>SSL</socketType>
<authentication>password-cleartext</authentication>
<username>%EMAILADDRESS%</username>
</incomingServer>
<outgoingServer type="smtp">
<hostname>smtp.testsys.de</hostname>
<port>465</port>
<socketType>SSL</socketType>
<authentication>password-cleartext</authentication>
<username>%EMAILADDRESS%</username>
</outgoingServer>
</emailProvider>
</clientConfig>
Proceed in the same way for the third domain.
Define domains, accounts, aliases and TLS policies in database
Before the mail server can be used meaningfully, domains and users must be registered in the MySQL database. Log in to the MySQL command line again:
mysql
… and switches to the vmail database:
use vmail;
Create new domain
In order to create a new user account or a new alias, the domain to be used must first be made known in the mail system. Postfix only processes emails to domains that are entered in the “domains” table:
insert into domains (domain) values ('testsys.de');
Create new e-mail account
Once the user domain has been created in the domain table, a new user account can be created for the mail server. However, before the appropriate SQL command is entered and sent, a password hash of the desired password for the account is generated first. With
doveadm pw -s SHA512-CRYPT
(in the Bash Shell! – Not in the MySQL Shell!) such a hash can be generated. Example for an output hash:
{SHA512-CRYPT}$6$wHyJsS.doo39xoCu$KI1N4l.Vd0ZWYj5BYLI8AdK7ACwAZaM18gSy7Bko0dG2Hvli4.KfAmLk2ztFVP.R4T7oqiu7clKBehCTc4GGw0
This hash is unique for each password and even changes with each generation. It is best to put the hash in your clipboard or in a text document – you will need it right away!
The SQL command to create a new account is:
insert into accounts (username, domain, password, quota, enabled, sendonly) values ('user1', 'mysystems.tld', '{SHA512-CRYPT}$6$wHyJsS[...]', 2048, true, false);
n the “Password” field the hash is entered completely (here: shortened).
It is best to create the postmaster@mysystems.tld account right away. It should be available on every mail server to be able to contact the administrator in case of technical problems with the server.
Create new alias
… creates an alias for the user “user1@mysystems.tld”. E-mails to “alias@mysystems.tld” are then delivered to the mailbox of this user.
E-mail accounts on foreign servers can also be specified as destination addresses. Postfix then forwards these e-mails. However, this can lead to problems with SPF records – after all, under certain circumstances Postfix sends e-mails under foreign domains for which it is not responsible according to the SPF record. SRS (Sender Rewriting Scheme) is a solution for this problem. However, I don’t think much of extensions that correct serious design flaws of a technique like SPF, so I recommend you to leave the SPF record (as above) set to an “?all” and to avoid redirects to foreign servers if possible. Aliases from local addresses to other local addresses are no problem.
If an e-mail distribution list is to be set up, several records with the same source address are set up, e.g. like this:
team@domain.de=> user1@domain.de
team@domain.de => user2@domain.de
team@domain.de=> user3@domain.de
A catch-all, on the other hand, can be achieved by setting the source_username to null, e.g. like this:
insert into aliases (source_username, source_domain, destination_username, destination_domain, enabled) values (null, 'domain1.tld', 'catchall', 'mysystems.tld', true);
A catch-all can co-exist with other aliases on the same domain and “catches” all user names on the respective domain for which no alias has been set yet. This allows you to centrally collect mails sent to mailboxes that do not exist on the mail server. Note that this may increase the amount of spam.
Create new TLS policy (optional)
The TLS policy table can be used to specify which security features should be used to communicate with the mail servers of a particular domain. For example, if “dane-only” is set in “policy” for the domain “thomas-leister.de”, the connection to mail servers of this domain will be valid only if it is DANE-authenticated and encrypted. Possible policies are:
- none: Do not use encryption, even if the other mail server supports it.
- may: Encrypt if the other server supports it, but no certificate checking (self-signed certificates are accepted).
- encrypt: Mandatory encryption, but no certificate checking (self-signed certificates are accepted).
- dane: If valid TLSA records are found, encryption is mandatory and the certificate is verified using DANE. If invalid TLSA records are found, “encrypt” is used. If no TLSA records arefound at all, “may” is used.
- dane-only: Encrypted connections only. Valid TLSA records for the hostname must exist (DANE).
- verify: Encrypted connections only + verification of CA. The hostname from the MX DNS record must be included in the certificate. (Based on trust in correct DNS data)
- secure: Only encrypted connections + verification of the CA. The other mail server must (by default) have a hostname corresponding to “.domain.tld” or just “domain.tld”. This hostname must be included in the certificate. The DNS is not used (security advantage over “verify). Example: An e-mail is to be sent to user@web.de. The MX mail server of Web.de should then only have the hostname “web.de” or a subdomain of it as hostname, e.g. mx.web.de. A connection to mx.web.net would not be allowed.
For domains of the big providers like gmx.de, web.de and Telekom you can choose “secure”. For Posteo and Mailbox.org even “dane-only”. For all providers that do not use valid TLS certificates, “encrypt” can be selected. Default setting for all other mail servers is “dane” (see main.cf of Postfix Config).
The “params” field is filled with additional info if it is required for a policy type, e.g. for a “secure” entry to GMX:
insert into tlspolicies (domain, policy, params) values ('gmx.de', 'secure', 'match=.gmx.net');
By default, Postfix checks for “secure” – as already mentioned above – whether the recipient domain (gmx.de) is present in the certificate of the target server. However, this is not the case with GMX (and many other large providers): GMX’s mail server certificates are only valid for gmx.net + subdomains. If the database entry for GMX was set to “secure” without any further settings, no mails could be transmitted to GMX. Therefore it is important to specify for GMX that the certificate should not search for “gmx.de” but for “gmx.net”. We can do this using the “params” field and the “match=…” string. If we want to search for more than one domain, we can specify more than one, e.g. like this: “match=.gmx.net:.gmx.ch”. However, the additional specifications in “params” are not necessary for every mail provider. GMX is an exception – just like Yahoo for example. If you have to specify a “match” string in “params”, you can find out e.g. via https://de.ssl-tools.net/. If the 2-nd-level domain of the mail server differs from the domain of the mail addresses, a matching match string must be specified.
Other settings like “dane-only” do not require any additional information in “params”:
insert into tlspolicies (domain, policy) values ('mailbox.org', 'dane-only');
In this case, communication with the mailbox.org mail servers is only DANE-secured and encrypted. The MySQL command line can be exited again with a quit;.
Optional: Configure firewall
If you run a firewall in front of / on the mail server that restricts access to ports, you should first unblock all mail server ports:
IMAP: 143/tcp
IMAPS: 993/tcp
Submission: 587/tcp
SMTPS: 465/tcp
SMTP: 25/tcp
ManageSieve: 4190/tcp
Web HTTP: 80/tcp
Web HTTPS: 443/tcp
Make sure to open your IPv6 ports as well! – Your mail setup speaks IPv6! 🙂 Ports 143 and 587 can stay closed if you don’t want to use a StartTLS based connection (see note below).
Start all the things!
Your new mail server is now configured. Time for a first start!
systemctl start dovecot
systemctl start postfix
The best thing to do is to check the log files for noticeable errors. I recommend the “tail” tool in a separate terminal session. New log entries appear immediately on the screen:
tail -f /var/log/syslog
The best thing to do is to check the log files for noticeable errors. I recommend the “tail” tool in a separate terminal session. New log entries appear immediately on the screen:
tail -f /var/log/syslog
respectively
tail -f /var/log/mail.log
You can connect using any IMAP-enabled email client and the following connection parameters:
IMAP(S)
Host: imap.mysystems.tld
Port: 993
Encryption: TLS
(this server is also valid for domain2 and domain3, if available!)
SMTP(S)
Host: smtp.testsys.de
port: 465
Encryption: TLS
(this server is also valid for domain2 and domain3, if available!)
Managesieve (optional, for configuration of user specific Sieve filter rules)
Host: imap.mysystems.tld
port: 4190
Encryption: StartTLS
Username: The full email address, i.e. @
Password: Should be known 😉
If connections over the IMAPS (993) and SMTPS (465) ports are not possible, you can also use the StartTLS ports:
IMAP server:
Host: mail.testsys.de
Port: 143
Encryption: StartTLS
SMTP server:
Host: mail.testsys.de
Port: 587
Encryption: StartTLS
However, as of 2018, the IETF (Internet Engineering Task Force) recommends not using StartTLS connections, and to rely on native TLS connections: https://tools.ietf.org/html/rfc8314
If problems occur, a look at the log will help!
For example, you can view the Rspamd log and read it live:
journalctl -f -u rspamd
Postfix like this:
journalctl -f -u postfix@-.service
… and Dovecot like this:
journalctl -f -u dovecot
That’s it! Thats Your Mailserver.
The next chapter is about hardening mail systems. However, I need for it quite a while.