configuring sendmail on FreeBSD
May 3, 2009 (updated to cover FreeBSD 8.x)

The procedures below configure sendmail to work in "outbound-only" mode - that is, to relay mail from the local network onto the internet, but NOT to receive mail from the internet. Incoming mail is handled via some other mechanism - in my case, the mail goes to my hosting provider and then I download it with POP3.

Firstly, if you're looking to configure sendmail to accept mail FROM the internet, don't follow the instructions below, they won't work for you. Secondly, as noted in the FreeBSD handbook, using sendmail for "outbound-only" mail is unnecessary, when ports such as ssmtp do the same job, with a fraction of the complexity.

In an ideal world, the configuration below might be fine, but delivering your mail directly to recipients' servers - as the configuration below does - is no longer a recommended approach, because modern mailservers may reject mail if it does not come from a "known-good" IP address, and it's likely that the IP address you have is NOT one of these. This is a widely-adopted anti-spam measure, and consequently using sendmail in the configuration below may cause you to suffer delivery problems, which you may or may not find out about.

To avoid delivery problems, mail should be routed via your ISP's mailserver. It's possible to use sendmail's SMART_HOST feature for this, but sendmail in outbound-only mode can be replaced entirely with ssmtp (ports/mail/ssmtp), which is reportedly much simpler, and no trouble to manage.

Consequently, the instructions below are deprecated, and should not be used, unless ssmtp or an equivalent is not an option for you.

configuring sendmail

Sendmail (docs: manpage - handbook) is installed and enabled by default. Use this procedure to configure it:

  1. cd /etc/mail
  2. cp access.sample access
  3. vi access
  4. comment out everything except RELAY line
  5. change RELAY line to reflect the subnet of the local LAN (eg. 10.0.0)

    In FreeBSD 8.x, the syntax of this file has changed slightly. The RELAY line now starts with "#Connect:128.32". Uncomment this line, then change it to reflect the subnet of the local LAN

  6. save the file and quit the editor
  7. create hostnames file: vi local-host-names
  8. add new line: localhost
  9. save the file and quit the editor
  10. vi aliases
  11. change the mailer-daemon line as follows (this is a security measure, recommended but not needed to make sendmail work):
    mailer-daemon:  /dev/null
    
  12. save the file and quit the editor
  13. cd /etc/mail/
  14. make
  15. echo sendmail_enable=\"YES\" >> /etc/rc.conf
  16. cp freebsd.mc sendmail.mc
  17. vi sendmail.mc
  18. add these lines above the other FEATURE lines near the top of the file:
    MASQUERADE_AS(`yourdomain.com')dnl
    FEATURE(masquerade_envelope)
    
  19. save the file and quit the editor
  20. m4 /usr/share/sendmail/cf/m4/cf.m4 sendmail.mc > temp.cf
  21. mv temp.cf sendmail.cf
  22. vi /etc/mail/sendmail.cf
  23. (optional) comment out the line DaemonPortOptions=Port=587, Name=MSA, M=E (this stops sendmail listening on port 587)
  24. save the file and quit the editor
  25. cd /etc/mail/
  26. make
  27. /etc/rc.d/sendmail restart

Where yourdomain.com is the name of the domain for which mail is being processed.

This setup permits the server to relay mail sent by any machine on the LAN, and also removes the machine's hostname from any mail originating from the machine.

verifying your sendmail configuration

The checks below ensure sendmail is correctly configured - as I need it to be on my server, which may or may not suit your own network. In particular, this sendmail is configured in "outbound-only" mode. Use the process below if your sendmail is malfunctioning.

Note: before making ANY changes to ANY files ensure to STOP sendmail like this:

/etc/rc.d/sendmail stop

To start it when done:

/etc/rc.d/sendmail start

To check sendmail, login to the server as root, then:

  1. cat /var/log/maillog
    - if the logs have been rotated, extract them to screen as follows: bzip2 -dkc /var/log/maillog.0.bz2
    - to show all sent items, use: cat /var/log/maillog | grep "from="
    - to see new log entries as they are made, use: tail -F /var/log/maillog

  2. cat /etc/rc.conf
    - should contain sendmail_enable="YES"

  3. cat /etc/mail/access
    - everything except the RELAY line should be commented out
    - the RELAY line should contain the subnet of the local LAN, for example:
    192.168             RELAY
    

  4. cat /etc/mail/local-host-names
    - should contain one line:
    localhost
    

  5. cat /etc/mail/sendmail.mc
    - should have these lines above the other FEATURE lines near the top of the file:
    MASQUERADE_AS(`yourdomain.com')dnl
    FEATURE(masquerade_envelope)
    

  6. cat /etc/mail/sendmail.cf | grep "587"
    - this line should be commented out: #O DaemonPortOptions=Port=587, Name=MSA, M=E
    - NOTE: this is optional, it stops sendmail listening on port 587

Audit your sendmail.cf like this:

cd /etc/mail
m4 /usr/share/sendmail/cf/m4/cf.m4 sendmail.mc > sendmail.audit
diff sendmail.cf sendmail.audit

If diff tells you that some lines are different, then you have some manual edits in your sendmail.cf, which are not generated by the m4 file. These edits may or may not be causing issues.

Still got problems? Recompile the config file:

cd /etc/mail
mv sendmail.cf sendmail.cf.old
m4 /usr/share/sendmail/cf/m4/cf.m4 sendmail.mc > sendmail.cf 
make

WARNING: recompiling the sendmail.cf will overwrite any changes previously made to it. Ensure to create the .old file before recompiling, and ensure to add any customisations (such as the port 587 tweak above) AFTER recompiling. Don't forget to stop sendmail before changing anything.

managing the queue

display mails currently on the outbound queue:

sendmail -bp

display the outbound queue directory:

ls -l /var/spool/mqueue

delete all mail on the outbound queue:

/etc/rc.d/sendmail stop
rm /var/spool/mqueue/*
/etc/rc.d/sendmail start

Note: sendmail should be stopped before mail is deleted, then restarted afterwards (this will flush any jobs currently executing, and prevent accidents).

sending mail from the commandline

TIP: by default, sendmail will never masquerade root's mail, which will likely prevent you from mailing from root onto the internet (since the unmasqueraded server address cannot be resolved). There is a sendmail.cf hack (apparently) that fixes this, but this is lame, not only will it be trashed next time sendmail.cf is recompiled, but is masquerading root's mail a good idea? I doubt it. Instead, use sendmail's -f parameter to send mails from any user (see below).

TIP: send a mail from the command line or from a script like this:

cat messagebody.txt | mailx -s "subject" destination@mailbox.com

To use sendmail directly, defining the sender's address (you need to be root, or a trusted user, to define the sender's address):

/usr/sbin/sendmail -f senders@email.com -i -t < completemessage.txt

where completemessage.txt contains:

To: destination@mailbox.com
Subject: test message

Hi there, this is a test message.

See the manpage for an explanation of these switches.

notes