Why?
You’ve got a server and sometimes you need to send outgoing emails. Like me, you may have messed around using someone elses SMTP server. Maybe, you’ve had a go at setting up Postfix or Exim?
It’s a lot of hard work, isn’t it?
Well, I couldn’t be arsed with all that, and eventually came across the awesome opensmtpd.
If you’re on Debian 10 (Buster), make sure you’ve enabled Debian Backports in your sources.list and run:
sudo apt-get install opensmtpd/buster-backports
You need to install from backports because the configuration syntax changed. The standard buster package will give you version 6.0.3, but we want at least 6.6
Run # smtpd -h
to check:
root@server:/home/simon# smtpd -h
version: OpenSMTPD 6.6.4p1
usage: smtpd [-dFhnv] [-D macro=value] [-f file] [-P system] [-T trace]
Below is the defaut config file “/etc/smtpd.conf”
OpenBSD: smtpd.conf,v 1.10 2018/05/24 11:40:17 gilles Exp $
# This is the smtpd server system-wide configuration file.
# See smtpd.conf(5) for more information.
table aliases file:/etc/aliases
# To accept external mail, replace with: listen on all
#
listen on localhost
action "local" maildir alias <aliases>
action "relay" relay
# Uncomment the following to accept external mail for domain "example.org"
#
# match from any for domain "example.org" action "local"
match for local action "local"
match from local for any action "relay"
For outgoing mail only, we don’t need to touch this at all!
DNS Records
We need to tell our domain registrar that we’re handling our mail now.
First, we’ll set an A
record with the IP address of our server and a hostname of mail
I threw in smtp
as well.
Next we’ll set our MX
records. The 10
in the screenshot below is the priority. I usually see this as 10
so that’s what I’ve been using.
Now we’ll set our SPF (Sender Policy Framework). As long as we’ve set our A
and MX
records, we can just put this as a TXT
record:
v=spf1 a mx -all
If you want to know more, here is a good article on the topic: mailtrap blog
Reverse DNS
Cloudflare explanation of a PTR
record
The Domain Name System, or DNS, correlates domain names with IP addresses. A DNS pointer record (PTR for short) provides the domain name associated with an IP address. A DNS PTR record is exactly the opposite of the ‘A’ record, which provides the IP address associated with a domain name.
DNS PTR records are used in reverse DNS lookups. When a user attempts to reach a domain name in their browser, a DNS lookup occurs, matching the domain name to the IP address. A reverse DNS lookup is the opposite of this process: it is a query that starts with the IP address and looks up the domain name.
So, lastly, you need to set the reverse DNS or PTR
record for you IP on your VPS settings page.
You’ll (usually) find this in your IP settings. All you need to do is put set RDNS or reverse DNS to your hostname. For this site, that’d be
simonh.uk
Let’s check opensmtpd is running correctly:
simon@server:~ [ssh] $ systemctl status opensmtpd
● opensmtpd.service - OpenSMTPD SMTP server
Loaded: loaded (/lib/systemd/system/opensmtpd.service; enabled; vendor preset
Active: active (running) since Fri 2021-06-11 07:47:36 BST; 3 days ago
Docs: man:smtpd(8)
Process: 28100 ExecStart=/usr/sbin/smtpd (code=exited, status=0/SUCCESS)
Main PID: 28101 (smtpd)
Tasks: 7 (limit: 1166)
Memory: 11.8M
CGroup: /system.slice/opensmtpd.service
├─28101 /usr/sbin/smtpd
├─28102 smtpd: klondike
├─28103 smtpd: control
├─28104 smtpd: lookup
├─28105 smtpd: pony express
├─28106 smtpd: queue
└─28107 smtpd: scheduler
Send a test email:
simon@server:~ [ssh] $ echo "hello!" | mail -s 'hi from server!' web@simonh.uk
And in my email client (Claws Mail):
So, all went well.
Closing Notes
Ideally, we’d also set up DKIM, which along with SPF helps to improve the chances of your emails not being labelled as spam. But in my case, it wasn’t worth the trouble (and I did have trouble).
As I’m only sending mail to accounts I control, I can also label them as “NOT SPAM” if they get the dreaded [SPAM]
header.
PKI Encryption (Added 2021-06-15)
Assuming you’re using Apache 2.4 as your web server:
$ sudo apt install certbot python3-certbot-apache
$ sudo certbot certonly -d yourdomain.com --apache
and then in your /etc/smtpd.conf
add the following lines
pki yourdomain.com key "/etc/letsencrypt/live/yourdomain.com/privkey.pem"
pki yourdomain.com cert "/etc/letsencrypt/live/yourdomain.com/fullchain.pem"
listen on eth0 port 25 tls pki yourdomain.com
Then run
root@server:/home/simon# smtpd -n
configuration OK
Finally, restart opensmtpd, and I always check that there are no errors:
root@server:/home/simon# systemctl restart opensmtpd
root@server:/home/simon# systemctl status opensmtpd
● opensmtpd.service - OpenSMTPD SMTP server
Loaded: loaded (/lib/systemd/system/opensmtpd.service; enabled; vendor preset
Active: active (running) since Fri 2021-06-11 07:47:36 BST; 4 days ago
Docs: man:smtpd(8)
Process: 28100 ExecStart=/usr/sbin/smtpd (code=exited, status=0/SUCCESS)
Main PID: 28101 (smtpd)
Tasks: 7 (limit: 1166)
Memory: 11.8M
CGroup: /system.slice/opensmtpd.service
├─28101 /usr/sbin/smtpd
├─28102 smtpd: klondike
├─28103 smtpd: control
├─28104 smtpd: lookup
├─28105 smtpd: pony express
├─28106 smtpd: queue
└─28107 smtpd: scheduler
The final thing to do is to connect from another machine to the server and check the output.
simon@computer:~$ openssl s_client -starttls smtp -connect yourdomain.com:25
CONNECTED(00000003)
depth=2 C = US, O = Internet Security Research Group, CN = ISRG Root X1
verify return:1
depth=1 C = US, O = Let's Encrypt, CN = R3
verify return:1
depth=0 CN = yourdomain.com
verify return:1
---
Certificate chain
0 s:CN = yourdomain.com
i:C = US, O = Let's Encrypt, CN = R3
1 s:C = US, O = Let's Encrypt, CN = R3
i:C = US, O = Internet Security Research Group, CN = ISRG Root X1
2 s:C = US, O = Internet Security Research Group, CN = ISRG Root X1
i:O = Digital Signature Trust Co., CN = DST Root CA X3
---
Server certificate
-----BEGIN CERTIFICATE-----
MIIFEjCCA/qgAwIBAgISA4O0G2Qpj6nXyJYMVicL2zLVMA0GCSqGSIb3DQEBCwUA
MDIxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MQswCQYDVQQD
EwJSMzAeFw0yMTA2MTUxNjQ5NDFaFw0yMTA5MTMxNjQ5NDBaMBExDzANBgNVBAMT
BmIxeC51azCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAN6YKF+LQTPz
2FxMeho/DG5XoapUTlOcTVSGJf/P9v1ZW6qiOKMDv7y9LRXTQ7RdJWp8fd+XN0HT
j/gUNh5iOt3n7KEEa5inl47o7eE/KSKUgvwRkHc4HNmPEgdqQ2QrbvGaOFGzDj07
dA68TNmHk1r3sy1NeJWipTp4qVjyuEVOLShWVBsLl/RL/Esg8XvbSAYwq8LBems/
K4LFrJ4mZ1IVJYZZ+O6oyyCApjlWVy8fxvFNkeZz9Y5nMp7KQuLwRus/jWj/zRiK
KKmtnA0tGm/QydJy2ozGcsyr8inWd+7A7SDpe3KiquznM2nj/3xlg2swKVzBx9zr
Ymh4ibCJdbsCAwEAAaOCAkEwggI9MA4GA1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAU
BggrBgEFBQcDAQYIKwYBBQUHAwIwDAYDVR0TAQH/BAIwADAdBgNVHQ4EFgQUj1Dv
xS3CzTjZ7bRHAf4oT/bsoqYwHwYDVR0jBBgwFoAUFC6zF7dYVsuuUAlA5h+vnYsU
wsYwVQYIKwYBBQUHAQEESTBHMCEGCCsGAQUFBzABhhVodHRwOi8vcjMuby5sZW5j
ci5vcmcwIgYIKwYBBQUHMAKGFmh0dHA6Ly9yMy5pLmxlbmNyLm9yZy8wEQYDVR0R
BAowCIIGYjF4LnVrMEwGA1UdIARFMEMwCAYGZ4EMAQIBMDcGCysGAQQBgt8TAQEB
MCgwJgYIKwYBBQUHAgEWGmh0dHA6Ly9jcHMubGV0c2VuY3J5cHQub3JnMIIBBAYK
KwYBBAHWeQIEAgSB9QSB8gDwAHYARJRlLrDuzq/EQAfYqP4owNrmgr7YyzG1P9Mz
lrW2gagAAAF6EMsQnwAABAMARzBFAiEA0wta1rOTMW7dz8zoJKN8vnPOn9vkyePd
jZt7nzKLk9gCIGV0zwsC1slAZSI48jdTh/QqgWRvh3wBBER/uepFtyJCAHYAfT7y
+I//iFVoJMLAyp5SiXkrxQ54CX8uapdomX4i8NcAAAF6EMsRKwAABAMARzBFAiAZ
SrWghf/uJDEMLg0N9K699d/0RmTr3L8uGFYp/9IBtQIhAMfeqE72W59iwARaf7jG
TmIvVKSbR3Xlls0ZhpJ2TuPoMA0GCSqGSIb3DQEBCwUAA4IBAQArgYBB2rE/PC98
TMOP/oNFRngEH0e5vVpc75r1CFy8urTbrfIW4NB7xevGK9FNQ2n7mUGmrtN1Gcra
WcRld3lzbEb/6jjbFO+X2DtAr8Xbn/MzfSCztEAW9P9iTaCjhHbqAiCsU18n13xb
f9GNkQoU+VSNOXRK6+aMWY/DAkvd0+IJ7qiZwZWFHhFlpPNO35VLSHslD+P02Fsz
BfNw0XhShOM5rBsilqQE3axr6EjTMQknTqWAj3xU/VEQj1H1VK5GonUyJzDVo7/c
X9QgI9F5nItsYFAEZLtRsctS/w8TM0JapAlfxVilgu53r1p97q4yjO94GCCB6tgL
KitlxSDz
-----END CERTIFICATE-----
subject=CN = yourdomain.com
issuer=C = US, O = Let's Encrypt, CN = R3
That all looks good.