Configure outgoing email from FreeBSD with sendmail

When you’re setting up a new host, sometimes it’s tricky to get outgoing email working right. I noticed that there isn’t a good guide for stock FreeBSD (except “install ssmtp instead“) so I wrote up some simple notes. I assume your system is connected to the Internet, including DNS, and your main goal is to get outgoing mail like cron job output sent offsite. You have your own domain name but use split DNS so internal hostnames are of the form “myserver.local”.

Assuming you’re on a private IP network (such as 10.* or 192.168.*), use a local hostname such as “myserver.local” in /etc/rc.conf or setup internal DNS. You can test it resolves via “nc myserver.local”. You’ll want to set an alias for root in /etc/mail/aliases. Let’s say you used “admin@example.org” here. The corresponding db file won’t be rebuilt unless you also type “make” in /etc/mail, but we’ll be doing that below.

Now copy the stock .mc files to your own local copies:

cp freebsd.mc ${HOST}.mc
cp freebsd.submit.mc ${HOST}.submit.mc

To rewrite the “From” domain to match your real domain, add the following to ${HOST}.mc:

MASQUERADE_AS(`example.org”)
FEATURE(`masquerade_envelope’)

This means mail from “user@myserver.local” will appear to come from “user@example.org” instead. The one exception is the root user, which is typically not rewritten. But if your goal is to capture cron output, root is the user you want to rewrite.

Unfortunately, the default for this is buried in a m4 file. You’ll have to edit /usr/share/sendmail/cf/domain/generic.m4. Make a backup if you’re concerned. Comment out the below line by adding “dnl” in front of it like this:

dnl # EXPOSED_USER(`root’)

Now “root@myserver.local” will become “root@example.org” as well. The final step to make this new configuration active is to run “make install” in /etc/mail. This will create your new /etc/mail/sendmail.cf from the appropriate files. You can restart sendmail with “make restart”.

The above approach is needed to avoid exposing the private domain “myserver.local” in the email headers since many remote servers will reject mail coming from a domain that doesn’t resolve. If you have a central host that does all this rewriting for you, you can just forward the mail to it for handling by the SMART_HOST directive in ${HOST}.mc.