Sendmail Notes

I have trouble with the default settings for sendmail that are supplied with most distributions. Their assumptions don't seem to fit my needs at all. To satisfy those needs, I don't install sendmail with the distribution but install it from source, and I have three sendmail configuration files.

I have a home network. Each of the desktop boxes passes the email up to my outgoing mail server. I also have an inbound mail server. So I have three sendmail configuration files - one for the desktops, one for the outgoing mail server and one for the incoming mail server.

Where to get information

I got most of my knowledge to help me set my email system up from three sources.

  • the README and INSTALL files that come with the sendmail sources. There are several of these, in the base directory and in the cf directory and again in cf/cf. Read them all.
  • Craig Hunt's book Linux Sendmail Distribution. This is a great book. I got a lot of benefit from it.
  • the O'Reilly sendmail book, by Bryan Castales and Eric Allman. Chapter 19 is the important one for m4 configuration. However the book is full of stuff and I jump all over the place.

Preliminary setup

Removing old sendmails

If you already have sendmail installed, then get rid of it completely. I use Slackware so I use removepkg. I check for the executables, and directories like /usr/share/sendmail and /etc/mail and then I delete the lot. I make sure all trace of previous sendmails are gone. Start with a clean slate.

Setup sendmail user and group

Before doing anything else, check that the mail user and group are set up. Look in /etc/passwd for user smmsp with uid 25. Then check in /etc/group for group smmsp with gid 25. If they are there, good. If not, add them with:

  • groupadd -g 25 smmsp
  • useradd -u 25 -g smmsp -d / smmsp
Then edit /etc/passwd and remove the shell. You want the line to look something like "smmsp:x:25:25::/:". I notice that Slackware has the line set to "smmsp:x:25:25:smmsp:/var/spool/clientmqueue:", and that's okay too, so I leave it at that.

Setup sendmail config directory

If you don't have /etc/mail, then create it.

Make sure that /etc and /etc/mail have correct permissions. Both should allow only the user (owner) to write to it. If this is not set correctly, then the aliases cannot be correctly created.

  • chmod 755 /etc
  • chmod 755 /etc/mail

Setup spool directories

We need two spool directories - /var/spool/clientmqueue and /var/spool/mqueue. If they aren't there, create them. Then make sure they have the correct owner and permissions.

  • cd /var/spool
  • mkdir clientmqueue
  • chown smmsp:smmsp clientmqueue
  • chmod 770 clientmqueue
  • mkdir mqueue
  • chown root:root mqueue
  • chmod 700 mqueue

Compile and install sendmail

Download the latest version of sendmail from sendmail.org. Get the most recent stable on with the maximum security patches in it. Get source. Currently I am using sendmail 8.12.10.

This shows how to get recent versions of sendmail running. To do this, you'll need to have m4 available. Make sure it's on your systems. If it isn't installed, get a copy and install it. Try Freshmeat. Or check your distribution disk and install from there. Most Linux will have it, but I've installed sendmail on Solaris and had to install m4 first.

Compile sendmail

  • log on as root
  • cd /usr/src
  • get the sendmail tarball
  • tar xvf sendmail-8.12.10.tar
  • cd sendmail-8.12.10
  • sh Build

Install the sendmail executables and other files

  • sh Build install
  • the sendmail executable needs specific ownership and permissions (read and execute and set GID), so
    • chmod 2555 /usr/sbin/sendmail
    • chown root:smmsp /usr/sbin/sendmail

Configure sendmail

  • cd /usr/src/sendmail-8.12.10/cf/cf (or wherever the source directory is)
  • get the appropriate mc for this machine (see below), copy it to this directory and name it sendmail.mc
  • create sendmail.cf from sendmail.mc with "sh Build sendmail.cf"
  • copy the two files - sendmail.cf and submit.cf - to /etc/mail with "sh Build install-cf"
  • these two files need specific ownership and permissions. The Build script will create them with the correct ownership and permission, but it's best to check them yourself and make sure they are right, so
    • cd /etc/mail
    • chown root:root sendmail.cf submit.cf
    • chmod 444 sendmail.cf submit.cf
  • set up aliases
    • cd /etc/mail
    • chown root:root aliases*
    • edit aliases and make sure there is an entry for postmaster
    • newaliases (Won't work unless the hostname is valid and a reverse DNS lookup can be done. On an existing machine this is not a problem, but on a new machine, you might have to wait till the machine comes up with final valid hostname.)

Setup start/stop scripts

Make sure you have a startup script in /etc/rc.d (assuming Slackware). If you're not using Slackware, find the appropriate place. If you don't have a startup script for sendmail, set up something like this one, which comes from Slackware.

Set permissions so it will execute.

We need to start two instances of sendmail, one as an MTA to handle outbound mail, and one to handle the cleanup of the error queue (clientmqueue)

rc.sendmail

#!/bin/sh
# Start/stop/restart sendmail.

# Start sendmail:
sendmail_start() {
  if [ -x /usr/sbin/sendmail ]; then
    echo "Starting sendmail MTA daemon:  /usr/sbin/sendmail -L sm-mta -bd -q25m"
    /usr/sbin/sendmail -L sm-mta -bd -q25m
    echo "Starting sendmail MSP queue runner:  /usr/sbin/sendmail -L sm-msp-queue -Ac -q25m"
    /usr/sbin/sendmail -L sm-msp-queue -Ac -q25m
  fi
}

# Stop sendmail:
sendmail_stop() {
  killall sendmail
}

# Restart sendmail:
sendmail_restart() {
  sendmail_stop
  sleep 1
  sendmail_start
}

case "$1" in
'start')
  sendmail_start
  ;;
'stop')
  sendmail_stop
  ;;
'restart')
  sendmail_restart
  ;;
*)
  echo "usage $0 start|stop|restart"
esac

Start sendmail

Once the startup script is in place, you can start sendmail with "/etc/rc.d/rc.sendmail start".

Use ps to check that it started. Then view /var/log/maillog and check that it started okay and there are no errors.

Test sendmail

  • Send a test email. Easiest way is to "telnet localhost 25" and then manually go through the SMTP transaction.
  • Watch for file or permissions errors.
  • Tail /var/log/maillog and check for errors.
  • Make sure the email was received and has correct headers.

Configuration files

mc file for desktops

This mc file is for the desktops. It passes the mail up to a specific server. No other files need to be configured in /etc/mail.

include(`../m4/cf.m4')
VERSIONID(`sendmail for desktops')dnl
OSTYPE(linux)dnl
FEATURE(always_add_domain)dnl
FEATURE(`masquerade_envelope')dnl
MASQUERADE_AS(`hatty.com')dnl
define(`SMART_HOST',`outbound.internal')dnl
undefine(`USE_CW_FILE')dnl
MAILER(local)dnl
MAILER(smtp)dnl

mc file for outgoing mail server

This mc file is for the outgoing email server. This will accept email from the internal network desktops, and relay it to the final destinations. Relaying is on, but only for the internal network and this is controlled by the access file.

include(`../m4/cf.m4')
VERSIONID(`sendmail for outbound email server')dnl
OSTYPE(linux)dnl
FEATURE(`nouucp',`reject')dnl
FEATURE(`access_db')dnl
FEATURE(`blacklist_recipients')dnl
define(`confSMTP_LOGIN_MSG', `outgoing mail server: passing on the mail')dnl
MAILER(local)dnl
MAILER(smtp)dnl

For this to work, you also need to set up the /etc/mail/access file like this:

192.168.1      RELAY

where the IP address specified is enough to identify only the network you want to relay email for. My home network is all 192.168.1.*, and 192.168.1 is enough to allow all email from all my local boxes to be relayed. So create /etc/mail/access and then "makemap hash access < access" to create the access.db database.

mc file for incoming mail server

This mc file is for the incoming email server. This will accept email from outside my network and save it for my users who pick it up using POP. This is the basic configuration with some extra blocking controls to control spam and with virtual domains.

include(`../m4/cf.m4')
VERSIONID(`sendmail for inbound email server')dnl
OSTYPE(linux)dnl
VIRTUSER_DOMAIN(hatty.com)dnl
VIRTUSER_DOMAIN(annie.com)dnl
FEATURE(`virtusertable', `hash /etc/mail/virtusertable')dnl
FEATURE(`access_db')dnl
FEATURE(`blacklist_recipients')dnl
FEATURE(`nouucp',`reject')dnl
define(`confSMTP_LOGIN_MSG', `generic mail server: accepting most mail')dnl
MAILER(local)dnl
MAILER(smtp)dnl

The virtual domains are accepted by specifying them with VIRTUSER_DOMAIN. The virtusertable specifies what user gets the mail for the domains. This is my /etc/mail/virtusertable which directs all mail for the domains to those users. I have a login for each of those users. The file is turned into a database with "makemap hash virtusertable < virtusertable".

@hatty.com    hatty
@annie.com    annie

Spam controls are provided by the access table. I can block specific To addresses, and specific From addresses, and specify the rejection message. This is turned into a database with "makemap hash access < access".

To:hatty@hatty.com       ERROR:550 Unsolicited junk mail is not accepted
To:h5@hatty.com          ERROR:550 Unsolicited junk mail is not accepted
To:hussy@annie.com       ERROR:550 No one here by that name
From:lovelorn@iguana.net ERROR:550 Looking for love in all the wrong places

Combining the servers

Right now I keep the incoming and outgoing mail servers separate. That was because I set the system up when I hadn't learnt how to relay only from my internal network. Now that I know how to control that, I am considering using one server for both incoming and outgoing. The easiest configuration would use the same mc file for the incoming mail server, but add the line

192.168.1      RELAY

to the access table. That should do it.

5 December 2003
I needed to merge the inbound and outbound servers sooner than I thought. I was driving my outbound server too hard. I was running seti, and indexing 50,000 HTML files for a search engine, and sendmail logged that the load was too great and it was refusing to accept connections. I never thought that sendmail did that, but now I know better. That server will at times get heavily used, so I decided to merge the inbound and outbound servers. Adding that RELAY line to /etc/mail/access does do what I thought it would do. It all works.

[Linux]