This wiki was updated to MediaWiki 1.37. If you notice any issues, please report them to admin[at]opensuse.org

Mail server HOWTO

Jump to: navigation, search

The task of setting up a mail server can be seen as complicated because there are many different options and configurations available. Many times there are numerous ways to achieve the same thing. As this page describes many different options, depending on your needs you may decide to use some parts and not use others.

Server

The standard email application is Postfix. It comes standard installed and enabled in an openSUSE system. This means that it is already active when the systeem is started for the first time. This also means that the setup application /usr/sbin/config.postfix has been run. This application may initialize quite a few parameters in the files /etc/postfix/main.cf and /etc/postfix/master.cf. Among others the name of your system and the parameter mynetworks. After the initial initialization a parameter is set to prevent further running this application again. It is also run when using the mail module of YaST, which sets parameters in /etc/sysconfig/postfix.

However the assumption of this HOWTO is that only the initialisation right after booting the system for the first time has been done.

Inbound

The main types of connections for inbound mail are:

  • POP or IMAP - these are client protocols and mostly used by user mail clients, but a mail server can also retrieve mail using these protocols.
  • SMTP - Simple Mail Transfer Protocol is the main protocol used by mail server to, well, transfer mail.

POP & IMAP

If you want to fetch mail from more than one mailbox, fetchmail is the tool to use. It will get mail from various servers with various protocols and various people.

First see that fetchmail is installed. Next you need to configure /etc/fetchmailrc. Open it with your favourite editor as root. Each mailbox needs to be configured separately. Things you need to know is:

  • local user id
  • remote server
  • remote user id
  • remote password

Now for each remote mailbox write:

poll remote.example.com
     proto auto
     user "remote_userid"
     pass "remote_password"
     is local_userid

This will deliver the mail from the mailbox remote_userid@remote.example.com via the SMTP server (MTA) on localhost in the mailbox for user local_userid, wherever that mailbox is configured in the MTA. Do this for any and all remote mailboxes. See that /etc/fetchmailrc is chmod 700.

Read man fetchmail for more info. Also there is a program fetchmailconf which could be used.

Now you want to do this automatically. As root you type

# systemctl enable fetchmail.service

This will automatically start fetchmail when booting the machine. To start it immediately type

# systemctl start fetchmail.service

This will get the mail every 10 minutes. You can change this by changing FETCHMAIL_POLLING_INTERVAL=600 to any other time interval.

Do NOT set this lower than 600 seconds (10 Minutes), as it will load the provider's mail server, unecessarily, and may even be against their Terms of Service

FETCHMAIL_POLLING_INTERVAL and other parameters can be changed either by editing /etc/sysconfig/fetchmail or by using YaST's sysconfig Editor (System -> /etc/sysconfig Editor): choose Network -> Mail -> Fetchmail.

Configure your client to get mail via mbox in case your MTA uses the simplest method of delivery.

Alternative for fetchmail

The recommended way is to configure POP and/or IMAP accounts in the email client of the users of these accounts.

SMTP

You can get mail directly sent to your server. For this you need several things:

  • Domain name
  • Fixed IP address
  • Correct MX records

If you have a Dynamic IP address, seriously reconsider to apply for a fixed address. You are on your own.

First see that a fresh installed postfix is running. This can be done by a telnet session:

# telnet localhost 25
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
220 example.com ESMTP Postfix

Use quit to exit.

  • Next see that the outside world is able to connect to port 25.
  • At this moment postfix is only listening to port 25 on localhost, so you need to make it listen to outside systems by giving the next command and restarting postfix by using the recommended way of changing parameters in /etc/postfix/main.cf, using postconf:
postconf -e "inet_interfaces = all"
  • Restart postfix by using:
systemctl restart postfix.service
  • You also need to open your firewall with YaST or with, assuming your interface is eth0 and you are using a fresh installed firewalld:
systemctl enable firewalld.service
systemctl start firewalld.service
firewall-cmd --zone=public --add-interface=eth0
firewall-cmd --zone=public --add-service=smtp
  • Also forward port 25 or for testing another port in your router to this port 25 in your system. Test it with This site.
The standard configuration of postfix does protect you already from being a spam relay.
  • The next step is to customize postfix with your identity (do this by replacing example.com by your domain name and hostname by smtp.example.com; this is a common name for a receiving email server). The name of your host in /etc/hostname can be different from this name, but should also be mentioned in the list of domains to be considered as email domains on your system. You also want email send by accounts from this domain to have addresses like account@example.com . So, four things should be added and/or changed:
postconf -e "myhostname = smtp.example.com"
postconf -e "mydomain = example.com"
postconf -e "mydestination = \$myhostname, \$mydomain, localhost, localhost.\$mydomain, $(cat /etc/hostname).\$mydomain"
postconf -e "myorigin = \$mydomain"
The backslash in front of the $ is needed to get the dollar in this parameter.
  • Restart postfix. You will now be able to receive mail for login accounts (e.g. root) on example.com or the other domains mentioned in mydestination, assuming that these domains have associated IP addresses in the DNS or in /etc/hosts of the sending system.
  • Install packet mailx on your system, and use the command:
mailx -s test root@example.com < test.txt

to send the content of test.txt (do 'echo "test line" > test.txt' to create it) to the root account on your system. After the @ you can test the other domains as well. The message should arrive in /var/ /mail/root. The sender in the message should be root@example.com.

Aliases

Postfix in the above status will accept email addresses that have names before the @ that correspond with usernames on the system and with names in the first row of the file /etc/aliases. The names in the first row end with a colon(:), behind the colon another name should be present, which should be the name of an account on the system or another name in this file. Following the recursion it should end in a valid destination, otherwise the sender will receive an Undelivered message.

Mail will be put in /var/mail/user_login. Most of the time you might want to receive mail under something else then your login. If your login is user, you probably would like an email address like firstname.lastname@example.com

You then link an alias to user with the name firstname.lastname . This can be done by editing /etc/aliases. Add the following at the end of the file:

firstname.lastname:    user

You will see some there already. If you want a generic address like sales@example.com and that to be received by several people, add the following line:

sales:                 user_1, \user_2, \user_3

After additions, you need to run newaliases.

You may also want the reverse, login_user should have a sender email address like firstname.lastname. This is done in the file /etc/postfix/sender_canonical in an entry like:

login_user firstname.lastname

or even:

login_user some_name@some_domain

After changing this file, don't forget to run the command:

postmap /etc/postfix/sender_canonical

It also requires in /etc/postfix/main.cf the entry:

db_type=$(postconf default_database_type)
db_type=${db_type##* }
postconf "sender_canonical_maps = ${db_type}:/etc/postfix/sender_canonical"

which may be already present in the standard postfix installation.

Allowing incoming email to outside addresses

In the current state of postfix email from IP addresses mentioned in mynetworks are allowed to be send on to outside addresses. Messages coming from other IP addresses are only allowed to users that have an account on the system or which are mentioned in /etc/aliases; the local addresses. However these messages to outside users are send in the clear. See the chapter Outgoing to send these on an encrypted connection.

However we want authenticated users to be able to send email to outside addresses. Authentication involves sending username and password on the connection to our server, so we want this connection to be secured. There are several ways for postfix to authenticate users. We will do this using dovecot, the POP3 and IMAP server, which we restrict to use the standard login accounts of the system. A side effect of using a secured connection is that also other incoming messages are able to come in over a secured connection. A sending server will check if a secured connection is possible and, if so, will use that.

Dovecot works with maildir as opposed to mbox, which means that we will not use /var/mail/login_user/ as the destination of email messages, but a folder in the home folder of a user, indicated as ~/Maildir/ . For this we need to configure postfix with:

postconf -e "home_mailbox = Maildir/"

Configuring dovecot

First we install dovecot:

zypper in --no-recommends dovecot
We use --no-recommends to prevent lots of unneeded packages to be installed.

In the file /etc/dovecot/dovecot.conf we only add one line to alter the default. After line with: "#protocols = imap pop3 lmtp submission" enter:

protocols = imap

This restricts dovecot to serve only the imap protocol. Also note that the default line with listen means that dovecot can be accessed from all IP addresses. The imap port, 143, will be opened when dovecot is activated. The connection to this port is not secured, so username and password are send in the clear.

In /etc/dovecot/conf.d/10-ssl.conf you can remove the comment character # in front of:

ssl = yes
ssl_cert = </etc/ssl/private/dovecot.crt
ssl_key = </etc/ssl/private/dovecot.pem

and

ssl_dh = </etc/dovecot/dh.pem

This means that the server is also accessible via imaps, port 993. However you need to populate the three mentioned files. We come to that later.

For postfix we need to change file /etc/dovecot/conf.d/10-master.conf. Find the line # Postfix smtp-auth and remove the three comment characters # and insert two lines so it reads:

 # Postfix smtp-auth
 unix_listener /var/spool/postfix/private/auth {
  mode = 0666
  user = postfix
  group = postfix
}

The last changes are in /etc/dovecot/conf.d/10-mail.conf; find the line with #mail_location and add after that line:

mail_location = maildir:~/Maildir

Find after the line namespace inbox { the line #prefix and add after that line the line:

prefix = INBOX.

With the current setting in the firewall both ports, 143 (imap) and 993 (imaps), are only accessible via localhost. The recommendation is that imap is only accessible from your local network and imaps from all IP-address. So the commands for the firewall, assuming zone public contains the network interface, are:

firewall-cmd --zone=internal --add-source=192.168.0.0/16 # your local network
firewall-cmd --zone=internal --add-service=imap
firewall-cmd --zone=public --add-service=imaps

The last issue is to populate the certificate files. The dovecot package offers a script in /usr/share/doc/packages/dovecot/mkcert.sh. Before you run that script you must edit the file dovecot-openssl.cnf and enter values for C, ST, L, O, CN(=imap.domain.com) and emailAddress(=postmaster@domain.com). The certificate you generate will have a live time of 365 days, so you may change the value of 365 at line 37 in 3650 (10 years). After editing these two files to suite your need, do the following:

cd /usr/share/doc/packages/dovecot/
. ./mkcert.sh

Dovecot also requires a file /etc/dovecot/dh.pem, which can be generated with:

openssl dhparam -out /etc/dovecot/dh.pem 4096
Warning: Generation of this file takes quite some time; on a Raspberry Pi 4B (1.5 GHz) 100 minutes

After this you should enable and start dovecot with:

systemctl enable dovecot.service
systemctl start dovecot.service
The generated certificate is a so-called self-signed certificate. This means that connecting the first time using imaps will raise a question in the email client if this certificate should be accepted or not. The assumption here is that only a few users will ever use this connection legitimate, so this is acceptable. The client will store the public certificate, so the next time the client will immediately accept the connection.

Using Let's Encrypt to generate and maintain certificates

In case you want properly signed certificates, so your users do not need to accept the self-signed certificates, you can use certificates signed by ["Let's Encrypt"]. See this wiki page on how to generate and maintain these (you need to renew these each 3 month).

Explanation on how to add them to postfix is pending.


Configuring postfix to allow validated users to send to outside addresses

These type of clients will use another port to deliver their messages. This port is called the submission port which has the value 587. This means that we have to add support for this port in /etc/postfix/master.cf. The command is:

postconf -M submission/type='submission inet n       -       n       -       -       smtpd   -o syslog_name=postfix/submission   -o smtpd_tls_security_level=encrypt   -o content_filter=smtp:[127.0.0.1]:10024   -o smtpd_sasl_auth_enable=yes   -o smtpd_tls_auth_only=yes   -o smtpd_reject_unlisted_recipient=no   -o smtpd_recipient_restrictions=   -o smtpd_relay_restrictions=permit_sasl_authenticated,reject   -o milter_macro_daemon_name=ORIGINATING  -o disable_vrfy_command=yes'

For a detailed explanation on these parameters, you are referred to the documentation on http://www.postfix.org In short, you need to use an encrypted connection, and to authenticate for mail presentation via this port. Apart from this entry in the master file, you also need to define parameters in /etc/postfix/main.cf. These are:

postconf -e 'smtpd_sasl_path = private/auth'
postconf -e 'smtpd_sasl_type = dovecot'
postconf -e 'smtpd_tls_auth_only = yes'
postconf -e 'smtpd_tls_CAfile = /etc/postfix/cacert.pem'
postconf -e 'smtpd_tls_cert_file = /etc/postfix/newcert.pem'
postconf -e 'smtpd_tls_key_file = /etc/postfix/newkey.pem'
db_type=$(postconf default_database_type)
db_type=${db_type##* }
postconf -e 'smtpd_tls_session_cache_database = ${db_type}:/var/lib/postfix/smtpd_tls_session_cache'
postconf -e 'smtpd_helo_required = yes'
postconf -e 'smtpd_tls_loglevel = 1'

As you may have noticed we need a few files with certificates to encrypt the connection to port 587. As with the connection to dovecot, we can use a self-signed certificate, again because we assume only a few users to use that port to send email. Below are the commands to do that:

openssl genrsa -des3 -out mail.domain.tld.key 2048

You will be asked to enter a passphase twice. Remember what you entered!

chmod 600 mail.domain.tld.key
openssl req -new -key mail.domain.tld.key -out mail.domain.tld.csr

The first question asked is for the above used passphase. There are some further questions of which the CN (Common Name) is the most important. Enter the fully qualified name of your host, like smtp.example.com. The question about a challenge password and the following question should be left empty (only Return).

openssl x509 -req -days 365 -in mail.domain.tld.csr -signkey mail.domain.tld.key -out mail.domain.tld.crt

Again you will be asked for the above passphrase.

openssl rsa -in mail.domain.tld.key -out mail.domain.tld.key.nopass
mv mail.domain.tld.key.nopass mail.domain.tld.key
openssl req -new -x509 -extensions v3_ca -keyout cakey.pem -out cacert.pem -days 3650

Like above enter the passphrase and the values like CN above. You did make a certificate without a password, so postfix will not ask for it. See https://e-rave.nl/create-a-self-signed-ssl-key-for-postfix for more information.

chmod 600 mail.domain.tld.key
chmod 600 cakey.pem
mv mail.domain.tld.key /etc/postfix/newkey.pem
mv mail.domain.tld.crt /etc/postfix/newcert.pem
mv cakey.pem /etc/postfix/
mv cacert.pem /etc/postfix/

Configuring the general entry point of postfix

On port 25 all email with a destination for your domain will enter. We discussed already some of the security issues associated with this entry point. At least we want to make it possible for senders to send a message via an encrypted connection. This means that server should provide the STARTTLS service. For this service postfix needs a number of parameters active on the service listening on port 25. These parameters are:

postconf -e "smtpd_tls_security_level = may"
postconf -e "smtpd_sasl_local_domain = \$myhostname"
postconf -e "smtpd_tls_received_header = yes"
postconf -e "smtpd_noop_commands = etrn"

The process tlsmgr needs to be activated by:

postconf -M tlsmgr/type='tlsmgr    unix  -       -       n       1000?   1       tlsmgr'

Restart postfix with:

systemctl restart postfix.service

You can test the secured connection with:

openssl s_client -connect localhost:25 -starttls smtp

This should give a lot of output. You can do an smtp session and finally or immediately enter: quit to exit the STARTTLS session.

Outgoing, preferably over an encrypted connection

This will be about all the mail that goes from you or your co-users to the Internet.

In the current state of your server postfix will look at the destination address of the message. If its destination is outside your system, it will lookup the MX record of the domain part, the part after the @, or, if that record does not exist, the A and AAAA records (IPv4 and IPv6 addresses). It will also look up the A and AAAA records of the name(s) in the MX record. So it will have one or more IP addresses to send the message to. It will try to connect to port 25 of these IP addresses and, if the connection succeeds, will present HELO/EHLO, MAIL FROM and RCPT TO commands. There are many reasons why these destination servers will deny access when these commands are presented. One of these reasons is that the connection is not encrypted. So to enhance acceptance of your messages, we will configure postfix to try to use an encrypted (TLS) connection when possible. The destination server indicates this by offering a STARTTLS parameter. For this we need to add a number of lines to /etc/postfix/main.cf:

postconf -e "smtp_tls_security_level = may"
postconf -e "smtp_tls_ciphers = medium"

This is the so-called Opportunistic TLS. It allows access to sites with low and no security settings. Some protocols are insecure and should not be used. For postfix < 3.6 (Leap) use:

postconf ´smtp_tls_protocols = !SSLv2, !SSLv3'

otherwise (Tumbleweed):

postconf "smtp_tls_protocols = >=TLSv1, <=TLSv1.3"

The next parameter logs the connections made.

postconf -e "smtp_tls_note_starttls_offer = yes"

The next parameter logs even more. When all is well, set it to 0.

postconf -e "smtp_tls_loglevel = 1"

The next parameter defines the location of cached information for later reuse.

db_type=$(postconf default_database_type)
db_type=${db_type##* }
postconf -e "smtp_tls_session_cache_database = ${db_type}:/var/lib/postfix/smtp_tls_session_cache"

Obviously you need to restart/reload postfix.

Pointing your Email program

The simplest way to send your email to others from your client, is to hand over your email to a server at your provider. Most of the time this will be an SMTP server. Most likely you need a login name and password. Read the documentation of your email-client on how to configure this.

In case you or co-users of your computer need to send email from an application or script it will be more easy to send it to the MTA (in this article postfix) of your machine.

Sending email via the local server to/via the provider for all

The standard for postfix is that it will send email to an external address directly to the server of that address. So if you point your email clients to send email to this postfix server, postfix will send this on. However most receiving email servers have restrictions on accepting messages from somewhere, so it is likely that your email is not accepted. A safe method is to send all your outgoing email to the server of your provider. Postfix uses relayhost for that purpose. Most likely your ISP requires a username and password and often not the standard access port (25) is used, but the submission port (587). So if your ISP does not use access control and the standard port, use:

postconf -e "relayhost = smtp.example.net"

else use:

postconf -e "relayhost = [smtp.example.net]:587"
db_type=$(postconf default_database_type)
db_type=${db_type##* } postconf -e "smtp_sasl_password_maps = ${db_type}:/etc/postfix/sasl_passwd"

As you can see this requires the file /etc/postfix/sasl_passwd, in which you enter:

echo "[smtp.example.net]:587 username:password" >> /etc/postfix/sasl_passwd

After that you give the command:

postmap /etc/postfix/sasl_passwd

Both files should be properly protected; owned by root:root and "chmod 0600". Restart postfix with systemctl restart postfix.service and configure your email client to point to the SMTP server at localhost.

The square brackets around smtp.example.net indicate that the system should not use MX records of that name to send the email to, but directly to the A or AAAA records of that name. If these brackets are not used messages are send to the servers mentioned in the MX records of that name.

Filtering incoming email

Filtering on origin and destination of messages

There are two entry points for email, smtp (port 25) and submission (port 587). Both use different checks, The one for submission is in the file /etc/postfix/master.cf. See the postconf -M submission/... command above. More specific the parameter smtpd_recipient_restrictions, which needs less checks, because all users are authenticated. The main entry point is smtp, which can be accessed from anywhere. The most important feature is access checks. This means that any email with a destination not explicitly configured here should be denied. This is done with the parameter smtpd_recipient_restrictions. The value of this parameter, we use here, is configured with:

postconf -e "smtpd_recipient_restrictions = permit_sasl_authenticated,permit_mynetworks,reject_unauth_destination,reject_rbl_client zen.spamhaus.org,check_policy_service unix:private/policyd-spf"
Note this is used only on incoming messages on port smtp(25); on the other ports submission(587) and submissions(465) in master.cf an explicit value for this parameter is present, which disables the value in main.cf.

It means: an incoming messages is tested according to the sequence of the elements in this parameter.

  • When a user sends credentials that are properly authenticated, permit_sasl_authenticed allows access.
  • When a user sends a message from a IP address in mynetworks access is allowed.
  • When the IP address of the sending host is mentioned in the DNS of zen.spamhaus.org the message will be denied access.
  • When a message fulfills the requirements of the mentioned policy_service, unix:private/policyd-spf, it is allowed access. This service does the so-called SPF check. This check looks at the domain of the sender address, tries to get the SPF record of that domain, which specifies which IP addresses are allowed to send messages for that domain, and compares these addresses with the address of the sending IP address. If the check fails, the message is rejected. If there is no SPF information for the sender domain or the check is positive, the message is allowed.

To make the check on SPF we need a policy service in master.cf:

postconf -M policyd-spf/type='policyd-spf    unix    -    n    n    -    0     spawn user=policyd-spf argv=/usr/lib/policyd-spf-perl'

This service needs its own user, so we add:

 useradd -c "SPF Policy Server for Postfix" -d /etc/python-policyd-spf -s "/sbin/nologin" policyd-spf

Also add:

postconf -e "policy_time_limit = 3600"
The packet postfix-policyd-spf-perl can be found using http://software.opensuse.org

Content filtering

Especially email delivered on the local system should be filtered for unwanted content; spam and viruses. This is done with the parameter:

content_filter=smtp:[127.0.0.1]:10024

This means that when a message is allowed access, it will be send on to port 10024 on localhost. The service on this port is provided by the packet amavisd-new, and the systemd service amavis.service. Configuration is in /etc/amavisd.conf. This service returns the message back to postfix via the amavis service, which needs to be enables using:

postconf -M amavis/type='amavis    unix  -       -       n       -       4       smtp -o smtp_data_done_timeout=1200 -o smtp_send_xforward_command=yes -o disable_dns_lookups=yes -o max_use=20'

Using DKIM

Icon-expand.png This article is a stub!
This article needs to be expanded. You are welcome to help in line with the Style Guidelines.