I recently configured smptd to replace a postfix-based solution. smtpd(8) is a joy to work with. In ~four rules I had a working email server!
My next goals was to get content filtering in place. I decided on amavisd-new with clamav and spamassassin. I couldn't find any tutorials for using amavisd with smtpd(8) so I worked out my own solution based on some postfix tutorials and the excellent smtpd.conf(5) doc. Following are the steps and missteps that got me to the working smtpd.conf included at the bottom. I have also have one question for the smtpd(8) developers at the end. The goal was to have smtpd deliver via lmtp to amavisd. Fortunately smtpd in 5.4 (shipping) supports lmtp via the deliver and relay keywords. That’s important as we’ll see in a minute. Installing amavisd is easy. Configuration is another story. For now I'm assuming the user can handle pkg_add -i amavisd-new and starting the relevant daemons. The first step is to create a rule to send inbound email to amavisd rather than procmail. accept tagged default from any for domain <domains> \ relay via lmtp://127.0.0.1:10024 The reason for "relay via" will make sense shortly. Once I had mail delivering to amavisd I had to arrange for smtpd to listen on another port to receive the content-filtered email. The default in the amavis world is to listen on port 10024 and re-inject on 10025. I initially tried writing to rules to “accept from if:port”. That failed miserably. Tagging is the solution. Each “listen on” command can tag client sessions that are later used via “accept tagged <tag>”. With that problem solved I was able to define 3 production listeners and one for testing: listen on lo0 port 10025 tag amavis hostname amavis # re-injection listen on lo0 port 1587 tag test hostname test # testing listen on msk0 port 25 tag default # external listen on lo0 tag default # internal It was at this point I discovered the need for "relay via" rather than "delivery to". Initially I sent mail to amavisd with this rule: accept tagged test from any for domain <domains> virtual <vmap> \ deliver to lmtp 127.0.0.1:10024 That failed. What would happen is "virtual <vmap>" was forwarding the emails to amavisd for delivery to the user’s system account. "To: <user-t...@example.com>" effectively became "To: <user>". When amavisd re-injected the email it was rejected by smtpd because "To: <user>" is an invalid recipient. The solution, then, was to defer the "virtual <vmap" lookup until re-injection. The way to do do that was to use "relay via": accept tagged default from any for domain <domains> \ relay via lmtp://127.0.0.1:10024 With those change in place content filtering began working and has continued to do so. smtpd(8) + spamd(1) + content-filtering = very little spam. The question I have for Gilles et al.: Is there a better way to send the emails to amavisd? It would be more efficient if emails went through "virtual <vmap>" first so invalid recipients were rejected before content filtering. Regardless, I'm happy with the results I'm seeing. Cheers, --Aaron Aaron Poffenberger # $OpenBSD: smtpd.conf,v 1.6 2013/01/26 09:38:25 gilles Exp $ # This is the smtpd server system-wide configuration file. # See smtpd.conf(5) for more information. # To accept external mail, replace with: listen on all # listen on lo0 port 10025 tag amavis hostname amavis # re-injection listen on lo0 port 1587 tag test hostname test # testing listen on msk0 port 25 tag default # external listen on lo0 tag default # internal table vmap db:/etc/mail/virtusertable.db table domains db:/etc/mail/domains.db # public emails before content filtering accept tagged default from any for domain <domains> \ relay via lmtp://127.0.0.1:10024 # re-injection from amavis accept tagged amavis from any for domain <domains> virtual <vmap> \ deliver to mda "/usr/local/bin/procmail -f -" # local delivery accept tagged default from any for local virtual <vmap> \ deliver to mda "/usr/local/bin/procmail -f -" # outbound relay for local users accept tagged default for any \ relay # Easy way to test content-filtering accept tagged test for domain <domains> \ relay via lmtp://127.0.0.1:10024