Before we dive into SMTP authentication I want you to understand what relaying actually means. When Postfix receives an email and needs to forward it to another server this is called relaying.
When someone on the internet sends an email to email@example.com some other mail server will deliver the email using SMTP to your mail server. Postfix will determine that it’s responsible for email addresses in the example.org domain and accept the email. John can then use POP3 or IMAP to fetch the email from your server.
Outgoing email (without authentication)
John is on the internet somewhere and wants to send an email to firstname.lastname@example.org. As your mail server is not responsible for the “example.com” domain it would have to forward the email to the responsible mail server. So your server receives John’s email and forwards (relays) it to the mail server that is responsible for …@example.com email addresses. This may seem like a harmless case your mail server will deny that:
Why? Because anyone can claim to be John and make your mail server forward mail. If an attacker (like a spammer) would send millions of spam emails through your server then other organisations will accuse you of spamming. Your mail server would be what people call an “open relay”. This is not what you want because your mail server’s IP address would get blacklisted and you will have serious trouble ever sending out mail again. So without any proof that John is actually John your server will reject the email.
Outgoing email (with authentication)
So how does John send his email? He needs to use authenticated SMTP. This is similar to the previous case but John’s email program will send his username and password first.
In addition to using SMTP authentication you can tell Postfix to always relay email for certain IP addresses. The mynetworks setting contains the list of IP networks or IP addresses that you trust. Usually you define your own local network here. The reason John had to authenticate in the above example is because he is not sending the email from your local network (usually).
Enabling SMTP authentication in Postfix
Authenticated SMTP with Postfix has been a hassle in the past. It was done through the SASL (Simple Authentication and Security Layer) library that was once part of the Cyrus mail server. It was nearly impossible to debug and threw error messages that were gibberish and misleading. Fortunately nowadays we can make Postfix ask the Dovecot server to verify the username and password. And as you already configured Dovecot’s authentication part this is really easy now. Postfix just needs some extra configuration.
postconf -e smtpd_sasl_type=dovecot
postconf -e smtpd_sasl_path=private/auth
postconf -e smtpd_sasl_auth_enable=yes
postconf -e smtpd_tls_security_level=may
postconf -e smtpd_tls_auth_only=yes
postconf -e smtpd_tls_cert_file=/etc/ssl/certs/mailserver.pem
postconf -e smtpd_tls_key_file=/etc/ssl/private/mailserver.pem
postconf -e smtpd_recipient_restrictions=” \
smtpd_sasl_auth_enable enables SMTP authentication altogether. And the smtpd_recipient_restrictionsdefine rules that are checked after the remote user sends the RCPT TO: line during the SMTP dialog. In this case relaying is allowed if:
- permit_mynetworks: the user is in the local network (mynetworks) or
- permit_sasl_authenticated: if the user is authenticated or
- reject_unauth_destination: the mail is destined to a user of a domain that is a local or virtual domain on this system (mydestination, virtual_alias_domains or virtual_mailbox_domains).
There are further restrictions (smtpd_client_restrictions, smtpd_helo_restrictions,smtpd_sender_restrictions) that get checked during the different states of the SMTP dialog (IP connection, HELO/EHLO command, MAIL FROM command) but for now you should put all restrictions into thesmtpd_recipient_restrictions.
The smtpd_tls_security_level is set to “may” to enable TLS encryption when sending the email, the user name and especially the password. You don’t want your users to send their password unencrypted over the internet. Ideally you would set from “may” to “encrypt” which would forbid sending such information unencrypted. While it sounds tempting it would break reception of emails from other mail servers on the internet. So unless you operate different mail servers for servers and users you must not use “encrypt”. However users are still able to ignore encryption and still send their password unencrypted. So we take another step…
Enforcing encryption for authentication data
Although emails may still get delivered unencrypted from other servers we should make sure that users don’t accidentally (or out of ignorance) send their passwords unencrypted over the internet. That’s what we enforce using “smtpd_tls_auth_only=yes”. Now we should be safe.
How SMTP authentication works
Are you curious how SMTP authentication looks on a protocol level? Let’s go through that. In previous versions of this guide we used “telnet” to connect to TCP port 25 and speak SMTP. But now we enforce encryption and can’t do SMTP authentication unencrypted. Let’s try the unencrypted part:
$> telnet localhost smtp
The server will let you in:
Trying 127.0.0.1... Connected to localhost. Escape character is '^]'. 220 mailtest ESMTP Postfix (Debian/GNU)
Postfix will present a list of features that are available during the SMTP dialog:
250-mailtest 250-PIPELINING 250-SIZE 10240000 250-VRFY 250-ETRN 250-STARTTLS 250-ENHANCEDSTATUSCODES 250-8BITMIME 250 DSN
Let me briefly explain what these lines mean:
This is a feature to speed up SMTP communication. Usually the remote system has to wait for a response to every command it sends. Pipelining allows the remote server to send bulks of commands without waiting for a response. Postfix will just store these commands and execute them one by one. If you told Postfix to forbid pipelining it would disconnect the remote server when it tries to send bulks of commands without waiting for the proper reply. It is mainly a feature against spamming programs that don’t behave.
- SIZE 10240000
The remote server is allowed to send emails up to 10 MB large. This has long been a common maximum size for emails. However nowadays 40 MB or even more are more common sizes because emails have grown larger.
Allows remote servers to verify a given name or email address. For example the remote server could send “VRFY john” and your server might respond “250 John Doe <email@example.com>”. It is a kind of dictionary lookup. It poses a security risk because it allows spammers to harvest valid email addresses. So Postfix will only allow it once the remote system has authenticated.
A command that a remote system can send to flush the Postfix queue of mails for a certain domain. It can be used if the remote system had technical problems and failed to receive email for a while. Then it could send an ETRN command to make your server start sending outstanding emails for that domain. It is rarely used.
This tells the remote system that it might start switching from this unencrypted to an encrypted connection by sending the “STARTTLS” command. It will then start negotiating a TLS-encrypted connection. You could compare it to an HTTP connection that suddenly switches over to an encrypted HTTPS connection. The advantage is that you can start talking SMTP on TCP port 25 and don’t have to open up a second TCP port like 465 which is the “SSMTP” (secure SMTP) port and only accepts encrypted connections.
This enables more three-digit return codes for various conditions. See the RFC2034 if you are curious.
In ancient times SMTP only processed 7-bit characters. You couldn’t transfer special characters like “Ä” or “ß” without special encoding. 8BITMIME allows a transmission of emails using 8-bit characters. Still many emails are specially encoded using ISO8859-1 or UTF-8.
It enables DSNs (delivery status notofications) that allows the sender to control the messages that Postfix creates when an email could not be delivered as intended
However one important line is missing here that would allow us authentication:
250-AUTH PLAIN LOGIN
We told Postfix to only allow authentication when the connection is encrypted. So we are not offered authentication over this plaintext connection. (You could allow unencrypted authentication by temporarily setting “postconf -e smtpd_tls_security_level=” and trying again. You would then see this line.)
Are you still connected? Okay, good. So we need an encrypted connection using TLS. You could enter STARTTLS:
And the server would reply:
220 2.0.0 Ready to start TLS
However now it’s getting complicated because you would have to speak TLS which is not human-friendly at all. But we can use OpenSSL instead. Enter “QUIT” to terminate the SMTP connection. Instead run:
$> openssl s_client -connect yourmailserver:25 -starttls smtp
You will see a lot of output. OpenSSL has connected to TCP port 25 and issued a STARTTLS command to switch to an encrypted connection. So whatever you type now will get encrypted. Enter:
And Postfix will send a list of capabilities that will look like this:
250-AUTH PLAIN LOGIN
And now that we are using an encrypted connection Postfix offers us to authenticate. So let us send the authentication string with a Base64-encoded password:
AUTH PLAIN am9obkBleGFtcGxlLm9yZwBqb2huQGV4YW1wbGUub3JnAHN1bW1lcnN1bg==
The server should accept that authentication:
235 2.7.0 Authentication successful
Disconnect from Postfix:
221 2.0.0 Bye
Authentication works. Well done.
If you have set John’s password to something other than ‘summersun’ you need Base64-encode it yourself. Use:
$> perl -MMIME::Base64 -e \
Now you can test sending email with authentication enabled. To make even your local network untrusted temporarily you can set:
$> postconf -e mynetworks=
Now you should be forced to use SMTP authentication even in your local network.
Should you get a warning message in your /var/log/mail.log that reads “warning: TLS library problem: 24125:error:14094418:SSL routines:SSL3_READ_BYTES:tlsv1 alert unknown ca:s3_pkt.c:1256:SSL alert number 48:” then you are using a self-signed certificate and the email application refused the certificate. In this case the users need to add an exception so the certificate gets trusted.
If you cannot send email from the mail client and get “Relay access denied” as an error message then it did not properly send a username and password. Re-check the settings of your mail program.