OpenSMTPD is a mail daemon currently developed by Gilles Chehade (gilles@), Pierre-Yves Ritschard (pyr@), Jacek Masiulaniec (jacekm@) and others for the OpenBSD operating system. Its goal is to be a secure mailing daemon without the licensing restrictions of Postfix and without the added complexity of sendmail. It is stable, fast, secure, and easy to configure and use.
OpenSMTPD is a FREE, easy to use implementation of the Simple Mail Transfer Protocol. It provides the ability to send and receive emails, as well as act as a relaying host. It aims to be as reliable as possible and to respect RFC and standard behaviors when they don't reduce the overall security of system.
OpenSMTPD is included in FreeBSD as a package or port. We will be going through a few fully working examples for FreeBSD; each config will also work for the newest version of OpenBSD, but the paths of the file will be different. At the end of this tutorial you will have a functional and very secure mail transfer agent (MTA). Let's take a look at the setup.
The mailer.conf is a configuration file for mailwrapper. This config file tells any program which would like to send mail what program to use. The FreeBSD port or package will update the /etc/mail/mailer.conf file with the full paths of the opensmtpd binaries. This is what the /etc/mail/mailer.conf looks like after install. You should not need to edit this file, but we included a copy for reference in case you have any issues.
# $FreeBSD: release/10.0.0/etc/mail/mailer.conf 93858 2020-01-01 01:10:10Z gshapiro $ # # Execute the "real" sendmail program, named /usr/libexec/sendmail/sendmail # ### smtpd: sendmail /usr/libexec/sendmail/sendmail ### smtpd: send-mail /usr/libexec/sendmail/sendmail ### smtpd: mailq /usr/libexec/sendmail/sendmail ### smtpd: newaliases /usr/libexec/sendmail/sendmail ### smtpd: hoststat /usr/libexec/sendmail/sendmail ### smtpd: purgestat /usr/libexec/sendmail/sendmail sendmail /usr/local/sbin/smtpctl send-mail /usr/local/sbin/smtpctl mailq /usr/local/sbin/smtpctl makemap /usr/local/libexec/opensmtpd/makemap newaliases /usr/local/libexec/opensmtpd/makemap
The aliases file is used to map email names to local user names. For example, if we accepted mail for webmaster@example.com we could setup an alias to deliver the mail to the username calomel on this system. Add the external email address followed by a colon ":" followed by the local user name. After editing the file run "newaliases" to update the /usr/local/etc/mail/aliases.db file.
root@machine# cat /usr/local/etc/mail/aliases root: calomel webmaster: calomel freebsd: calomel root@machine# newaliases /usr/local/etc/mail/aliases: 3 aliases
After installing the OpenSMTPd package or port you may have to do some cleanup on the /var/spool/smtpd/ permissions and ownership. The following commands should help you out if this the first time installing.
mkdir /var/spool/smtpd mkdir /var/spool/smtpd/corrupt mkdir /var/spool/smtpd/incoming mkdir /var/spool/smtpd/purge mkdir /var/spool/smtpd/queue mkdir /var/spool/smtpd/temporary chmod 755 /var/spool/smtpd chmod 700 /var/spool/smtpd/corrupt chmod 700 /var/spool/smtpd/incoming chmod 700 /var/spool/smtpd/purge chmod 700 /var/spool/smtpd/queue chmod 700 /var/spool/smtpd/temporary chown _smtpq /var/spool/smtpd/corrupt chown _smtpq /var/spool/smtpd/incoming chown _smtpq /var/spool/smtpd/purge chown _smtpq /var/spool/smtpd/queue chown _smtpq /var/spool/smtpd/temporary ### ### This is what /var/spool/smtpd/ should like like: root@calomel# ls -al /var/spool/smtpd/ drwx--x--x 8 root wheel 8 Feb 10 16:51 . drwxr-xr-x 9 root wheel 9 Feb 10 16:33 .. drwx------ 2 _smtpq wheel 2 Feb 10 16:42 corrupt drwx------ 2 _smtpq wheel 2 Feb 10 16:53 incoming drwxrwxrwt 2 root wheel 2 Feb 10 16:41 offline drwx------ 12 _smtpq wheel 13 Feb 10 16:51 purge drwx------ 44 _smtpq wheel 44 Feb 10 16:52 queue drwx------ 2 _smtpq wheel 2 Feb 10 16:53 temporary
The following examples should provide a good idea of what you can do with OpenSMTPD. You can combine different options from each example in your config file. For example you may need to use the aliases, secret and virtual db files in your config. Let's take a look at some example configurations and how to set them up.
This config file will allow local mail delivery only. Mail will go into the recipient's mbox in ~/Mail according to your procmail rules unless overridden by an entry in the aliases file. No mail will be sent from or accepted to this box from the outside world.
####################################################### ## Calomel.org OpenSMTPD -- /usr/local/etc/mail/smtpd.conf ## https://calomel.org/opensmtpd.html ## listen on localhost (ipv4 only) and port 25 (smtp) listen on 127.0.0.1 port 25 hostname example.com ## the mail aliases database, created with "newaliases" #table aliases file:/usr/local/etc/mail/aliases table aliases db:/usr/local/etc/mail/aliases.db ## accept mail from the local machine (lo0) to localhost accounts and pass to ## the recipient's procmail rules. Address mapping is derived from the aliases file. ## This rule is for internal machine mail only. accept from local for local alias <aliases > deliver to mda "/usr/local/bin/procmail -f -" accept for all relay #######################################################
This configuration is made for a local system which does not accept remote email, but will relay to a central mail server. The user or daemons can send mail to the local machine. Mail that is not destined for the local hostnames will be relayed to the "mailrelay.domain.lan" mail server using standard unencrypted SMTP port 25. For fun, we also want mail that is destined for @somehost.com, i.e. not our domain name, to also be delivered locally. All mail delivered to the local system will be passed to procmail for delivery.
Lets setup an alias file for local mail delivery. An email alias is simply a forwarding e-mail address. Each e-mail alias simply forwards e-mail messages on to each specified e-mail address. Your file may be significantly larger, but as an example we will be aliasing root to calomel. All mail to the user root will be sent to our user calomel.
## FreeBSD root@machine# cd /usr/local/etc/mail/ root@machine# cat /usr/local/etc/mail/aliases root: calomel
Second, make a db of the aliases file like so.
root@machine# newaliases /usr/local/etc/mail/aliases: 1 aliases
Then copy the following into /usr/local/etc/mail/smtpd.conf and start the daemon.
####################################################### ## Calomel.org OpenSMTPD -- /usr/local/etc/mail/smtpd.conf ## https://calomel.org/opensmtpd.html ## listen on localhost (ipv4 only) and port 25 (smtp) listen on 127.0.0.1 port 25 hostname example.com ## the mail aliases database, created with "newaliases" #table aliases file:/usr/local/etc/mail/aliases table aliases db:/usr/local/etc/mail/aliases.db ## accept mail from the local machine (lo0) to localhost accounts and pass to ## the recipient's procmail rules. Address mapping is derived from the aliases file. ## This rule is for internal machine mail only. accept from local for local alias <aliases > deliver to mda "/usr/local/bin/procmail -f -" ## accept mail from any ip address to the hostname calomel.org and pass to ## the recipient's procmail rules. Address mapping is derived from the aliases file. ## This rule is for external mail being snt to a local account. accept from any for domain "somehost.com" alias <aliases > deliver to mda "/usr/local/bin/procmail -f -" ## outgoing mail is accepted from localhost only and relayed through accept from local for any relay via "mailrelay.domain.lan" #######################################################
This configuration is made for a local system which also accepts remote email for the somehost.com domain. The user or daemons can send mail to the local machine. Mail that is not destined for the local hostnames and sent from a local account will be relayed to gmail over TLS port 587. All mail delivered to the local system will be passed to procmail for delivery.
IMPORTANT: In order for OpenSMTPd to connect to the Gmail servers, your gmail configuration must allow "access by less secure apps". Google has published a simple tutorial to help you set the correct settings in their post, "Allowing less secure apps to access your account". If your Gmail account is not setup to allow less secure apps you will receive odd error messages like "Password incorrect", access denied or network connection issues.
First, we to make a file which allows the smtpd daemon to send the username and password to the gmail server so we can relay mail. Make a new file called "secrets" in /etc/mail/. Add the gmail smtp server you are going to relay to and your gmail username and password. Make sure to set the permission of the file to 640 so only root can read and write to the file and the smtpd daemon running as _smtpd can read it.
## FreeBSD root@machine# cd /usr/local/etc/mail root@machine# vi secrets label GMAIL_USERNAME@gmail.com:GMAIL_PASSWORD root@machine# chmod 640 secrets* root@machine# chown root:_smtpd secrets*
Second, make a db of the secrets file. If you received the error, "no credentials for relay through "$myrelay": Undefined error: 0" then the smptd daemon did not find your secrets.db file. Make sure you made the db file in the /etc/mail directory and you have a map line in smtpd.conf like the example below. Run the following line to make the secrets.db file.
## FreeBSD root@machine# cd /usr/local/etc/mail/ root@machine# /usr/local/libexec/opensmtpd/makemap secrets
Now place the following into /etc/mail/smtpd.conf and start the daemon. We have commented every line so you know what they do.
####################################################### ## Calomel.org OpenSMTPD -- /usr/local/etc/mail/smtpd.conf ## https://calomel.org/opensmtpd.html ## listen on localhost (ipv4 only) and port 25 (smtp) listen on 127.0.0.1 port 25 hostname somehost.com ## expire messages in the mail queue after 4 hours. Expired messages will ## be bounced back to the sender after this time. expire 4h ## the mail aliases database, created with "newaliases" #table aliases file:/usr/local/etc/mail/aliases table aliases db:/usr/local/etc/mail/aliases.db ## the file holding the gmail username and password ## created with "/usr/local/libexec/opensmtpd/makemap /usr/local/etc/mail/secrets" table secrets db:/usr/local/etc/mail/secrets.db ## accept mail from the local machine (lo0) to localhost accounts and pass to ## the recipient's procmail rules. Address mapping is derived from the aliases file. ## This rule is for internal machine mail only. accept from local for local alias <aliases> deliver to mda "/usr/local/bin/procmail -f -" ## accept mail from any ip address to the hostname calomel.org and pass to ## the recipient's procmail rules. Address mapping is derived from the aliases file. ## This rule is for external mail being snt to a local account. accept from any for domain "somehost.com" alias <aliases> deliver to mda "/usr/local/bin/procmail -f -" ## outgoing mail is accepted from localhost only and relayed through ## Google's gmail using TLS authentication on port 587. The user and password ## from the map "secrets"' file is used. ## This rule is for local users _only_ to send mail through gmail. No open relays! accept from local for any relay via tls+auth://label@smtp.gmail.com:587 auth <secrets> #######################################################
Check the validity of your configuration file, /usr/local/etc/mail/smtpd.conf .
root@machine# smtpd -n configuration OK
Start the smtpd. Pick one method...
## Start in daemon mode as a background process smtpd ..or.. ## Start in debug mode so you can see error output to the console. smtpd -dv
As of FreeBSD 10, smtpd can be started using the smtpd_enable="" directive in the /etc/rc.conf file. You will also want to make sure sendmail does not start by setting sendmail flags to "NO".
Edit /etc/rc.conf and add the following to start OpenSMTPD on boot and disable sendmail.
root@machine# vi /etc/rc.conf smtpd_enable="YES" ## sendmail daemons disabled dumpdev="NO" sendmail_enable="NO" sendmail_submit_enable="NO" sendmail_outbound_enable="NO" sendmail_msp_queue_enable="NO"
A few readers have sent mail with some features they would like to see in future updates of OpenSMTPD. This list is just to keep track of them. Remember that OpenSMTPD is still in development and stability is most important right now. Features like the following may come later if the developers see them as useful. Also, look in the "Questions" section below for info on contacting the developers directly.
Verbose Logging: Even if you start the daemon with the "-v" argument verbose logging of the daemon does not increase the output to /var/log/maillog. One could expect the logs to show the full conversation between client and server.
Filter header output: For security and privacy you may not want the usernames and ip address of your internal network to be included in the header output of sent mail. Postfix has a filter directive using the "header_checks" file that will accomplish this function. For example, "/^Received:.*.domain.lan/ IGNORE" in postfix would omit any header lines with *.domain.lan in it. This option is required in top secret or secure environment.
Blacklists or RTBL: The ability to query a real time black list (RTBL) like zen.spamhaus.org and deny mail on the results. The majority of spam is sent from compromised windows boxes. The zen list has a list of these types of ips, as well as other lists, and mail could be denied from them. Truthfully, if you are using smtpd you really should be using spamd in front which has support for black lists.
DNS hostname verifications: When a remote mail server connects we could verify that the hostname of the originating ip matches the domain they say they are sending from. We might also want to make sure the HELO statement matches the senders ip. A directive similar to "accept if $CLIENT_HELO equals $SENDER_DOMAIN or error 450" says the HELO header must match the DNS domain name of the client or we send an error 450. The biggest problem with this request is the high cost of dns lookups.
Work with Spamd: When mail is delivered on its first attempt, the connection goes to opensmtpd if the mail passes the checks. It not it is proxied to spamd. This is probably not going to be developed unless a smtpd proxy is put in front of both daemons.
How do I flush a single message from the mail queue ?
First, use smtpctl to show all of the messages in your queue:
root@machine# smtpctl show queue MTA|1244574723.MTwCoXNepGJtbMcJ.441941725|PROCESSING,ENQUEUED|user@our_domain.org|someguy@somedomain.org|1244582934|0
This will schedule the immediate delivery of that message. OpenSMTPD will try to deliver that mail right away.
root@machine# smtpctl schedule 1244574723.MTwCoXNepGJtbMcJ.441941725 command succeeded
How do I print out statistics on the smtpd process?
root@machine# smtpctl show stats mta.sessions=16 mta.sessions.active=0 parent.uptime=157948 queue.inserts.local=5 queue.inserts.remote=11 runner.active=0 smtp.errors.delays=0 smtp.errors.linetoolong=0 smtp.errors.read_eof=0 smtp.errors.read_system=0 smtp.errors.read_timeout=0 smtp.errors.tempfail=0 smtp.errors.toofast=0 smtp.errors.write_eof=0 smtp.errors.write_system=0 smtp.errors.write_timeout=0 smtp.sessions=16 smtp.sessions.aborted=0 smtp.sessions.active=0 smtp.sessions.timeout=0 smtp.sessions.smtps=0 smtp.sessions.smtps.active=0 smtp.sessions.starttls=0 smtp.sessions.starttls.active=0
Where can the logs for smtpd be found?Check in /var/log/maillog for entries similar to this...
root@machine# cat /var/log/maillog | grep smtpd Jan 10 12:30:00 test smtpd[13226]: 1244651996.ZjcewNaiDZhvzdsD: from=<user@our_domain.org>, size=471, nrcpts=1, proto=ESMTP, relay=localhost [IPv6:::1] Jan 10 12:30:00 test smtpd[20966]: 1244651996.ZjcewNaiDZhvzdsD.2164998912: to=<someguy@somedomain.org>, delay=0, stat=Sent
Does opensmtpd support smtp auth ?yes, the daemon supports smtp for both incoming and outgoing sessions over ssl (smtps or tls). -gilles@
What is the error, "couldn't enqueue offline message; smtpctl exited abnormally" followed by "sendmail: unknown option -- L" ? This is a known bug (seen Jun 2009) that will be fixed soon. Make sure to clear out the old mail queue before starting smtpd on a new build.
What is the error, "fatal: queue_load_envelope: fopen: No such file or directory" followed by "lost child: runner exited abnormally" ?This probably means that the /var/spool/smtpd/ queue directories are out of sync somehow. Opensmptd will not start if this is true. To fix this problem you can just delete all of the files and directories under that path. Like so, "rm -rf /var/spool/smtpd/*". Opesmtpd will remake all of the queue directories when it starts.
What is the error, "error on start warning: could not load cert: lo0, no SSL/TLS/AUTH support" ?This is a known bug that should be fixed soon (seen Jun 2009). Even though we are not using a SSL cert for mail and it is not configured, this error still shows up. It is an informational message only.
What is the error, "send-mail: write error: Broken pipe" ?The mail server will return this error if it unexpectedly dies or is killed.