loading . . . OpenSMTPD Is The Mail Server For The Future
_Image credit:the OpenSMTPD project_
© 2026 Peter N. M. Hansteen
_The SMTP mail server for the 21st century and onwards is_OpenSMTPD _, which is developed as an integral part of_OpenBSD _, but available in a portable variety too._
It was one of those things that I had fully intended to do years ago, but I only got around to actually doing once there was a definite deadline to get it done.
The time has come, as _OpenBSD 7.9_ will leave the `exim` package behind, and `exim` users will need to find a replacement before upgrading. This article describes my transition to OpenBSD's own _OpenSMTPD_ mail server.
* * *
_OpenBSD 7.9 will leave the `exim` package behind, and `exim` users will need to find a replacement._
_OpenSMTPD (`smtpd`) is in the base system._
* * *
When _OpenSMTPD_ was first introduced in the _OpenBSD_ base system in _OpenBSD 4.6_ in October 2009, I had already been running a mail service for some years.
At the time I still found it convenient to keep using `exim` as the real mail server, protected by OpenBSD `spamd` in the incoming signal path and with a combination of `spamassassin` and `clamav` for content filtering.
It seemed quite tempting to me to play around with at the new `smtpd` at the time, but the initial version of the new mail server was not yet considered quite ready for prime time.
* * *
**Note:** This piece is also available _without_ trackers but _classic_ formatting only here.
* * *
The pace of development was quite hectic in the early years, and by the time `smtpd` replaced the classic `sendmail` as the default mail server in OpenBSD with the November 2014 _OpenBSD 5.6_ release, I had just completed the _third_ edition of _The Book of PF_ and I was interested, but the writing had been quite a drain on my energy.
And of course, the mail server setups I had running for myself and friends I thought of as complex enough that moving to something else would require quite some preparation and testing. So I would leave looking into the new mail server software properly for another day, soon to come, I was sure.
## An Old Setup, Maintained With Much Love and Care
There are some hints of what that setup did (and still does) in the 2012 piece _In The Name Of Sane Email: Setting Up OpenBSD's spamd(8) With Secondary MXes In Play - A Full Recipe_ (also _tracked, prettified_), but the main features are:
* Two (originally three) separate sites, each with their own domains, where the other site(s) provide secondary MX duty for the other(s), each with a `spamd`-instrumented OpenBSD machine as the Internet-facing part of the mail setup
* The OpenBSD machines perform spamd _greylisting_ and _greytrapping_ , but also provide content filtering on behalf of another set of domains with their own, not necessarily Internet-exposed, mail servers that receive the filtered mail relayed to them by the Internet-facing mail services.
This setup, with OpenBSD `spamd` in a greylisting and greytrapping setup in front and content filtering as the second stage before finally relaying to the protected mail hosts, worked well enough that we simply kept the systems running with only routine system and package upgrades and minor adjustments to configurations as needed.
In short, domains to be served came and went, but the `spamd`, `exim` and `clamav`+`spamassassin` combination stayed, on the ever reliable _OpenBSD_ platform.
## Time To Move On, Wait, Then Finally ...
Over the years, there were several episodes with medium to severe security flaws discovered in the `exim` codebase, but the OpenBSD package was generally well maintained and fixes tended to appear within a reasonable time.
From time to time OpenBSD developers and port maintainers discussed dropping support and removing `exim` from the package system, but it was only in early 2026 it finally happened.
_OpenBSD 7.9_ will ship without an official `exim` package.
So it was finally time for even this holdout to move to something else.
## And Of Course, A False Start
Other OpenBSD users had kept telling me how good OpenSMTPD had become, so I decided now was the time, so I dug out some old notes and started experimenting.
Those old notes turned out to be utterly useless, and for a reason: The _OpenSMTPD 6.4_ release was the result of a major code overhaul that also changed important parts of the `smtpd.conf` syntax.
Unfortunately a majority of the third party guides out there that turn up early in search results still use the old syntax, and as a consequence, are useless, at least to users on OpenBSD or other platforms that have kept their code reasonably in sync. A useful rule of thumb is, if you find yourself reading an _OpenSMTPD_ guide that is dated before 2020, do yourself a favor and move on to something newer.
* * *
> _If you find yourself reading an_OpenSMTPD _guide is dated before 2020, do yourself a favor and move on to something newer._
* * *
## The Task At Hand: The Analysis
But to the problem at hand. The setup I was setting out to convert, was one that needed to accommodate
* Inbound mail for users in the local domains, where we are the primary mail exchanger
* Inbound mail for users in the domains where we are the secondary mail exchanger
* Inbound mail for the users in the domains where we are the primary public-facing mail exchanger, but where we actually only relay after greylisting and filtering
* Outbound mail from the local domains
* Outbound mail from networks we have chosen to trust enough to relay for
The mail exchanger (MX) records for all domains involved were already in place, as was other relevant DNS information such as _SPF_ , _DKIM_ and _DMARC_ records. TLS certificates and a regime for maintaining them was already in place, using _LetsEncrypt_ tools.
That analysis converted to `smtpd.conf` logic would be:
* We keep the existing `/etc/mail/aliases` file, the formats are compatible
* OpenSMTPD conveniently has tables, which can be either simple lists or key-value pairs. Our tables are:
* `domains_local` lists the domains we receive mail for to handle locally
* `relay-for_domains` lists the domains we only filter for, then relay to
* `domain_relays` is the list of domains and their final destination mail exchangers as list of key-value pairs
* `relay_from_ips` is the list of IP addresses and networks we allow relaying for
## Now The Actual Implementation
So I set to work from that specification, and at the end of that afternoon I had reached the conclusion that
* setting up for TLS was the easiest, with simple `pki` statements
* `listen` statements actually do the work in very limited space
* routing to local delivery and forwarding is easy with a combination of `action` and `match` rules
* for filtering, `clamav` had not actually been of much use to my users (no Windows users among them), and that the filtering options that made use of `spamassassin` for the back end were either not functional or I was too dense to make any sense of them.
I ended up testing a modern alternative, `rspamd`, which is available via the OpenBSD package system.
* `dkimproxy` looked like a good candidate for signing outgoing messages, so I tested that for a while, but on the advice of Martijn van Duren, I switched to `dkimsign`, which is available on OpenBSD as the package `opensmtpd-filter-dkimsign`.
In addition to `smtpd`, which is already in base, this configuration requires the packages `opensmtpd-filter-dkimsign` and `opensmtpd-filter-rspamd`.
Installing both via `pkg_add` have the packages pull in all required dependencies.
With the prerequisites in place,
disable and stop `exim`
` doas rcctl disable exim && doas rcctl stop exim`
disable and stop `clamav`
` doas rcctl disable clamav && doas clamav stop clamav`
disable and stop `spamassassin`
` doas rcctl disable spamassassin && doas rcctl stop spamassassin`
At some point, you should remove the packages with
`doas pkg_delete _packagename_`
and follow the steps outlined in the package delete message.
Don't remove the `exim` configuration, though, until you have copied the useful parts across to your new `/etc/mail/smtpd.conf`.
I ended up with this configuration (lightly edited for brevity)
` **---- /etc/mail/smtpd.conf**
table aliases file:/etc/mail/aliases
table domains_local {
"bsdly.com",
"bsdly.eu",
"bsdly.net",
"bsdly.no",
"bsdly.org",
"bsdly.se",
"nxdomain.no",
# plus a lot of other domains, elided here for brevity
}
table relay_for_domains {
"nuug.no",
"blug.linux.no"
# again more domains in the real smtpd.conf, left out here
}
table domain_relays {
"nuug.no" = "smtp://mx1.nuug.no",
"blug.linux.no" = "smtp://mail.lamasti.net"
# again more domains in the real smtpd.conf, left out here
}
table relay_from_ips {
127.0.0.1
::1
# The rest are fictional, RFC5737 and RFC3849
192.0.2.0/24
198.51.100.0/24
203.0.113.0/24
2001:DB8::/32
}
filter "rspamd" proc-exec "filter-rspamd"
filter dkimsign_rsa proc-exec "filter-dkimsign -d bsdly.net -s x -k /etc/mail/dkim/private.rsa.key" user _dkimsign group _dkimsign
pki skapet.bsdly.net cert "/etc/mail/certificate.pem"
pki skapet.bsdly.net key "/etc/mail/privkey.pem"
listen on socket
listen on all port 25 tls pki skapet.bsdly.net filter "rspamd"
listen on all port 465 smtps pki skapet.bsdly.net filter "rspamd"
listen on all port submission tls pki skapet.bsdly.net
action "local_mail" mbox alias <aliases>
action "relay_domain" relay domain <domain_relays> filter "rspamd"
action "outbound" relay filter dkimsign_rsa
match from local for local action local_mail
match from any for domain <domains_local> action local_mail
match from any for domain <relay_for_domains> action relay_domain
match from src <relay_from_ips> for any action outbound
match from local for any action outbound
**----**`
The specific domain names and IP addresses will be different for the secondary site, as it will for any configuration you will set up.
After some logs and messages observation, I also ended up with minor modifications to the `rspamd` config,
`**---- /etc/rspamd/local.d/actions.conf**
reject = 10; # final reject
discard = 15;
add_header = 6; # mark spam
greylist = null; # do not greylist, we have spamd for that
# Custom action (referenced by force_actions), no own threshold
phishing = {
flags = ["no_threshold"];
}
**----**`
That is the entire configuration. With the somewhat longer list of domains and networks, the net length of my configuration now is
` $ grep -vc \# /etc/mail/smtpd.conf
104
`
104 lines, while the previous `exim` config with comment lines stripped out ran to
` $ grep -vc \# /etc/exim/configure
380
`
380 lines.
The `smtpd.conf` configuration is readable on par with `pf.conf`, with similar readability features.
At any time after installing the packages and disabling the previous services, enable and start the new services.
To (re)enable `smtpd` as the default mail server after running with exim, run
`$ doas /usr/local/sbin/exim-disable`
to restore `/etc/mailer.conf` to its original state.
If all else fails, you can easily retrieve a pristine version from the OpenBSD CVS.
To enable the new services, run
` $ doas rcctl enable smptpd && doas rcctl start smtpd
$ doas rcctl enable redis && doas rcctl start redis
$ doas rcctl enable rspamd && doas rcctl start rspamd
`
You should see activity fairly soon by monitoring `/var/log/maillog`, such as
` $ tail -n 500 -f /var/log/maillog
`
When you are satisfied that mail flows in and out and is relayed where you want it to, it is safe to remove the `exim`, `clamav` and `spamassassin` packages and follow the instructions in the `pkg_delete` messages to free up some space.
And yes, considerably more complicated configurations are possible, especially in the filtering department.
But I was pleasantly surprised at both how simple the transistion has proven to be and the prospect for having truly maintenance and enhancement friendly setup going forward.
The transition process has showed me that OpenSMTPD product is solid, like the wider OpenBSD environment. Making OpenSMTPD the default mail server software was no doubt one of those extremely good decisions the OpenBSD project has made, and even latecomers like myself applaud the decision.
OpenSMTPD and OpenBSD both are characterized by their developers' ability to not only learn from earlier iterations of development of the operating system and the mail server component, but also to come up with new, and some times radically different, approaches to known problems that result in a more secure and more useable product. To my mind, this _is_ the mail server and the operating system for the future.
If you are interested in setting up `smtpd` with more filters or other ones, quite a few are available, including such things as `opensmtpd-filter-dnsbl`, which pulls in DNS blocklists from the sources you specify.
OpenSMTPD is available on a wide variety of platforms, including various Linux distributions and BSDs such as FreeBSD via its `-portable` variety.
I have kept this configuration rather minimal, mostly because in my experience, the greylisting and greytrapping `spamd` is a very efficient and low maintenance outer shield for any mail service. If you are interested greytrapping, the infrequently updated _Eighteen Years of Greytrapping - Is the Weirdness Finally Paying Off?_ (also _tracked, prettified_) provides more reading material via its numerous links than you could reasonably take in during even a long evening.
If you would rather have a book that covers more networking topics with OpenBSD and FreeBSD as the platform, and includes a fairly extensive treatment of `spamd`, _The Book of PF_ , now in its _fourth_ edition, is for you.
Good night and good luck!
I want to thank _Martijn van Duren_ for useful advice while working on this article.
* * *
_OpenSMTPD is the Mail Server for the Future_ is © 2026 Peter N. M. Hansteen (published 2026-05-15)
* * *
You might also be interested in reading selected pieces via _That Grumpy BSD Guy: A Short Reading List_ (also _here_).
* * * https://bsdly.blogspot.com/2026/05/opensmtpd-is-mail-server-for-future.html