Bruce H. Hunter
Part 1 of this article (January/February 1993) described
and introduced sendmail; in Part 2, I begin with a review
mail routing through sendmail and then go deeper.
Mail is collected and delivered by a mail agent, classically,
not necessarily, the mail command. It is processed for
by a routing agent, most frequently sendmail. Unless
for local delivery it is then passed on to a delivery
the Internet or UUCP (see Figure 1). To complete the
cycle, the delivery
agent then passes mail to the routing agent, which passes
it to a
mail agent. Simple? Not really, not when you see what
agent has to do -- let alone the protocols the delivery
In the Ethernet-TCP/IP protocol stacks, mail travels
just like other
traffic at the physical, link, and network layers. At
layer, however, it must rely on SMTP and must be able
to find its
own special port, TCP port 25. Have you seen these lines
sendmail listens (via socket) to that port for
incoming mail and sends mail via the same port.
Mail delivery by way of the routing agent relies on
command to work as a daemon. In the system's run-command
you will find lines like
which tests for the presence of the sendmail command
and the sendmail.cf configuration file. If they are
the command file starts sendmail with the appropriate
to run as a daemon. It also sets the queuing time. sendmail
then uses its configuration file to define how it is
to deliver mail.tcpuucpproto.cf
The standard distribution typically provides two .cf
one, subsidiary.cf, is intended for use with all systems;
other, main.cf, is used by the mail master system.
sendmail.cf, like so many UNIX configuration files,
into sections. The first section, general macros, begins
The definitions are for such things as domain aliases,
hostname, relay mailer and host, and DNS.
These are followed by:
The system administrator usually has only to provide
definitions for a few things like the domain name. sendmail
internal macros automatically provide the others, the
being the hostname.
The sendmail configuration file for nodes is always
the smaller and
simpler of the two configuration files: its only job
is to get the
mail routed to the mail master. The mail master, however,
story -- you'll find that most sendmail.cf files are
For speed in reading configuration files, you can use
a compiled version,
called a frozen configuration file. Unlike the .cf files
is not an ASCII file.
# file send*
sendmail.cf: ASCII text
sendmail.cf.orig: ASCII text
sendmail.cf.save: ASCII text
While the compiled version does read faster, it cannot
be changed without recompilation. Worse yet, if a frozen
file exists and you change sendmail.cf, the change will
take effect until you recompile. This has left many
a frustrated system
administrator wondering why his/her changes won't take.
To understand sendmail.cf, you have to understand that
lines are formatted for easy machine parsing rather
than for reading
by people. White space is used only where it is part
of a string and
is therefore significant only to the macros being set.
play no role in the parsing of macro tokens.
The following example of a conditional shows just how
ugly the lines
of this file can look:
This is the total name format and it is standard in
.cf files. Here q defines (in terms of [g]) the
sender address. It says if x (the sender name) is set,
it. The syntax is:
$xSTR_1 $| SRT_2$.
if ($?) x set
else ($|) use STR_2
Format for Lines
Each line to be acted on (in the first part of the file)
an uppercase letter that denotes the type of action
(Table 1 shows
the values available for this position, along with the
action or entity
Following this single letter is the macro name, also
letter. The macros defined regularly by sendmail are
those created by the system administrator are local
and are in uppercase
by convention. Table 2 shows sendmail's essential macros.
Confusion can arise when you can't find certain macro
anywhere in the .cf file. These macros are internal
Table 3 presents a partial list of sendmail's internal
Header Format Conditionals
More than half of a short mail message will consist
of header information,
which suggests how important headers are to sendmail.
result, sendmail.cf spends a lot of its space defining
Here is a header format conditional's format:
$?x $x $
An example would be the definition of a complete name
for the default sender name format, which must include
name as it appears in the passwd comment field.
This defines q (the default sender name format)
as the sender address ($g) plus the sendmail internal
macro ($x), which is the user name taken from the GECOS
and essentially sets q to g if g is already set.
The header line that follows shows an application of
$g $x, sender
address (sender name).
From: email@example.com (Bruce H Hunter ~)
The last $. is the end of the conditional.
Rules and Rulesets
The first sections of the configuration file are a warmup
rules and rulesets. This section is where the addresses
into a consistent internal format and readied for delivery.
is defined by the mnemonic S. There can be 20 or 30
rules but 0
- 4 are the most critical. These are:
S0 message delivery ruleset
S1 sender ruleset
S2 recipient ruleset
S3 preamble ruleset
S4 final output ruleset
All messages must pass ruleset 3. This is the first
the addresses ever see. Sender addresses pass ruleset
1 while recipient
addresses must pass through ruleset 2. Both output to
ruleset 4, which
is used to translate from internal address form to external
form. Ruleset 0 is the message delivery ruleset. It
is applied only
after ruleset 3 and only to the recipient address. Figure
a flow diagram of how the rules are read.
Internal Names, Canonical Form, and "Focus"
Internal names are represented in user@domain format.
uses a pair of operators -- the < and the > --
to focus on a particular part of the address. Here in
form with focus are several addresses as they would
This canonical form is required by ruleset 0 for message
Address Rewrite Rules
The address rewrite rule section uses white space that
is not a part
of the string needed by the macro. The form is right-hand
left-hand side, tab, comment; the functions are as follows:
left-hand side (lhs) pattern matched
right-hand side rewrite pattern (if match found)
Table 4 shows the token matching symbols used in the
left-hand side. These symbols are never used to match
an exact token
such as "@" or ".".
matches bhunter@stalker, firstname.lastname@example.org,
matches only bhunter@stalker. The right-hand side
||match of the first metasymbol
||match of the second metasymbol
||match of the third metasymbol
Exact tokens match exact tokens. So for $-@$+ on email@example.com:
The address transformation metasymbols are:
|| substitute indefinite token N
|| substitute canonical string
|| call ruleset N
|| terminate ruleset
|| terminate rewrite rule
For example, applying focus, the address
must transform to
so the rewrite rule is
In the transformation
where $B is defined as acme.com, the address
alone will transform from
the rule is written
to use Acme's full Internet address.
Getting More Help
sendmail configuration is complex and debugging sendmail
is an art (although the tools are provided). An excellent
the subject is O'Reilly's Administering TCP/IP, by Craig
The most complete coverage I have ever seen is a seminar
Made Easy" by Robert Harker. For information, contact
About the Author
Bruce H. Hunter is the co-author, with Karen Hunter,
of UNIX Systems
Advanced Administration and Management Handbook (Macmillan: