Cover V02, I02
Article
Figure 1
Figure 2
Table 1
Table 2
Table 3
Table 4

mar93.tar


Mail and Sendmail Administration: Part 2

Bruce H. Hunter

Part 1 of this article (January/February 1993) described mail and introduced sendmail; in Part 2, I begin with a review of mail routing through sendmail and then go deeper.

Mail is collected and delivered by a mail agent, classically, but not necessarily, the mail command. It is processed for delivery by a routing agent, most frequently sendmail. Unless it is for local delivery it is then passed on to a delivery agent, typically 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 the routing agent has to do -- let alone the protocols the delivery agent uses.

In the Ethernet-TCP/IP protocol stacks, mail travels just like other traffic at the physical, link, and network layers. At the transport 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 in /etc/services?

telnet    23/tcp
smtp      25/tcp     mail
time      37/tcp     timserver

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 the sendmail command to work as a daemon. In the system's run-command file(s) you will find lines like

if [ -f /usr/lib/sendmail -a -f /etc/sendmail.cf]; then
/usr/lib/sendmail -bd -q1h; echo -n ' sendmail

which tests for the presence of the sendmail command and the sendmail.cf configuration file. If they are present, the command file starts sendmail with the appropriate flags 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.

How the sendmail.cf File Works

In the broadest view the sendmail.cf file

  • defines the mail environment

  • rewrites addresses to be accepted by other mailers

  • performs address-to-instruction mapping.

    All vendors ship their systems with sendmail.cf, typically including -- at a minimum -- both TCP/IP and UUCP. This is overkill, since most sites need one or the other but not both. More streamlined versions of sendmail.cf, available by anonymous ftp from ftp.uu.net, include

  • tcpproto.cf

  • uucpproto.cf

  • tcpuucpproto.cf

    The standard distribution typically provides two .cf files: one, subsidiary.cf, is intended for use with all systems; the other, main.cf, is used by the mail master system.

    sendmail.cf, like so many UNIX configuration files, is divided into sections. The first section, general macros, begins with

    defines 	D
    classes 	C

    The definitions are for such things as domain aliases, hostname, relay mailer and host, and DNS.

    These are followed by:

    classes
    version number
    special macros
    options
    message precedence
    trusted users
    header formats
    rewriting rules
    mailers
    rulesets
    mail routing

    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 best example being the hostname.

    Configuring sendmail.cf

    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, is another story -- you'll find that most sendmail.cf files are heavily commented.

    For speed in reading configuration files, you can use a compiled version, called a frozen configuration file. Unlike the .cf files this is not an ASCII file.

    31% su
    Password:
    # 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 configuration file exists and you change sendmail.cf, the change will not 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 .cf 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. White spaces 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:

    Dq$g$?x ($x)$.

    This is the total name format and it is standard in host .cf files. Here q defines (in terms of [g]) the sender address. It says if x (the sender name) is set, use it. The syntax is:

    $xSTR_1 $| SRT_2$.
    if ($?) x set
    use STR_1
    else ($|) use STR_2
    endif ($.)

    Format for Lines

    Each line to be acted on (in the first part of the file) starts with an uppercase letter that denotes the type of action (Table 1 shows the values available for this position, along with the action or entity they denote).

    Following this single letter is the macro name, also a single letter. The macros defined regularly by sendmail are in lowercase; 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 definitions anywhere in the .cf file. These macros are internal to sendmail; Table 3 presents a partial list of sendmail's internal macros.

    Header Format Conditionals

    More than half of a short mail message will consist of header information, which suggests how important headers are to sendmail. As a result, sendmail.cf spends a lot of its space defining headers. 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 the sender's name as it appears in the passwd comment field.

    Dq$g$?x ($x)$.

    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 field, 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: bhunter@mfg.acme.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 for the rules and rulesets. This section is where the addresses are reordered into a consistent internal format and readied for delivery. A ruleset 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 ruleset 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 address form. Ruleset 0 is the message delivery ruleset. It is applied only after ruleset 3 and only to the recipient address. Figure 2 shows a flow diagram of how the rules are read.

    Internal Names, Canonical Form, and "Focus"

    Internal names are represented in user@domain format. sendmail uses a pair of operators -- the < and the > -- to focus on a particular part of the address. Here in internal canonical form with focus are several addresses as they would be translated by sendmail:

    smith@<apex.uucp>
    smith@<apex.dnet>
    smith@<apex.ibm>

    This canonical form is required by ruleset 0 for message delivery.

    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 side, tab, left-hand side, tab, comment; the functions are as follows:

    left-hand side (lhs)	pattern matched
    right-hand side		rewrite pattern (if match found)
    comment

    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 ".".

    For example,

    $-@$+

    matches bhunter@stalker, bhunter@stalker.acme.com, bhunter@stalker.mfg.acme.com while

    $-@$-

    matches only bhunter@stalker. The right-hand side metasymbols are

    $1 match of the first metasymbol
    $2 match of the second metasymbol
    $3 match of the third metasymbol

    Exact tokens match exact tokens. So for $-@$+ on bhunter@stalker.acme.com:

    $1 	bhunter
    $2	stalker.acme.com
    @@ 	@

    Address Transformations

    The address transformation metasymbols are:

    $N substitute indefinite token N
    $[string$] substitute canonical string
    $>N call ruleset N
    $@ terminate ruleset
    $: terminate rewrite rule

    For example, applying focus, the address

    bhunter@jaeger

    must transform to

    bhunter@<jaeger>

    so the rewrite rule is

    R$+<$+>

    In the transformation

    $1@$2<.$B>

    where $B is defined as acme.com, the address alone will transform from

    bhunter@jaeger

    to

    bhunter@jaeger.acme.com

    the rule is written

    R$+<@.$+>	$1@$2<.$B>

    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 book on the subject is O'Reilly's Administering TCP/IP, by Craig Hunt. The most complete coverage I have ever seen is a seminar called "Sendmail Made Easy" by Robert Harker. For information, contact harker@harker.com.

    About the Author

    Bruce H. Hunter is the co-author, with Karen Hunter, of UNIX Systems Advanced Administration and Management Handbook (Macmillan: 1991).


     



  •