Chapter 14. Signals, Transactions, and Syslog

The sendmail program can keep the system administrator up-to-date about many aspects of mail delivery and forwarding. It does this by logging its activities using the syslog(3) facility. Information about things such as total message volume and site connectivity can help the administrator make sendmail more efficient. Information about the SMTP dialog that was used to send the message can help the administrator solve delivery problems.

In this chapter, we cover three important aspects of sendmail. First, we explain how signals interact with sendmail and show how signals can be used to cause sendmail to log additional information. Second, we show how to use the -X command-line switch to cause sendmail to record its SMTP transactions. Finally, we explain the use of the syslog(3) facility, illustrate several ways to tune its output, and describe the meaning of that output.

Signal the Daemon

The sendmail program recognizes three signals that cause it to perform certain actions. SIGINT and SIGTERM cause sendmail to clean up after itself and exit. Beginning with V8.7, SIGHUP causes sendmail to re-execute itself (thus restarting and reading its configuration file anew). Also beginning with V8.7, SIGUSR1 causes sendmail to log its file descriptors and other information.

SIGTERM

Cleanup and exit sendmail signal

Whenever sendmail gets a SIGTERM signal (as would be the case if the system were being shut down), it tries to exit cleanly.

First, it unlocks any queued file it is processing. This has the effect of canceling delivery so that the message will be tried again when the system comes back up. Then sendmail resets its identity to the identity it originally ran under. This causes accounting records to correctly show that the same user sendmail started as has exited. Finally, sendmail exits with EX_OK, no matter what, so that errors will not be produced during shutdown.

SIGINT

Handle Ctrl-C sendmail signal

Before V8.7, when sendmail was run in rule-testing mode with -bt, it could be killed with a Ctrl-C (SIGINT). Beginning with V8.7, SIGINT is handled specially. This allows you to resume testing whenever something such as a bad DNS lookup takes excessively long to complete.

SIGKILL

Don’t kill forcefully sendmail signal

You should never kill sendmail with a SIGKILL (a kill −9). If you do, mail can be lost, or re-sent despite successful delivery. Instead, use SIGTERM to stop sendmail.

SIGHUP

Tell sendmail to restart sendmail signal

Beginning with V8.7, a SIGHUP signal will cause sendmail to re-execute itself with its original command line. This works only if it is running in daemon mode (with -bd, -bd on page 234). For example, consider initially running sendmail like this:

# /usr/sbin/sendmail -bd -q1h

Then imagine that you changed something in the configuration file and wanted the running daemon to reread that file. You could cause that to happen by killing the currently running daemon with a SIGHUP signal:

# kill -HUP `head −1 /etc/mail/sendmail.pid`

This will cause sendmail to execute the command:

/usr/sbin/sendmail -bd -q1h

The original daemon exits, and the newly executed daemon replaces it.

Be aware that this works only if you run sendmail using a full pathname. If you use a relative path, an attempt to restart sendmail with SIGHUP will fail, and the following warning will be logged at LOG_ALERT:

could not exec bad command line here: reason

This is a very serious situation because it means that your original daemon has exited and no new daemon ran to replace it.

SIGUSR1

Tell sendmail to dump its states sendmail signal

Beginning with V8.6.5, sendmail responds to a SIGUSR1 signal. This signal causes sendmail to syslog at LOG_DEBUG the several items that define its state.[220] That syslog output begins with a line that looks like this:

--- dumping state on reason: $j = val ---

where reason can be any one of the following:

user signal

The information has been logged because sendmail received a SIGUSR1 signal. In this instance, the daemon logs the information and continues to run.

daemon lost $j

The information has been logged because a running daemon discovered that the value in $j (the canonical name of this host, $j on page 830) disappeared from the class $=w (the list of all names by which the local host is known, $=w on page 876). This test is made and this information is logged only if sendmail was compiled with XDEBUG defined (XDEBUG on page 152). In this instance, the daemon logs the information and aborts.

daemon $j lost dot

The information has been logged because a running daemon discovered that the value in $j (the canonical name of this host, $j on page 830) was no longer canonical (no longer contained a dot inside it). This test is made and this information is logged only if sendmail was compiled with XDEBUG defined (XDEBUG on page 152). In this instance, the daemon logs the information and aborts.

Whichever the reason, the information that is logged for each looks pretty much the same; for example:

--- dumping state on reason: $j = val ---
CurChildren =num
NextMacroId = nextid (Max maxid)
--- open file descriptors: ---
                ← output of dumpfd(  ) here
--- connection cache: ---
                ← output of mci_dump( ) here
--- ruleset debug_dumpstate returns stat ret, pv: ---output of rule set debug_dumpstate here
--- end of state dump ---

We have described the first line already. If, for some reason, $j is missing from $=w, that line will be followed by:

*** $j not in $=w ***

The second line simply shows the number of children the daemon has forked and currently has out doing other work in parallel with itself. The third line shows the next available value that can be assigned to a multicharacter sendmail macro (nextid) and the maximum of such numbers available (maxid). That line is followed by three sections of information. The first two sections are always output; the third is output only if rule set debug_dumpstate (--- ruleset debug_dumpstate returns stat ..., pv: --- on page 511) exists.

--- open file descriptors: ---

Each open file descriptor is displayed along with its current properties. These lines of output can be numerous. In general form, they look like this:

num: fl=flags mode=mode type stats

Here, the num is the number of the open file descriptor. The other information in this line is described in detail in our discussion of the -d2.9 debugging switch (-d2.9 on page 546).

--- connection cache: ---

When sending mail, outgoing connections are maintained for efficiency, and information about those connections is cached. Before connecting to a remote host, for example, sendmail checks its cache to see whether that host is down. If it is, it skips connecting to that host.

This output is highly detailed and very complicated. See the -d11.1 debugging switch (-d11.1 on page 550) for a full description.

--- ruleset debug_dumpstate returns stat ..., pv: ---

If the debug_dumpstate rule set[221] is defined in your configuration file, it will be called here, and the previous line of output will be printed. The stat is the numeric representation of the code returned by sendmail’s internal rewrite( ) routine. That code will be either EX_OK (0) if there were no parsing errors, EX_CONFIG (78) if there were, or EX_DATAERR (65) if there was a fatal error (such as too much recursion, or if a replacement was out of bounds). Text describing the error is also logged and will appear in this output.

Rule set debug_dumpstate is called with an empty workspace. After the debug_dumpstate rule set is done, each token in the resulting new workspace is printed, one per line. This gives you a hook into the internals of sendmail, enabling you to display information that might otherwise be invisible. For example, consider the desire to display identd information, the current sender’s address, and the current queue identifier:

Sdebug_dumpstate
R$*     $@ $&_ $&s $&i

Here, the $* in the LHS matches the zero tokens passed to the debug_dumpstate rule set. The $@ prefix in the RHS suppresses recursion. Each of the three sendmail macros that follows is stated with a $& prefix (Use Value As Is with $& on page 793) that prevents each from being prematurely expanded when the configuration file is first read.

Another example might involve the need to look up the current recipient’s host with DNS:

Sdebug_dumpstate
R$*     $@ $[ $&h $]

The $[ and $] operators (Canonicalize Hostname: $[ and $] on page 668) cause the hostname appearing between them to be looked up with DNS and replaced with its full canonical name. Again, the macro h is prefixed with $& to prevent premature expansion.

In general, the debug_dumpstate rule set should be excluded from your configuration file. When a problem does appear, you can define it, restart the daemon, and then wait for the problem to reoccur. When it does, kill sendmail with a SIGUSR1 and examine the syslog result.

Do not be tempted to use the debug_dumpstate rule set for routine logging of specialty information. Forcing rules to be processed with a signal is fraught with danger. The current active rule set can, for example, be clobbered in possibly unrecoverable ways. Use this debug_dumpstate rule set technique only to solve specific problems, and then erase it when the problem is solved.

Log Transactions with -X

Beginning with V8.2 sendmail, the -X command-line switch can be used to record all input and output, SMTP traffic, and other significant transactions. The form of the -X (transaction) command-line switch looks like this:

-X file

Space between the -X and the file is optional. The file can be specified as either a full or a relative pathname. For security, the -X command-line switch always causes sendmail to give up its privileges unless it was run by root. If the transaction file cannot be opened for writing, the following error is printed and no logging is done:

cannot open file

Otherwise, the file is opened in append mode, and each line that is written to it looks like this:

pid what detail

The pid is the process identification number of the sendmail that added the line. The what is one of these three symbols:

<<<

This is input. It is either text that is read on the standard input, or parts of an SMTP dialog that were read on a socket connection.

>>>

This is output. It is either something that sendmail printed to its standard output, or something that it sent over an SMTP connection.

= = =

This is an event. The only two events that are currently logged are CONNECT for connection to a host and EXEC for execution of a delivery agent.

To illustrate, consider sending a mail message to yourself and to a friend at another site:

% /usr/sbin/sendmail -X /tmp/xfile -oQ`pwd` yourself,friend@remote.host

To: yourself,friend@remote.host
Subject: test

This is a test.
.

These few lines of input produce a long /tmp/xfile. The first few lines of that file are illustrative:

29559 <<< To: yourself,friend@remote.host
29559 <<< Subject: test
29559 <<<
29559 <<< This is a test.
29559 <<< .
29561 =  == CONNECT remote.host
29561 <<< 220 remote.host ESMTP Sendmail 8.9.3; Fri, 13 Dec 2002 08:06:47 −0600 (MDT)
29561 >>> EHLO your.host
29561 <<< 250-remote.host Hello you@your.host [206.54.76.122], pleased to meet you
29561 <<< 250-8BITMIME
29561 <<< 250-SIZE
29561 <<< 250-DSN
29561 <<< 250-VERB
29561 <<< 250-ONEX
29561 <<< 250 HELP
29561 >>> MAIL From:<your@your.host> SIZE=65
29561 <<< 250 <your@your.host>... Sender ok
29561 >>> RCPT To:<friend@remote.host>
29561 <<< 250 Recipient ok
29561 >>> DATA
29561 <<< 354 Enter mail, end with "." on a line by itself
29561 >>> The first line of data here,
29561 >>> the second line of data here,
29561 >>> and so on.

Notice that the process ID changes. After sendmail collects the message, it performs a fork(2) and exec(2) to handle the actual delivery.

Because these transaction files include message bodies, they should be guarded. Never use the -X switch with the daemon unless you are prepared for a huge file and the possibility of disclosing message contents to nonprivileged users.

Log with syslog

Logging is the process of issuing one-line messages or warnings that will be either displayed to a human, archived to a file, or both. The mechanism that sendmail uses to produce these logging lines is called syslog(3). The sendmail program is concerned only with issuing its messages and warnings. Once they are issued, the syslog facility takes over and disposes of them in a manner described in the file /etc/syslog.conf. Statements in this file determine whether a logged line is written to a device (such as /dev/console) appended to a file, forwarded to another host, or displayed on a logged-in user’s screen.

In the following discussion of syslog and syslog.conf, we will describe the BSD 4.4 version. Some versions of Unix, such as Ultrix, use the 4.2 version of syslog, but because syslog is public domain, we recommend you upgrade and will not cover that old version here.

syslog(3)

The syslog(3) facility uses two items of information to determine how to handle messages: facility and level. The facility is the category of program issuing a message. The syslog facility can handle many categories, but only one, mail, is used by sendmail. The level is the degree of severity of the warnings. The sendmail program issues messages with syslog(3) at various levels depending on how serious the message or warning is.

When sendmail first starts to run, it opens its connection to the syslog facility with the following C-language line:

openlog("sendmail", LOG_PID, LOG_MAIL);       ← prior to V8.10
openlog(SM_LOG_STR, LOG_PID, LOG_MAIL);       ← V8.10 and later

This tells syslog three things:

  • Unless told otherwise with the -L command-line switch (-L on page 243), all messages should be printed using sendmail as the name of the program doing the logging. This means that regardless of what name is used to run sendmail (such as newaliases or smtpd), the name that is logged will always be either sendmail or a name you specify. To specify a different name, with V8.10 or above, just define the SM_LOG_STR compile-time macro when building sendmail:

    define(`SM_LOG_STR', `smtpd')
  • The LOG_PID tells syslog that the PID (process identification number) should be included when each message is written. This is necessary because sendmail forks often, and each parent and child will have a different PID. Because queue file identifiers are constructed from PIDs, this record helps to determine which invocation of sendmail created a particular queued file. The PID also allows messages from the daemon form of sendmail to be differentiated from others.

  • The facility for sendmail (and all mail-handling programs) is LOG_MAIL. We’ll show why this is important when we discuss the syslog.conf file.

Just before sendmail issues a warning, it looks at the logging level defined by its LogLevel option (LogLevel on page 1040). If the severity of the message or warning is greater than the logging level, nothing is output. If the severity is less than or equal to the logging level, sendmail issues that warning with a C-language call like this:

syslog(pri, msg);

Here, pri is the syslog logging priority, and msg is the text of the message or warning. Note that the LogLevel option (LogLevel on page 1040) level is different from the syslog priority. The former is used internally by sendmail to decide whether it should log a message. The latter is used by syslog to determine how it will dispose of the message.

The LogLevel option sets a threshold at and below which sendmail will issue warnings. When the LogLevel option has a zero value, essentially nothing is ever issued. When the LogLevel option has a low value, only critical warnings are issued. At higher values, less critical messages are also logged.

The syntax of the LogLevel option and the kinds of information issued for each level are explained in LogLevel on page 1040. For each level, all the information produced at lower levels is also issued. That is, setting the LogLevel option to 9 causes messages for levels 1 through 8 also to be issued.

The relationship between the LogLevel option logging levels and syslog priorities is shown in Table 14-1. Note this relationship is not strictly adhered to by sendmail.

Table 14-1. L Levels versus syslog priorities

Level

Priority

1

LOG_CRIT and LOG_ALERT

2–8

LOG_NOTICE

9–10

LOG_INFO

11+

LOG_DEBUG

Tuning syslog.conf

Although all messages are emitted by sendmail using a single facility, that of syslog, they need not all arrive at the same place. The disposition of messages is tuned by the syslog.conf file.

The file syslog.conf (usually located in the /etc directory) contains routing commands for use by syslog. That file can be complex because it is designed to handle messages from many programs other than sendmail, even messages from the kernel itself. Under SunOS, the syslog.conf file is also complex because it is preprocessed by m4(1) when it is read by syslog.

The file syslog.conf is composed of lines of text that each have the form:

facility.level           target

The facility is the type of program that may be producing the message. The facility called mail is the one that sendmail uses. For the complete list, see the online manual for syslog.conf(5).

The level indicates the severity at or above which messages should be handled. These levels correspond to the LogLevel option levels shown in Table 14-1 on page 515. The complete list of syslog.conf levels used by sendmail is shown in Table 14-2.

Table 14-2. syslog.conf levels used by sendmail

Level

Meaning of severity (highest to lowest)

alert

Conditions requiring immediate correction

crit

Critical conditions for which action can be deferred for a brief while

err

Other errors

warning

Warning messages

notice

Nonerrors that might require special handling

info

Statistical and informational messages

debug

Messages used only in debugging a program

The target is one of the four possibilities shown in Table 14-3. The target and the preceding level must be tuned for use by sendmail.

Table 14-3. syslog.conf targets

Target

Description

@host

Forward message to named host.

/file

Append message to named file.

user,user,...

Write to users’ screens, if logged in.

*

Write to all logged-in users’ screens.

For example, the following syslog.conf line causes messages from “mail” (the facility) that are at or above severity “info” (the level) to be appended to the file /var/log/syslog (the target):

facility                  target
 ↓                       ↓
mail.info               /var/log/syslog
      ↑     level

A typical (albeit much simplified) /etc/syslog.conf file might look like this:

*.err;kern.debug;user.none          /dev/console
*.err;kern.debug;user.none          /var/adm/messages
auth.notice                         @authhost
mail.info                           /var/log/syslog
*.alert;user.none                   *

Notice that there can be multiple facility.level pairs on the left, each separated from the others by semicolons. The first two lines handle messages for all facilities at level err, all kernel messages (kern) at level debug and above, and none of the levels (none) for the facility user. The first line sends those messages to the file /dev/console, the computer’s screen. The second appends its messages to the file /var/adm/messages.

The third line sends authorization messages (such as repeated login failures) to the host named authhost.

The fourth line appends all messages printed by sendmail at level info and above to the file /var/log/syslog.

The last line is an alert broadcast facility. A message to any facility (the leftmost *) at the highest level (alert), except for the facility user (the .none), will be written to the screen of all currently logged-in users (the target *).

Finally, note that facilities can be listed together by using a comma:

mail,daemon.info

This causes the level info to be the level for both the facilities mail and daemon. Only the facility can be listed this way. The level cannot, and (unfortunately) the target cannot.

syslog’s Output

When the LogLevel option level is 9 or above (LogLevel on page 1040), sendmail logs one line of information for each envelope sender and one line of information for each recipient delivery or deferral. As sendmail has evolved, these lines of logging information have grown more complex. Here, we discuss the lines produced by sendmail 8.12.

Each line of information logged looks something like this:

date host sendmail[pid]: qid: what=value, ...

Each line of output that syslog produces begins with five pieces of information. The date is the month, day, and time that the line of information was logged.[222] The host is the name of the host that produced this information (note that this can differ from the name of the host on which the logfiles are kept).[223] The sendmail (or whatever you specified with the -L command-line switch) is literal. Because of the LOG_PID argument that is given to openlog(3) by sendmail (syslog(3) on page 514), the PID of the invocation of sendmail that produced this information is included in square brackets. Finally, each line includes the qid queue identifier (The Queue Identifier on page 396) that uniquely identifies each message on a given host.

This initial information is followed by a comma-separated list of what=value equates. Which syslog equate appears in which line depends on whether the line documents the sender or the recipient and whether delivery succeeded, failed, or was deferred.

Table 14-4, we list the possibilities in alphabetical order. Then, in the sections at the end of this chapter, we describe the role that each plays.

Table 14-4. what= in syslog output lines

what=

§

Description

action=

action= on page 521

The Milter’s phase

arg1=

arg1= on page 521

The argument to a check_ rule set

bodytype=

bodytype= on page 521

The body type of the message

class=

class= on page 522

Precedence: header’s value

ctladdr=

ctladdr= on page 522

The controlling user

daemon=

daemon= on page 522

The name of the sender’s daemon

delay=

delay= on page 522

Total time to deliver

dsn=

dsn= on page 523

Show DSN status code

from=

from= on page 523

The envelope sender

intvl=

intvl= on page 523

The illegal interval to schedule

len=

len= on page 524

The length of a too-long header value

mailer=

mailer= on page 524

The delivery agent used

milter=

milter= on page 524

The name of the Milter

msgid=

msgid= on page 525

The Message-ID: header identifier

nrcpts=

nrcpts= on page 525

The number of recipients

ntries=

ntries= on page 525

The number of delivery attempts

pri=

pri= on page 526

The initial priority

proto=

proto= on page 526

The protocol used in transmission

quarantine=

quarantine= on page 526

Why a message was quarantined (V8.13 and later)

reject=

reject= on page 526

The reason a message was rejected

relay=

relay= on page 527

The host that sent or accepted the message

ruleset=

ruleset= on page 527

The check_ rule set

size=

size= on page 527

The size of the message

stat=

stat= on page 528

The status of delivery

to=

to= on page 528

The final recipient

xdelay=

xdelay= on page 528

Transaction delay for this address only

Note that this table is not comprehensive. There are many more syslog equates used in sendmail’s logging output, and those equates can document everything from authentication failure to spam rejection notices. We explain those specialty log lines and equates in their respective sections of this book. In this chapter, we restrict our coverage to those equates common to everyday mail delivery.

Gathering Statistics from syslog

The logfiles that syslog creates provide a wealth of information that can be used to examine and tune the performance of sendmail. To illustrate, we will present a simple shell script for printing daily total message volume.

In the following discussion, we will assume that sendmail logging is enabled (the LogLevel option, LogLevel on page 1040, is nonzero) and that all syslog(8) messages for the facility mail at level LOG_INFO are being placed into the file /var/log/syslog.

message_volume.sh

Each mail message that sendmail receives for delivery (excluding those processed from the queue) causes sendmail to log a message such as this:

date host sendmail[pid]: quid: from=sender, size=bytes, ...

That is, for each sender that is logged (the from=), sendmail also logs the total received size of the message in bytes (the size=).

By summing all the size= lines in a /var/log/syslog file, we can generate the total volume of all messages received for the period represented by that file. One way to generate such a total is shown in the following Bourne shell script:

#!/bin/sh
LOG=/var/log/syslog
TOTAL=`(echo 0;
        sed -e '/size=/!d' -e 's/.*size=//' -e 's/,.*/+/' $LOG;
        echo p;
       ) | dc`
echo Total characters sent: $TOTAL

The sed(1) selects only the lines in /var/log/syslog that contain the expression size=.[224] It then throws away all but the number immediately following each size= (the actual number of bytes of each message), and appends a + to each.

The entire sequence of processes is enclosed in parentheses. An echo statement first prints a zero. Then the list of +-suffixed sizes is printed. Finally, another echo prints a character p. The resulting combined output might look like this:

0
123+
456+
7890+
p

The leading 0, the + suffixes, and the final p are commands for the dc(1) program, which adds up all the numbers (the + suffixes) and prints the total (the p). That total is saved in the variable TOTAL for later use in the final echo statement. The output of this simple script might look something like this:

Total characters sent: 8469

More sophisticated scripts are possible, but the Bourne shell’s lack of arrays suggests that perl(1) would provide a more powerful scripting environment. Most of the scripts that are available publicly are written in the perl scripting language.

Pitfalls

  • The syslog(3) library uses datagram sockets for passing information to other hosts. As a consequence, there is no guarantee that all logged information will be received by those other hosts.

  • When using m4, exercise care to avoid using m4 keywords in unexpected places. For example, attempting to notify a user named dnl in the syslog.conf file causes that name and all the text following on the same line to be lost.

  • Care should be exercised in using the -X switch as root. No check is made to ensure that the transaction logging file makes sense. It is possible to make a typo and accidentally append transaction data to the wrong file or device.

  • Not all information is available in syslog(3) output. Some information, such as the number of invocations of sendmail at any given time, is available only via process listing or accounting programs.

  • Note that syslog will not work properly on Solaris versions 2.1 through 2.3 unless the proper operating system patch is applied. See sendmail/README for information about how to fix this problem.

Other Useful Logging

Not all logging uses the equates shown in the next section. Much of what sendmail logs is specific to particular functions. Please refer to Table 14-5 to be guided to other places in this book where we describe additional syslog(3) output.

Table 14-5. Other places that syslog useful information

Section

Description

SMTP Probes on page 157

Log SMTP probes.

-L on page 243

-L defines a logging label.

FEATURE(accept_unresolvable_domains) on page 276

Logging with FEATURE(accept_unresolvable_domains)

FEATURE(greet_pause)—V8.13 and Later on page 293

Logging with FEATURE(greet_pause)

Log quarantined messages on page 442

Log quarantine messages

The Postmaster Alias on page 473

can't even parse postmaster!

The User’s ~/.forward File on page 500

The user’s ~/.forward file

${daemon_info} on page 819

The ${daemon_info} listening daemon’s syslog information

syslog on page 939

The syslog database-map type syslogs via rule sets

Milter Logging with syslog on page 1180

Milter logging with syslog

Alphabetized syslog Equates

In this section we list, in alphabetical order, the common syslog(3) equates you will encounter during normal operations.

action=

The Milter’s phase syslog equate

The action= equate specifies the Milter phase that was in effect when the message was prevented from being delivered. The phases correspond to the xxfi routines in the Milter documentation. For example, if the xxfi_header(3) routine (Milter xxfi_header() on page 1217) was used to reject the message based on a header, the following action= will be logged:

action=header

arg1=

The argument to a check_ rule set syslog equate

When sendmail processes one of the check_ rule sets (The Local_check_ Rule Sets on page 252) and when that rule set rejects a message, sendmail logs one of the following two messages:

... ruleset=rset, arg1=firstarg, discard
... ruleset=rset, arg1=firstarg, reject=reason

Here, rset is the name of the rule set called (such as check_mail, Local_check_mail and check_mail on page 255). The workspace passed to the rule set is indicated by firstarg.

Note that some check_ rule sets (such as check_relay, Local_check_relay and check_relay on page 252) take more than one argument. If so, the workspace is provided with the first argument separated from the second with a $| operator. When a second argument is supplied, the log lines shown earlier will have an arg2= equate added which shows that second argument.

When a message is rejected, a reason is passed back to the original envelope sender. That reason is echoed with the reject=reason (reject= on page 526).

bodytype=

The body type of the message syslog equate

The body type of a message can be BITMIME, BIT, or undefined. If it is defined, this equate will appear in the envelope sender’s syslog(3) record to show the body type:

... bodytype=8BITMIME,

class=

Precedence: header’s value syslog equate

If the mail message contained a Precedence: header (Precedence on page 1148), the class= reflects sendmail’s interpretation of the keyword that follows that header. For example, given the configuration command:

Plist=-30

the following header will yield a class= value of −30:

Precedence: list

If no Precedence: header is present in the message, the value shown for class= is zero. The class= is shown only for sender records.

ctladdr=

The controlling user syslog equate

When sendmail logs the recipient’s record, it will include the identity of the controlling user, if there is one. A controlling user is set when delivering to files (Delivery to Files on page 466) or through programs (Delivery Via Programs on page 468):

ctladdr=<you@your.domain> (111/22),

The controlling user is printed as an address, the <you@your.domain>, although it could also be a local login name when mail originates locally (such as you). If the controlling user is the identity of a local user, the uid (the 111) and the gid (the 22) for that user are also logged.

daemon=

The name of the sender’s daemon syslog equate

When sendmail logs the sender of a message it includes a syslog equate that shows the name of the daemon that handled the transaction. Daemons are named with the DaemonPortOptions option’s Name pair (DaemonPortOptions=Name= on page 996).

O DaemonPortOptions=Name=MTA

Whenever sendmail logs the sender of a message (with from=) and when the message was handled by a daemon (not standard input), this daemon= syslog equate will show the daemon’s name.

delay=

The total time to deliver syslog equate

A mail message can be delivered immediately, without ever having been queued, or it can be queued and retried over and over again until it either times out or succeeds. The delay= shows the total amount of time the message took to be delivered. This period of time starts when sendmail first receives the message and ends when the message is finally delivered or bounced. This interval is displayed with the delay= syslog line equate:

delay=DD+HH:MM:SS

The time expression shows the time it took in hours (HH), minutes (MM), and seconds (SS) to handle delivery or rejection of the message. If the delay exceeds 24 hours, the time expression is prefixed with the number of days (DD) and a plus character. For example, the following message took 5 seconds to deliver or bounce:

delay=00:00:05

The following message took 4 days, 2 hours, 16 minutes, and 2 seconds to deliver or bounce:

delay=4+02:16:02

Note that the delay= syslog equate is shown only for recipient records.

dsn=

Show DSN status code syslog equate

When sendmail bounces a message, it notifies the envelope sender of the problem using DSN. A critical part of DSN is the error code, which provides more detail than the usual SMTP error code. A DSN error code, as reported with syslog, looks like this:

dsn=5.7.0

Here, the 5 means it was a permanent error, and the 7 means it was a security or policy rejection. The meanings of DSN status codes are documented in RFC1893.

from=

The envelope sender syslog equate

The from= syslog equate shows the envelope sender:

from=addr

The addr is the address of the envelope sender with any RFC2822 commentary (Comments in the Header Field on page 1125) removed. This will usually be the address of an actual person, but it can also be postmaster or the value of the $n sendmail macro ($n on page 836) in the case of a bounced message. The from= syslog equate is shown only for sender records.

intvl=

The illegal interval to schedule syslog equate

The sendmail program needs to schedule events that happen at future times—for example, processing the queue. Internally, such events are set by specifying an interval to wait before the event is to begin. In the unusual instance that any such interval is less than or equal to zero, sendmail will log a message such as the following:

554 5.3.0 setevent: intvl=seconds

Here, the leading 5.3.0 is reported because such an error can happen during an SMTP session. The seconds will print as zero or as a negative number.

Should you ever see this error, the problem will most likely be found in a bad time specification in your configuration file.

len=

The length of a too-long header value syslog equate

Beginning with V8.10, sendmail is able to check headers with rule sets (Rules Check Header Contents on page 1130). When such a rule set is specified as part of the H configuration command, and when that header is found in a message, sendmail first assigns values to special variables (such as {hdrlen}, {currHeader}, and {hdr_name}) and then calls the appropriate rule set. Should the calculated length of the header (as stored in {hdrlen}) prove longer than the limit set at compile time by MAXNAME (MAX... on page 120), the following error will be logged and the too-long header will be truncated:

Warning: truncated header 'hdr' before check with 'ruleset' len=len max=
MAXNAME

Here, hdr is the name of the header (the text to the left of the colon). The ruleset is either the number or the name of the rule set that will be called to check this header. The len is the length of the value (the part of the header to the right of the colon) before it was truncated. Generally, unless you redefined it, the maximum length is set by MAXNAME, which defaults to 256 characters (including the terminating zero-value character).

Note that this reports only that the value (the part of the header to the right of the colon) is too long. If the name (the part of the header to the left of the colon) is longer than 100 characters, it will never be checked.

mailer=

The delivery agent used syslog equate

The sendmail program calls other programs (called mail delivery agents) to perform that delivery. Some delivery agents are external (as for local delivery), and others are internal (as for network delivery). The mailer= syslog equate shows the symbolic name (The M Configuration Command on page 711) of the delivery agent that was used to perform delivery to the recipient:

mailer=agent

A list of symbolic names assigned to delivery agents can be viewed with the -d0.15 debugging switch (-d0.15 on page 544). The mailer= syslog equate is shown only for recipient records.

milter=

Name of the Mliter that issued the log record syslog equate

The milter= equate shows the name of the Milter that was used to prevent the message from being sent. That name was set by the X configuration command when your configuration file was created. For example, the following sets the name of the Milter to Milter1:

INPUT_MAIL_FILTER(`Milter1', `S=local:/var/run/f1.sock, F=R')

If a message is prevented from being delivered by this Milter, the following equate will be logged:

milter=Milter1

This equate is most useful when you run multiple Milters.

msgid=

The Message-ID: header identifier syslog equate

RFC2822 requires that each email message have a unique worldwide identifier associated with it. That identifier is listed with the Message-ID: header (Message-ID: on page 1159) and often looks something like this:

Message-Id: <200212131533.dAPFX1o01876@here.us.edu>

The information inside, and including, the angle brackets is the message identifier. That identifier is what is listed with the msgid= syslog equate:

msgid=<200212131533.dAPFX1o01876@here.us.edu>

If a mail message arrives without a Message-ID: header, and if your configuration file correctly includes a definition for that header, a new identifier will be created and listed with msgid=. If a Message-ID: header is absent, and if your configuration file incorrectly excludes a definition for that header, the msgid= syslog equate will be excluded from the syslog report.

The msgid= syslog equate is shown only for sender records.

nrcpts=

The number of recipients syslog equate

The nrcpts= syslog equate shows the number of recipients after all aliasing has been performed. If the original message was addressed to root, and if root was aliased like this:

root: bob, hans

and if bob’s ~/.forward file contained this:

\bob
|"/usr/ucb/vacation bob"

the nrcpts= syslog equate would show three recipients.

Note that nrcpts= is included only with the sender record and that record is emitted when the message is first processed. Any later changes in aliasing that might happen while the message is queued are not reported. Aliasing on remote machines (as would be the case with exploder mailing lists) is also not reported for obvious reasons.

ntries=

The number of delivery attempts syslog equate

The ntries equate shows the number of times delivery was attempted before final delivery could be achieved for an envelope, or before delivery couldn’t be successfully achieved, resulting in the message being returned to the sender. When multiple envelopes are processed from the queue and are destined for the same host, only the first will be deferred and have its number of attempts incremented. The others will not be tried because the host is unavailable, and therefore will not have their number of attempts incremented. Thus, the ntries equate shows only actual attempts.

Note that the ntries= syslog equate is shown only for recipient records. Also note that the ntries= syslog equate will appear only if the LogLevel option (LogLevel on page 1040) is set to 10 or above.

pri=

The initial priority syslog equate

The pri= syslog equate shows the initial priority assigned to the message (Precedence on page 1148). This value is calculated once when the message is first processed and changed each time the queued file is tried. This pri= syslog equate shows the initial value.

The pri= syslog equate is displayed only for the sender. As of V8.10 sendmail, this equate is displayed only for the recipient, and it shows the current priority as it changes with each delivery attempt.

proto=

The protocol used in transmission syslog equate

The $r sendmail macro ($r on page 842) holds as its value the protocol that was used when a mail message was first received. That value is either SMTP, ESMTP, or internal, or it is a protocol assigned with the -p command-line switch (-p on page 246). If $r lacks a value, this proto= syslog equate is omitted. If $r has a value, the first 20 characters of that value are printed following the proto= in the syslog line:

proto=ESMTP

quarantine=

Reason the message was quarantined (V8.13 and later) syslog equate

The quarantine= equate is used to log the reason that an envelope was quarantined (Log quarantined messages on page 442). For example, the following log line shows that this particular envelope was quarantined because it was destined for a competitor’s site:

Oct  9 11:26:00 your.domain sendmail[4788]: f99IPuIH004788: ruleset=check_mail, arg1=
bob@competitor.gov, quarantine=Held, mail from competitor.gov

Note that the reason for quarantining, which is printed following this equate, may contain spaces, equals signs, and commas, possibly making this output more difficult to parse.

reject=

The reason a message was rejected syslog equate

When sendmail processes one of the check_ rule sets (The Local_check_ Rule Sets on page 252) and when that rule set rejects a message, sendmail logs the following message:

... ruleset=rset, arg1=firstarg, reject=reason

Here, rset is the name of the rule set called (such as check_mail, Local_check_mail and check_mail on page 255). The workspace passed to the rule set is indicated by firstarg. The reason for the rejection is echoed with the reject=reason. For example, the following rule causes mail to fax to be rejected:

Rfax                    $#error $@ 5.1.3 $: cannot send mail to fax

This rule would produce a reject= syslog(3) message such as this:

reject=553 5.1.3 <fax@ourhost>... cannot send mail to fax

A complete description of the construction of rejection messages can be found throughout Chapter 7.

relay=

The host that sent or accepted the message syslog equate

When running as a daemon and listening for incoming connections, sendmail attempts to look up the true identity of connecting users and hosts. When it can find that information, it saves it in the $_ sendmail macro ($_ on page 801).

When transporting mail to other hosts, sendmail looks up the MX records for those hosts and connects to the MX records when they are available. If MX records are not available, sendmail connects to A or AAAA addresses.

For recipient and sender syslog lines, the relay= syslog equate shows the name of the corresponding receiving or sending host, followed by the A address, or AAAA address, of that host (if there was one) in square braces:

relay=root@other.site.edu [123.45.67.89]

If the sender is a local user, the login name and localhost will appear in the relay= syslog equate:

relay=bob@localhost

In summary, the relay= syslog equate shows who really accepted or sent the message.

ruleset=

The check_ rule set syslog equate

When sendmail processes one of the check_ rule sets (The Local_check_ Rule Sets on page 252) and when the rule set rejects a message, sendmail logs one of the following two messages:

... ruleset=rset, arg1=firstarg, discard
... ruleset=rset, arg1=firstarg, reject=reason

Here, rset is the name of the rule set called (such as check_mail, Local_check_mail and check_mail on page 255). The workspace passed to the rule set is indicated by firstarg. When a message is rejected, a reason is passed back to the original envelope sender.

size=

The size of the message syslog equate

The size of an incoming SMTP message is the number of bytes sent during the DATA phase, including end-of-line characters. The size of a message received via sendmail’s standard input is a count of the bytes received, including the newline characters. In both instances, the size is displayed with the size= syslog equate:

size=23

Note that this size is reported before sendmail adds or deletes any headers. Therefore, for mail being relayed through a site, the size will usually be small coming in and somewhat larger going out.

The size= syslog equate is produced only for sender records.

stat=

The status of delivery syslog equate

Whenever the delivery status of a mail message changes, sendmail logs the event and includes the stat= to specify why the change happened. For example, a mail message might initially be queued because the recipient’s host was down:

stat=queued

Later it might change again because it succeeded in being delivered:

stat=Sent (HAA03001 Message accepted for delivery)

In transmitting a mail message via SMTP, the stat= will include the actual text that the other host printed when it accepted the mail message, as shown earlier. But in delivering locally, the stat= is more succinct:

stat=Sent

In the case of bounced mail, the stat= will show the reason for failure:

stat=User unknown

The stat= syslog equate is included only in recipient records.

to=

The final recipient syslog equate

As each recipient is delivered to, deferred, or bounced, sendmail logs a line of information that includes the recipient address:

to=bob@here.us.edu

Each such address is that of a final recipient (from the point of view of the local host) after all aliasing, list expansions, and processing of ~/.forward files.

xdelay=

The transaction delay for this address only syslog equate

The xdelay= syslog equate shows the amount of time the current total transaction took. This could be the amount of time the message took to be transmitted during its successful, final delivery, or the amount of time the message took to be deferred because of a transient error. This differs from delay= in that delay= shows the total amount of time the message took, computed from when the message was originally received or queued (this could be days ago), until it was eventually delivered.

In the case of SMTP mail, the xdelay= computation starts when sendmail starts trying to connect to the remote host. In the case of locally delivered mail, the computation starts when sendmail executes the delivery agent. The computation ends when the dot is accepted at the close of the DATA SMTP phase or when the local delivery agent exits, and is typically a few seconds.

The form of the xdelay= looks like this:

xdelay=HH:MM:SS

The time expression shows the hours (HH), minutes (MM), and seconds (SS) it took to perform delivery via the final delivery agent. In the case of networked mail, that interval can be long but usually isn’t:

xdelay=00:41:05       ← sometimes a bit long
xdelay=00:00:02       ← usually swift

But in the case of locally delivered mail, this interval can seem instantaneous:

xdelay=00:00:00

Note that the xdelay= syslog equate is shown only for recipient records.



[220] * This same information is syslog‘d if the daemon loses track of $j in $=w and if $j becomes or is not fully qualified.

[221] * In V8.7 sendmail, this is rule set 89. Beginning with V8.8 sendmail, rule sets 80 through 89 are reserved for use by vendors, such as Sun Microsystems.

[222] * Note that the year is absent. If you need to archive logfiles for multiple years, you will need to modify the dates inside the files, store files in directories named after years, or use some other similar solution.

[223] When one host sends the message to another host for handling, and when that later host also sends the message to yet another host, the final host will show the name of the middle host, not the originating host. In general, it is not wise to relay messages when originating host information is of concern.

[224] * If other programs also put size= expressions into the logfile, you might also want to screen for “sendmail.”