Sendmail, with its cryptic single-character option tags and notorious
rewriting rule sets, has nevertheless always been the premier Internet
mail transfer agent. But the latest releases, with macro-based configuration
and spelled-out options, add some ease-of-use and sophistication to the
program's traditional power.
By Richard Reich
Please address questions regarding this article to the author at richard@reich.com
.
Table of Contents
Sendmail is the most common SMTP mail transfer agent on the thousands of
mostly Unix-based Internet hosts that handle mail routing and serve as
post offices. Millions of e-mail messages are handled by Sendmail every
day. Although it is very popular, Sendmail has been obscure and difficult
to configure during much of its long history. Recent versions of Sendmail,
however, have a much improved configuration system, based on the m4
macro processor and a large set of predefined m4 macros.
This tutorial does not pretend to be a complete treatment of Sendmail.
But it will try to show the average system administrator that Sendmail,
with macro-based configuration, can be set up usefully with a reasonable
amount of study and attention.
The focus will be on Berkeley Sendmail version 8.7, the freely distributed
version maintained and improved by its original author, Eric Allman. Most
Unix system vendors include ``Sendmail,'' but often these are old versions,
almost always lacking the m4-based configuration environment and other
improvements. In addition, older versions of Sendmail have well-known security
problems that are repaired in the later versions available from Berkeley.
Although there are generally valid arguments against early adoption of
new versions of critical software, Sendmail may be an exception to the
rule.
This tutorial first describes Internet mail basics and a common strategy
for SMTP mail handling on an Internet-connected local network. Sendmail
configuration is treated in the context of implementing the example mail
strategy. Sendmail's UUCP capabilities, perhaps less relevant than they
were a few years ago, are outside the scope of this presentation. (Sendmail,
even with tractable configuration tools, is t oo large a topic to present
in the abstract in this limited space.)
Quick Overview of Internet mail
The rules that permit heterogeneous computer systems to interoperate smoothly
on the global Internet are set forth in documents called Requests For Comments,
or RFCs. The format of Internet mail messages is defined by RFC 822 (see
Reference 6) . Thus, Internet e-mail is often called ``RFC 822'' mail.
The protocol used to send RFC-822 e-mail between host computers is referred
to as the Simple Mail Transfer Protocol, or SMTP, and is defined in RFC
821 (see Reference 5) .
RFC-822 Mail Format
The format of Internet mail is fundamentally very simple: various required
and optional message attributes come first in a ``header,'' followed by
a blank line, then the ``body'' of the message. The header fields predominate
in the short example message shown here:
Editor's Note: The long ``received'' lines were wrapped then
indented so they'll fit in the average window.
Return-Path: pete@maclean.com
Received: from tempo.maclean.com (tempo.maclean.com [204.182.19.66])
by goldengate.reich.com (8.7.1/8.7.1/FultonSt-gg0916) with ESMTP
id WAA01451 for <richard@reich.com>; Sun, 15 Oct 1995 22:09:10 -0700
Received: from petewin95.maclean.com (petewin95.maclean.com [204.182.19.95])
by tempo.maclean.com (8.7.Beta.10/8.7.Beta.10/FultonSt-tempo0806) with
SMTP
id WAA12144 for <richard@reich.com>; Sun, 15 Oct 1995 22:09:08 -0700
Message-Id: <199510160509.WAA12144@tempo.maclean.com>
X-Sender: pete@tempo.maclean.com
X-Mailer: Windows Eudora Pro Version 2.1.2
Mime-Version: 1.0
Content-Type: text/plain; charset="us-ascii"
Date: Sun, 15 Oct 1995 22:06:05 -0700
To: richard@reich.com
From: Pete Maclean <pete@maclean.com>
Subject: A question...
Just wondered if this message will appear in your Sendmail article?
-p
The blank line after the ``Subject'' line divides the header from the message
body that follows. Any subsequent blank line is part of the message body
and has no structural significance. Most header fields are brief and have
an intuitively obvious meaning ( Subject: A question... ) while
some others are lengthy and not readily understood ( Received: from...
). For a good explanation of many standard as well as non-standard
header fields, see Chapter 31 of Sendmail (Reference
1) .
Each header line consists of a ``keyword-value pair'' that declares
one specific characteristic of the message. For instance, the required
line that specifies the recipient of the message consists of the keyword
``To:'', one or more space or tab (white space) characters, followed by
the value that specifies the mailing address of the recipient, here ``richard@reich.com''.
Simple Mail Transfer Protocol (SMTP)
SMTP is a TCP-base d, client-server protocol. Its operation is really quite
simple: after a reliable connection is established, the client initiates
a brief handshake sequence. Then the client sends one or more messages
to the server. Preceding each message, the remote system is given a list
of the message's local recipients as well as the sender's address. This
information is referred to as the message's ``envelope''. The natural metaphor
of physical letters is instructive: to send a letter to several people
at different locations, for each recipient place a copy of the letter in
an envelope, which bears both the recipient's address and the return address
of the sender, and post individually to each envelope addressee.
This exchange of information takes place in a formal language of four-character
commands and three-digit reply codes, but it is usually replete with human-readable
comments that render transcripts of SMTP sessions quite easy to follow.
A somewhat improved version of SMTP, Extended SMTP, or ESMTP, i s now in
wide use. Here's a real example of an ESMTP mail exchange log. Don't worry
about what everything means, but note the basic simplicity of the conversation.
Editor's Note: The long lines in this example were wrapped and
then indented four spaces so they'll fit on the average window.
$
/usr/sbin/sendmail -v pete@maclean.com < message
pete@maclean.com... Connecting to tempo.maclean.com. via smtp...
220 tempo.maclean.com ESMTP Sendmail 8.7/8.7/FultonSt-tempo0806;
Sun, 15 Oct 1995 22:47:52 -0700
>>> EHLO goldengate.reich.com
250 tempo.maclean.com Hello richard@goldengate.reich.com [204.182.19.1],
pleased to meet you
>>> MAIL From:<richard@goldengate.reich.com>
250 <richard@goldengate.reich.com>... Sender ok
>>> RCPT To:<pete@maclean.com>
250 Recipient ok
>>> DATA
354 Enter mail, end with "." on a line by itself
>>> .
250 WAA12161 Message accepted for delivery
pete@maclean.com... Sent (
WAA12161 Message accepted for delivery)
Closing connection to tempo.maclean.com.
>>> QUIT
221 tempo.maclean.com closing connection
Interfaces and Agents
The ``life cycle'' of an e-mail message involves several distinct stages.
Writing a mail message is quite different than sorting envelopes, which
in turn, is different than delivering mail. This is true in the realm of
electronic mail as well as in the world of surface postal mail (a.k.a.
snail mail).
Preparing and reading e-mail is done with a Mail User Agent (MUA). The
qualities that people prefer in a MUA vary, as do the platforms on which
MUAs are implemented. This leads to a wide variety of different MUAs, catering
to different tastes in user interfaces, capabilities and platforms. Some
examples include: Eudora, elm, pine, mh, exmh, xmail, mailx, Mail, mail,
etc.
Delivering e-mail is generally handled by programs (Mail Delivery Agents,
or MTAs) that do one specific type of delive ry. For example, putting mail
into a local mailbox file on Unix systems is often handled by so called
``bin'' mail (probably named because
it classically had path name /bin/mail ), sending mail via UUCP
is done by uux , while forwarding
mail via SMTP is done by Sendmail itself.
Mail Transfer Agents, like Sendmail, handle everything else. An MTA
determines how a message has to be routed to get to a recipient. It accepts
mail from another transfer agent and relays it to an agent closer to the
ultimate recipient. It handles the interpretation of address aliases. It
transforms addresses so that the panoply of incompatible delivery agents
can deal with them properly. It handles special actions required by certain
header fields (for instance, ``Bcc:'' for blind-carbon copy, and ``Return-Receipt-To:''
to verify delivery). It queues messages when delivery can't be done immediately
and handles them later. It rec ognizes bad addresses and other errors and
reroutes or bounces mail as needed. And more.
What Sendmail Does
Let's follow the path a message might take, starting after it's been composed
and is handed to Sendmail by a Mail User Agent.
MUA Sends a Message . We've composed this simple message:
From: Richard Reich <richard@reich.com>
To: pete@maclean.com
Bcc: me
Subject: My Sendmail article
Please read the draft of my Sendmail article. It will be in the
usual place by tonight. Thanks.
-r
This simple note is intended for a single recipient, with a blind carbon
copy for my records. The MUA that composed it will start Sendmail and give
it the message and the list of recipients.
Aliases . An alias is a convenient abbreviation for one or more
full mailing addresses. That is, an alias can just be a nickname for an
address or it can be the name of a list of recipients. Aliases can be maintained
and expanded by a MUA or by Sendmail. Most MUAs keep alias information
in their own version of an alias file. So, if you use, say, elm ordinarily,
its alias file will not be available to Netscape when you use Netscape's
``Mail Document'' function. However, aliases maintained centrally by Sendmail
will be recognized and expanded regardless of which MUA is used to compose
a message.
There is an alias among the recipients of our example message: me. Sendmail
will expand it and discover that the full address for ``me'' is the local
mailbox ``richard''.
Handling Mail . The two recipient addresses are examined by Sendmail.
One is local (me) and the other (pete@maclean.com) is an address at a remote
host.
The message must be transformed slightly to handle the ``Bcc:'' header
properly. Blind copying requires that the primary recipients not be informed
of the blind copy recipient. So Sendmail, after having added my address
to its internal list of recipients, deletes the ``Bcc :'' header field
from the message.
Local Delivery . Assuming Sendmail has been configured to use
``bin mail'' for local delivery, it directs this program to save a copy
of the message in my mailbox.
Local delivery is not always so dull, however. A user can keep private
aliases in the .forward file in their home directory. Mail intended
for delivery to a user with such a file will go instead to the addresses
listed in that file. Mail can even be delivered (as standard input) to
a program you specify in the .forward file. (That's how automatic
mail response is implemented sometimes.)
Remote Delivery . Returning to our example, Sendmail now has
an address that it determines--by examining its format--is probably intended
for a remote Internet recipient. For each remote recipient, Sendmail will
call upon its domain name resolver to find out the Internet host to which
the message should be sent (that is, a mail exchanger--MX--qu ery will
be made). Then, to actually transfer the message, an SMTP session will
be initiated with the MTA (perhaps another Sendmail) at each remote mail
handling host. A failed transfer will result in the message being queued
for later delivery.
The Sendmail daemon . Our sample message will be accepted by
a Sendmail daemon on a remote host (the mail exchanger for maclean.com).
The message will then go through Sendmail's handling process on the remote
system (assuming it's running Sendmail). Presumably, the message will be
delivered locally to the mailbox of the intended recipient. Alias processing,
forwarding, or other kinds of required relaying, however, might result
in the message being passed to still another transfer agent.
The Role of DNS
Sendmail uses the Domain Name System to help it deliver mail. Proper implementation
of a domain's mail handling strategy requires that the configurations of
both Sendmail and DNS be accurate and coordinated. If a message is to be
sent to a non-local recipient, the domain name portion of the recipient's
address must be examined to determine the host where the message should
be sent.
First, Sendmail queries the local DNS resolver to find so-called ``Mail
Exchange or MX records'' for the recipient's domain. For example, to decide
where to send a message addressed to pete@maclean.com, Sendmail will look
for MX records for the domain name maclean.com. The DNS resolver will return
any MX records it finds, often more than one. In the event that the recipient
domain has no MX records defined, Sendmail will query DNS for CNAME or
A records to arrive at a possible mail exchanger host. Multiple MX records--each
specifying an alternative mail-handling host--can be defined for a domain
name. An MX record contains a preference field that ranks its mail exchanger
host relative to others for the same domain name. (The preference field's
value is like a golf score: lower numbers are preferred, w ith zero the
best. The maximum value is 65535). A mail transfer agent is required to
choose the most preferred mail-exchange host among those that are currently
functioning. Given a choice among several equally preferred hosts, Sendmail
will choose one at random.
Continuing with our example (sending a message to pete@maclean.com),
the DNS resolver might return to Sendmail MX records for maclean.com like
the following (rendered here in the textual form used by BIND's configuration
file):
maclean.com. 85676 IN MX 10 tempo.maclean.com.
maclean.com. 85676 IN MX 20 goldengate.reich.com.
The fields here are the recipient domain name, the TTL (time-to-live value
in seconds), the data class, the record type, the preference value and,
finally, the mail exchange host.
The records define a preferred mail exchanger at tempo.maclean.com and
a less preferred one at goldengate.reich.com. This means that Sendmail
will try to send the message to tempo.maclean.com--and failing that--goldengate.reich.com.
If it gets to goldengate, the Sendmail daemon there will make its own attempt
to deliver the message. Unless tempo has recovered in time, goldengate
also fails to relay the mail as we'll see below.
Then a crucial bit of special handling is invoked to avoid sending mail
about pointlessly. Sendmail will not relay mail to a mail exchanger that
has an equal or greater preference value than its own. As long as tempo
is unreachable, goldengate won't be able to relay the message because it
can't find any other acceptable host. It will queue the message to disk
and try to deliver it later.
Thus it's crucial to get the MX records right. If your domain has an
erroneous MX record in its DNS server configuration, your perfectly configured
Sendmail daemon may never see an incoming message. Remote Sendmails (or
other transfer agents) may not find out that your host handles mail at
all!
Inst alling Sendmail and Friends
To get the very latest version of Sendmail, you may want to download the
source package from its home at Berkeley. Compilation and installation
of the Berkeley distribution is a relatively smooth operation. The source
package includes make-description files tailored for many different systems
and a ``build'' script that automatically chooses the correct one. Often
one or two simple changes are necessary to the appropriate make-description
file to match the configuration of a particular system, but these are usually
quite obvious. (See below for where Sendmail and its helpers can be found.)
Berkeley ``db'' is a library for manipulation of indexed data records,
such as the aliases file. Sendmail can get by with weaker data management
packages (for instance, ndbm) or with none at all. But db does enhance
Sendmail's efficiency and robustness.
Sendmail handles SMTP mail transfer directly, but it relies on other
programs to handle other kinds of delive ry. In particular, Sendmail can
be configured to use one of several local mail delivery agents, such as
bin-mail , procmail
, mail.local , or deliver
. All these delivery agents have special features and strengths.
Although mail.local is virtuously simple and procmail is
robust and powerful, it is easiest at first to use whichever local delivery
agent your version of Sendmail is configured for by default.
The Sendmail Configuration File
The Sendmail configuration file, generally named sendmail.cf ,
contains several classes of information that determine the behavior of
Sendmail on a host system:
-
Options determine the values of numerous Sendmail parameters (for
instance, file and directory paths, operational control switches, timeout
values).
-
Header definitions are templates used to specify required and optional
message headers and their formats.
-
Mailer definitions specify the programs that will be used to deliver
various kinds of mail (for instance, local mailbox delivery, delivery to
a file or program) as well as specifying details of Sendmail's interaction
with them.
-
Macro and class definitions provide names for strings and sets of
strings (for instance, domain name of this host, set of alternate names)
that are used in header definitions and rewriting rules.
-
Rewriting rule sets are used to parse and transform addresses. In
addition to controlling the appearance of addresses and directing special
handling of certain classes of addresses, rewriting rules are used by Sendmail
to determine, for each message recipient, the final delivery address, the
mailer to use and the host system where the message should be delivered
(or relayed).
-
Key (map) file declarations specify the path and other attributes
of files that can be used in rewriting rules to lookup and transform elements
of addresses.
With very few exceptions, all of these components of the original Sendmail
configuration file are hidden by the m4-based configuration macro files
(as we'll see below).
For a majority of Sendmail configurations, the m4 macros in the Sendmail
distribution package will suffice. For instance, having mail from all local
hosts ``masquerade'' as though it comes from domain is
a configuration choice that has been foreseen in the Berkeley release--a
one-line macro ( MASQUERADE_AS( domain ) ) takes care of
numerous details, including adding rewriting rules. However, some of the
original configuration elements, like the semantics of Sendmail options
and the nuances of rewriting rule sets, must be understood in their full
glory if customization is attempted beyond that already anticip ated by
the existing m4 macros.
Sendmail Options
Sendmail options are set in its configuration file with the single-letter
command, capital O. In versions before 8.7, all options had single-letter
names. For example, the option A held the path name of the alias file.
Beginning with version 8.7, all options can be referred to by full names.
For instance, the path name of the alias file is now specified by option
AliasFile . The old single-letter option names are still recognized
for backward compatibility.
To avoid any ambiguity between the older single-letter form and the
new full-name form, a space (which may not appear between the O command
and the single-letter option being defined) must appear between
the O command and the full name. For example, to set the name of the alias
file in the old style, use:
OA/usr/lib/aliases
whereas with the new style, employ:
O AliasFile=/usr/lib/aliases
In a m4 configuration file, you need not worry about defining the alias
file name. An operating system specification macro (for example, OSTYPE(irix4)
) takes care of setting it with the m4 statement:
define(`ALIAS_FILE', `/usr/lib/aliases')
Note in the preceeding example how the arguments of the define command
are quoted. First, balanced left and right single-quote marks are used.
Second, non-alphabetic characters in a phrase means that the phrase must
be quoted.
It's not feasible to explain each of the many global configuration options
here that can be set within sendmail.cf . For a complete and up-to-date
list of these options, consult the BSD System Manager's Manual paper
entitled ``Sendmail Installation and Operation Guide'' (see Reference
3 ).
Address Rewriting
Address rewriting rules are the essence of Sendmail's power and its complexity.
They can be seen as a simple, quite specialized, text-oriented programming
language. Two critical tasks that Sendmail performs--rather than being
hard-coded in the Sendmail program itself--are expressed in the language
of rewriting rules, making it relatively easy to configure Sendmail's behavior
very flexibly, without modifying its internal code.
First, Sendmail must examine each recipient's address to determine which
of several mail delivery agents should be used to send the message to--or
closer to--the recipient.
Second, Sendmail may transform addresses in both the envelope and the
message header to facilitate delivery or reply. (This is probably the moment
to address a never-ending controversy that dogs Sendmail: RFC-821, which
defines the SMTP protocol, disallows mail transfer agents from modifying
message header fields, with a couple of exceptions. Sendmail violates this
prohibition. However, if one considers Sendmail to be a mail gateway as
well as an MTA, its ``offending'' behavior can be justified as essential
to its gateway function. Case closed.)
When Sendmail is presented with a message it examines the addresses
in the envelope and the header fields (``From:'', ``To:'', ``Sender:'',
and so forth). Each address is placed in a area called the ``workspace'',
and--depending on whether the address is for a sender or a recipient and
whether it came from the envelope or a message header field--certain rule
sets are applied to the address in a prescribed order. Also, once the appropriate
mail delivery agent is determined for a particular message, an associated
rule set is applied.
Rewriting rules are organized into rule sets. A rule set is like a small
program consisting of an ordered sequence of rules. The program acts on
the address in the workspace, applying each rewriting rule as long as its
matching clause matches the address in the workspace. When it does not,
the next rule in sequence is tried. (This flow-of-control, such as it is,
can be modified very slightly, as explained below.) Viewed this way, a
rule set is a function acting on an address, yielding an address.
Rule sets are identified by number, each new rule set beginning with
an S followed by its identifying number. Each rule in the set follows.
Rules always begin with the letter R. The rule set is terminated when a
non-R command is encountered. For example:
S17
R$* < @ $=w > $: $1 < @ ourco.com >
------------- ----- ---------------------
| | |
lhs one or more rhs
tabs
Rewriting rules appear cryptic, but they are actually conceptually simple
(as well as being crypt ic!). A rule contains a ``left-hand side'' (lhs),
a ``right-hand side'' (rhs) and, optionally, a ``comment,'' separated from
each other by one or more tabs. Note that space characters (which can be
used to separate tokens for readbility) are not valid rule-part
separators.
When a rule is applied to the address in the workspace, the left-hand
side is compared to the address as a pattern. If the pattern matches, the
address in the workspace is replaced by the rule's right-hand side.
The pattern-matching proceeds simply. Ordinary words are matched literally.
Operators, which begin with a dollar sign ( $ ), have the following
meanings on the left-hand side:
$*
Match zero or more tokens
$+
Match one or more tokens
$-
Match exactly one token
$=
x
Match any phrase in class
x
$^
x
Match any word not in class
x
If an operato r matches part of the address in the workspace, then the
matched token(s) are assigned to the positional operator $ n ,
where n is 1 for the first match, 2 for the second such
match, and so forth. For example, applying the left-hand side $-
@ $* to fred@athena.mit.edu we have a match that assigns
``fred'' to $1 and ``athena.mit.edu'' to $2 .
When a left-hand side pattern match succeeds, the workspace is replaced
with the contents of the rule's right-hand side. Analogous to matching,
the replacement process copies literal tokens from the left-hand side to
the workspace and gives a special interpretation to operators. Some of
the recognized right-hand side operators include:
$
n
Substitute the
n
th matched
token from the lhs
$>
n
Call rule set
n
$#
mailer
Specify delivery agent,
mailer
$@
host
Specify
host
$:
user
Specify
user
$(
token
$)
Look up
token
in a database
Continuing with our example, if the workspace address is ``fred@athena.mit.edu''
and the current rule is:
R$-@$* phil@$2
then the workspace will be rewritten as ``phil@athena.mit.edu''.
The $> n symbol tells Sendmail to go to rule set n
after the current rewrite rule has been processed. This mechanism acts
like a subroutine facility. For example, it is sometimes necessary to make
sure an address is in the standard form Sendmail expects when applying
rewriting rules. This operation of ``canonicalization'' is done by rule
set 3. A rule to invoke rule set 3 looks like:
R$* $: $>3 $1
(The $: at the beginning of the right-hand side in this example is the
``one-time only'' prefix. (See below, too). It stops Sendmail from applying
the rule over and over, which it would do if not restrained. The left-hand
side-- $* --means ``match anything''.)
The mailer, host, and user specification symbols are used to resolve
envelope-recipient addresses. These constructs appear only in rule set
0 (or rule sets called by rule set 0), which uses rewrite rules to parse
and resolve recipient addresses. For example, after some involved application
of rule set 0, Sendmail will at last decide that an address is local and
resolve the host (this one), the user (the addressee) and the mailer (whatever
local mailer has been configured) with this rule:
R$+ $#local $: $1
In this example the address in the workspace, which consists of one or
more tokens ( $+ ), is the name of a local user ( $: $1 )
and should be delivered by the local mail delivery agent ( $#local
).
The complex token-lookup function ( $( ... $) ) permits substitution
of text in an address based on mapping files, that is, ndbm or db databases.
The argument to the lookup is always constructed from things that have
matched on the left-hand side. For example, if the left-hand side has parsed
a user name into $1 and a domain name into $2 , the token
lookup function on the right-hand side might translate a ``user@domain''
phrase into a replacement phrase by using $1@$2 as its argument.
If the mapping file consulted by the lookup function contains a map for
the argument, it is returned and replaces the entire lookup function as
the workspace is rewritten. See the major configuration example below for
a practical example.
In addition to the substitution operators, there are two other operators
that have special meanings when they appear as the first token on the right-hand
side. The $: operator instructs Sendmail to apply this rule only
once--even if it matches--to prevent i nfinite looping. Ordinarily, a rule
is applied repeatedly, until it fails to match. The $@ operator
directs Sendmail to exit from the rule set with the remainder of the right-hand
side as the rule set's result.
A Configuration Example
The first and most important step in developing a Sendmail configuration
is deciding upon a mail-handling strategy. For local networks of reasonable
size, a single mail hub system offers centralized administration, coherent
e-mail address structure and high levels of reliability, integrity and
performance. Even for networks consisting of as few as three or four systems,
a mail hub approach makes sense. (In fact, a network consisting of just
a single workstation can be viewed as a mail hub and client system rolled
into one.)
A Mail Hub Strategy
The mail hub we will configure processes all outgoing messages and acts
as the ``post office'' for mail coming in from outside the network. (I
t acts as a post office for local, intra-network mail as well.) Every user
who wants to receive mail has a mailbox on the mailhub machine. Enforcement
of acceptable use is centralized, as is technical administration of such
tasks as back up and mail system/DNS coordination. With a combination of
aliases and rewriting of sender addresses on outgoing mail at the hub,
all users in our example network have Internet e-mail addresses of the
form ``Firstname_Lastname@ourco.com''. Using ``guessable'' names is desirable
(though some disagree), especially in an environment where security or
privacy concerns may prohibit open directory services (for example, finger
). Using ``domain addressing'' (``ourco.com'' instead of ``zippy.research.ourco.com'')
not only hides internal domain structure, but it's simply more handsome.
These policies demand some administrative effort, but without a mail hub
the fragmented administrative effort required could be greater still.
Client syste ms (that is, the non-hub systems on the local network)
can be configured in a few different ways, each consistent with the overall
mail strategy. A ``smart'' client can run a Sendmail daemon that handles
idiosyncratic alias processing as well as dispatching mail to the hub.
A ``null'' client starts Sendmail locally on a per-message basis, using
it simply to pass each message to the Sendmail hub with no local processing.
Some hosts, such as those running Eudora on a Macintosh or Windows system,
rely on establishing a SMTP connection from the mail user agent (MUA) directly
to the mail hub, or use a POP (Post Office Protocol) (see
Reference 7) connection with a user's mailbox on the hub machine.
m4 and Sendmail
The m4 macro processor can be thought of as a translator from a simple
Sendmail configuration language to the opaque native configuration used
in its configuration file ( sendmail.cf ). An m4 configuration
file is rarely more than a few readable lines; the sendmail.cf file
created by m4 will often be several hundred cryptic lines.
The cf directory tree within the Berkeley Sendmail distribution
package contains the various Sendmail configuration macros spread among
a few descriptively named subdirectories. Macro files refer to one another
using relative path names ( `../m4/cf.m4' ). The integrity of
the interrelated m4 macros depends on the cf directory tree's
structure. Don't disturb it. You can put the cf tree anywhere
that's convenient (including leaving it right where you find it) so long
as you move all of it.
If you work with a Sendmail older than version 8.7, the m4 configuration
file you write (or adapt from prototypes and samples) should be kept in
the cf/cf directory. It will consist of a few concise calls to
various macros and symbol definitions that invoke and control the expansion
of large sequences of complex Sendmail configuration l anguage. Indeed,
the first line of an m4 Sendmail configuration file must be:
include(`../m4/cf.m4')
The cf.m4 macro file contains (or includes) all the definitions
of macros we might invoke in an m4 Sendmail configuration. We will touch
on a few of the important macros in the examples below.
Compiling a m4 Sendmail configuration is very simple. Just invoke m4
with the m4-format configuration file as its argument. The standard output,
which can be redirected to a disk file, will be the desired Sendmail-style
configuration file.
$
m4 mailhub.mc > mailhub.cf
After successful compilation, the ``.cf'' configuration can be tested using
the -C Sendmail option (that is, /usr/sbin/sendmail -C mailhub.cf
) and ultimately copied to to its final destination. If Sendmail is
running in daemon mode, kill and restart it to insure that Sendmail reads
its new configuration.
As of Sendmail version 8.7, you can place your configuration file anywhere
and use parameters on the m4 command line to specify a base include directory.
You can also omit the first include line, include(`../m4/cf.m4') ,
from the configuration file, specifying cf.m4 on the m4 command
line before your configuration file. For example, if you decide to keep
mailhub.mc somewhere other than cf/cf , you would compile
it with something like:
$
m4 -I /usr/src/sendmail/cf /usr/src/sendmail/cf/m4/cf.m4 \
mailhub.mc > mailhub.cf
A Mail Hub: Command Line and m4 Configuration
Daemon Mode . As a mail hub, Sendmail must be available to handle
incoming mail (via SMTP connections) at all times. Sendmail can be invoked
at system startup time (or any time) in ``daemon mode.''. It will listen
for and process all incoming SMTP connections, creating subprocesses as
necessary to complete the mail transfer work.
To sta rt Sendmail in daemon mode, lines like the following are placed
conventionally in a system's network or multiuser server startup script,
which is found in various places with various names depending on the Unix
implementation. Here's an example:
# Start the Sendmail daemon...
if [ -x /usr/sbin/sendmail ]; then
echo "Starting sendmail daemon..."
/usr/sbin/sendmail -bd -q 15m
fi
The -bd option specifies daemon-mode operation and -q 15m
directs Sendmail to attempt to send any queued messages every 15 minutes.
The mailhub.mc File . This configuration file for our mail hub
system (mailhub.ourco.com) is not too difficult to understand, yet it fully
specifies the behavior of our somewhat customized, powerful mail hub. Let's
examine it line-by-line:
include(`../m4/cf.m4')
VERSIONID(`mailhub.mc Richard Reich 11 AUG 95')
OSTYPE(linux)
FEATURE(nouucp)
FEATURE(use_cw_file)
MASQUERADE_AS(ourco.com)
MAILER(local
)
MAILER(smtp)
LOCAL_CONFIG
Kuserdb btree -o /etc/userdb.db
LOCAL_RULE_1
R$* < @ ourco.com. > $* $: $( userdb $1 $) < @ ourco.com. > $2
The first line ( include(`../m4/cf.m4') ...) causes m4 to read
and process cf.m4 , which defines the Sendmail macros and includes
a great deal of native Sendmail configuration language. The second line,
the VERSIONID macro, adds some useful version information as comments
in the output file ( mailhub.cf ).
The OSTYPE macro is really just a pretty kind of ``include''
statement. In our example this statement directs m4 to read and process
../ostype/linux.m4 . There is a wide selection of operating system
dependent macro files in the ostype subdirectory. In general,
these files include definitions that determine which local delivery agent
will be used and what oddities, if any, an OS may require with respect
to directory or file names. After deciding whether the distributed file
that corresponds to your operating system makes sense for your situation,
use it in every configuration file you write.
Here, FEATURE(nouucp) removes UUCP-related rewrite rules, and
so forth, from the resulting Sendmail configuration file.
Sendmail must know the names of all hosts or domains that may receive
mail on this system. Otherwise, Sendmail will assume the mail should be
routed to another destination system. The names can appear on certain command
lines in the configuration file, or they can be read from a separate file.
The FEATURE(use_cw_file) line instructs Sendmail to read the names
from the file /etc/sendmail.cw . If our host is the highest priority
mail exchanger for a domain name, that name should appear in /etc/sendmail.cw
. In our case, at least the domain name (ourco.com) must appear in
the ``.cw'' file if domain addressing is to function properly.
Here, MASQUERADE_AS(ourco.com) spec ifies the host pseudonym
to be used in sender fields of outgoing mail in place of the full domain
name of this host. This is the implementation of ``domain addressing.''
Mail sent from this host (mailhub.ourco.com), appears to be sent from ``ourco.com.''
So replies will be directed to sender @ourco.com.
The two MAILER macros define the types of mail delivery our
mailhub will require, local delivery and SMTP-based Internet delivery.
(Note that the actual local delivery agent used is often determined by
the contents of the macro file named by the OSTYPE macro. See
above.)
Rewriting Rules: A Very Simple Example
The last four lines of our mailhub configuration file have a potent impact
on sender addresses in outgoing mail:
LOCAL_CONFIG
Kuserdb btree -o /etc/userdb.db
LOCAL_RULE_1
R$* < @ ourco.com. > $* $: $( userdb $1 $) < @ ourco.com. > $2
A complete introduction to address rewriting is b eyond the scope of this
article, but this simple example may show that the subject is not completely
incomprehensible. The macros LOCAL_CONFIG and LOCAL_RULE_1
determine where in the resulting ``.cf'' file the lines that follow
them will end up. Raw Sendmail commands that are not rewriting rules usually
belong in the LOCAL_CONFIG section. The LOCAL_RULE_1 specifies
that the following rule should be placed in the section that processes
sender addresses (for example, the ``From:'' address). The other two lines
are ``raw'' Sendmail configuration language.
Sendmail configuration statements usually begin with a single upper
case letter that specifies a particular Sendmail command. In this case,
the ``K'' command directs Sendmail to open a keyed mapping file ( /etc/userdb.db
) for subsequent use.
Rewriting rules begin with the command letter ``R''. The rule in this
example means: if a sender address is of the form sen der
@ ourco.com anything-else , then look up the sender
name in the userdb-keyed file. And if the sender name is
found in the file, replace it with the address for that key.
For example, if the userdb file has this record in it:
richard Richard_Reich
then the actual local address ``richard@ourco.com'' in outgoing mail will
be rewritten as ``Richard_Reich@ourco.com''.
The mailhub.cf file that results from compiling mailhub.mc
with m4 is shown in this file . Note that
(according to wc ) mailhub.cf has more than ten times
as many words as mailhub.mc . This is a very rough measure of
relative complexity, but it is indicative of the advantage gained from
using the m4-based Sendmail configuration tools.
The last step: POP or NFS . The function of the mail hub is to
deliver all mail for the entire local network in to recipients' mailboxes
resident on the mail hub system. The last step is to get the mail to the
recipients.
One very popular solution consists of a Post Office Protocol (POP) Server
on the mail hub system, which retrieves mail when asked by a mail user
agent (for example, Eudora, Z-Mail). Some POP servers and clients can negotiate
the sending of outgoing mail as well.
Another common way to get users and their hub mailboxes together is
to allow client systems to mount the mailbox's directory via NFS (Network
File System). A mail user agent, via soft links or environment pointers,
sees its mailbox file as though it were local to its own system. Care must
be taken whenever NFS is used, however, to maintain user mailbox privacy
and system security.
Null Clients
A null client m4 configuration file consists of the macro FEATURE(nullclient)
and little or nothing else. It expands to a target ``.cf'' file that
causes this workstation's Sendmail to forward all mail for delivery to
a mail hub system. No additional processing takes place. Sendmail on null
clients is normally not run in daemon mode, nor does it maintain a mail
queue. Sendmail is initiated by a sending MUA for each piece of outgoing
mail, which it immediately sends on to the hub system. Of course, some
MUAs (like Netscape) do not start up instances of Sendmail--they make an
SMTP connection directly to the hub (or to a local smart client).
Where to get Sendmail, etc.
Sendmail is freely distributed. You may be able to find precompiled versions
for your Unix version. For instance, a Linux version is available via anonymous
FTP from Sunsite at University of North Carolina at Chapel Hill . However,
the authoritative source version is available via anonymous
FTP from U.C.Berkeley . It's usually little or no trouble to compile
and to get running.
Freely available m4 can be obtained from GNU's
anonymous FTP archive . The current version is 1.4, which does not
change frequently.
Freely available db code is available as a compressed-tar archive
via anonymous FTP from U.C.
Berkeley .
Where to Find Help
The Sendmail Usenet newsgroup is comp.mail.sendmail
. The discussions are lively and participants offer timely help to
those with problems. Eric Allman--the author of Sendmail--has frequently
contributed answers and announcements of new versions. (Eric, who has left
Berkeley for a new job, may not be able to commit as much time and energy
to Sendmail as he has in the past.)
References
-
Costales, Bryan with Eric Allman & Neil Rickert. Sendmail .
Sebastopol, CA.: O'Reilly & Associates, 1993. ISBN: 1-56592-056-2.
Huge (792 pages), but essential. O'Reilly's
descriptive page .
-
Avolio, Frederick M., and Paul A. Vixie. Sendmail: Theory and Practice
. Wobrun, MA.: Digital Press/Butterworth-Heinemann, 1995. ISBN: 1-55558-127-7.
An excellent guide to all aspects of Sendmail, marred slightly by its focus
on the pre-V8 version. Vixie
Enterprises' descriptive page .
-
Allman, Eric. ``SENDMAIL Installation and Operation Guide'' from 4.4BSD
System Manager's Manual . Berkeley, CA.: The USENIX Association and
Sebastopol, CA.: O'Reilly & Associates, 1994. Also, online as 128K
gziped-PostScript file . The most recent, definitive version is included
in the U.C. Berkeley Sendmail distribution (as doc/op/op.ps )
The latest details, amazingly concise, but not the easiest to follow.
-
Hedrick, Charles. ``Subject: a brief tutorial on sendmail rules''. An e-mail
note written by Charles Hedrick to explain rewriting rules. A genuine Internet
classic, though now dated, a gem of brevity and clarity. Available as a
16K text file .
-
Postel, J. ``Simple Mail Transfer Protocol''. RFC
821 (117K text file) , 1982.
-
Crocker, D. ``Standard for the format of ARPA Internet text messages''.
RFC 822 (103K text file)
. 1982.
-
Reynolds, J. K. ``Post Office Protocol''. RFC
918 (10K text file) . 1984.
|