Chapter 25. The H (Headers) Configuration Command

All mail messages are composed of two distinct parts: the header (containing information such as who the message is from) and the body (the actual text of the message). The two parts are separated from each other by a single blank line (although there are exceptions, which we will cover). The header part used by sendmail was originally defined by RFC822 (with clarifications contained in RFC1123), and most recently defined in RFC2822. These three documents detail the required syntax and contents of most header lines in mail messages. Many other RFCs define other headers, but in this chapter we will discuss header lines as they relate specifically to sendmail, referencing other RFCs as necessary.

When sendmail receives a mail message, it gathers all the header lines from that message and saves them internally. Then, during queueing and delivery, it re-creates them and augments them with any new ones that might be required either by the configuration file or by sendmail’s internal logic.

Overview

The H header configuration file command tells sendmail which headers are required for inclusion in the header portion of mail messages. Some headers, such as Date:, are added only if one is not already present. Others, such as Received: (Received: on page 1162), are added even if one or more are already present.

The form for the header command is:

H?flags?name:field

The H must begin the line. The optional ?flags? (the question marks are literal), if present, must immediately follow the H with no intervening space. We will discuss header ?flags? after the name and field are explained.

The name is the name of the header, such as From. The name must immediately follow the ?flags?, if present, or the H if there are no flags.

A colon then follows, which can be surrounded by optional space characters. The field is last and constitutes everything from the first nonspace character following the colon to the end of the line:

Hname   :    fieldfrom here to end of line is the field

The colon must be present. If it is absent, sendmail prints the following error message and ignores that H command:

header syntax error, line "offending H command here"

The "offending H command here" is the full text of the H command in the configuration file that caused the error.

Prior to V8.10 sendmail, the field could only be the text of an ordinary header. Beginning with V8.10, the field can also be a $ > or $+> operator (Rules Check Header Contents on page 1130) followed by the name or number of a rule set through which the header’s value is to be passed:

Hname   :   $>rule  setsee §25.5 on page 1130 for details
Hname   :   $>+rule  set

As with all configuration commands, a line that begins with a space or a tab is joined to the line above it. In this way, header commands can be split over one or more lines:

HReceived: $?sfrom $s $.by $j ($v/$V)
      id $i; $b
  ↑
  tab

When sendmail reads these two lines from the configuration file, they are internally joined to form the single line:

HReceived: $?sfrom $s $.by $j ($v/$V)\n      id $i; $b
                                          ↑
                                          tab

The \n illustrates that when lines are joined, the newline and tab character are retained. This results in the header looking the same as it did in the configuration file (minus the leading H) when it is later emitted by sendmail.

Header Names

The name portion of the H configuration command must be one of the names shown in Table 25-1. Other names do not produce an error but might confuse other programs that need to process them. Names marked with an asterisk are defined by RFC2822.

Table 25-1. Header names

apparently-to

bcc*

cc*

comments*

content-length

content-transfer-encoding

content-type

date*

disposition

encrypted

errors-to

from*

full-name

in-reply-to*

keywords*

mail-from

message

message-id*

notification-to

posted-date

precedence

received*

references*

reply-to*

resent-bcc*

resent-cc*

resent-date*

resent-from*

resent-message-id*

resent-reply-to

resent-sender*

resent-to*

return-path*

return-receipt-to

sender*

subject*

text

to*

via

x400-received

These are discussed individually in Alphabetized Header Reference on page 1150 at the end of this chapter.

The RFC2822 standard allows a special form to be used for creating custom header names. All mail programs, including sendmail, are required to accept and pass through as is any header name that begins with the special characters x-. The following header definition, for example, can be used to introduce information that your site is running an experimental version of sendmail:

HX-Beware: This message used an experimental version of sendmail

The name part of header definitions is case-insensitive. That is, X-Beware, x-beware, and X-BEWARE are all the same. For example, when sendmail checks for the To: header internally, it will recognize it regardless of how it is capitalized.

Beginning with V8 sendmail, header names are left alone. They are passed through without case conversion of any kind. Previous assumptions[435] about capitalization are no longer valid in light of new headers generated and expected by programs.

Header names can contain only printable characters. Names cannot contain control characters, space characters (such as space and tab), or the colon character. An illegal character will result in this error message:

header syntax error, line "HFull Name: $x"

Here, the error is a space in the name portion of the header declaration.

Header Field Contents

The field of the H configuration command can contain any ASCII characters, including whitespace and newlines that result from joining.[436] For most headers, however, those characters must obey the following rules for grouping:[437]

Atom

In the header field, space characters separate one item from another. Each space-delimited item is further subdivided by specials (described next), into atoms:

smtp          ← an atom
foo@host      ← atom special atom
Babe Ruth     ← atom atom

An atom is the smallest unit in a header and cannot contain any control characters. When the field is an address, an atom is the same thing as a token (see Chapter 18 on page 648).

Specials

The special characters are those used to separate one component of an address from another. They are internally defined as:

( ) < > @ , ; : \ " . [ ]

A special character can be made nonspecial by preceding it with a backslash character. For example:

foo;fum       ← atom special atom
foo\;fum      ← one atom

The space and tab characters (also called linear-whitespace characters) are also used to separate atoms and can be thought of as specials.

Quoted text

Quotation marks can be used to force multiple items to be treated as a single atom. For example:

Babe Ruth       ← atom atom
"Babe Ruth"     ← a single atom

Quoted text can contain any characters except for the quotation mark (") and the backslash character (\).

Any text

Some headers, such as Subject: (Subject: on page 1166), impose minimal rules on the text in the header field. For such headers, atoms, specials, and quotes have no significance, and the entire field is taken as arbitrary text.

The detailed requirements of each header name are covered at the end of this chapter.

Macros in the Header Field

Macros can appear in any position in the field of a header definition line. Such macros are not expanded (their values tested or used) until mail is queued or delivered. For the meaning of each macro name and a description of when each is given a value, see Chapter 21 on page 784.

Only two macro prefixes can be used in the field of header definitions:

$

The $ prefix tells sendmail to replace the macro’s name with its value at that place in the field definition.

$?

The $? prefix tells sendmail to perform conditional replacement of a macro’s value.

For example, the following header definition uses the $ prefix to insert the value of the macro x into the header field:

HFull-Name: $x

The macro $x ($x on page 851) contains as its value the full name of the sender.

When the possibility exists that a macro will not have a value at the time the header line is processed, the $? conditional prefix (Macro Conditionals: $?, $|, and $. on page 794) can be used:

HReceived: $?sfrom $s $.by $j ($v/$V)

Here, the $? prefix and $. operator cause the text:

from $s

to be inserted into the header field only if the macro s has a value. $s can contain as its value the name of the sending site.

Escape Character in the Header Field

Recall that the backslash escape character (\) is used to deprive the special characters of their special meaning. In the field of header definitions the escape character can be used only inside quoted strings (see next item), in domain literals (addresses enclosed in square bracket pairs), or in comments (discussed later). Specifically, this means that the escape character cannot be used within atoms. Therefore, the following is not legal:

Full\ Name@domain        ← not legal

Instead, the atom to the left of the @ must be isolated with quotation marks:

"Full Name"@domain        ← legal

Quoted Strings in the Header Field

Recall that quotation marks (") force arbitrary text to be viewed as a single atom. Arbitrary text is everything (including joined lines) that begins with the first quotation mark and ends with the final quotation mark. The following example illustrates two quoted strings:

"Full Name"
"One long string carried over
        two lines by indenting the second"
   ↑
   whitespace

The quotation mark character can appear inside a quoted string only if it is escaped by using a backslash:[438]

"George Herman \"Babe\" Ruth"

Internally, sendmail does not check for balanced quotation marks. If it finds the first but not the second, it takes everything up to the end of the line as the quoted string.

When quotation marks are used in an H configuration command, they must be balanced. Although sendmail remains silent, unbalanced quotation marks can cause serious problems when they are propagated to other programs.

Comments in the Header Field

Comments consist of text inside a header field that is intended to give users additional information. Comments are saved internally by sendmail when processing headers, then are restored, but otherwise are not used. Beginning with V8.7 sendmail, the F=c delivery agent flag (F=c on page 768) can be used to prevent restoration of the saved comments.

A comment begins with a left parenthesis and ends with a right parenthesis. Comments can nest. The following lines illustrate a non-nested comment and a comment nested inside another:

(this is a comment)
(text(this is a comment nested inside another)text)

Comments can be split over multiple lines by indenting:

(this is a comment
       split into two lines)
   ↑
   whitespace

A comment (even if nested) separates one atom from another just like a space or a tab does. Therefore, the following produces two atoms rather than one:

Bill(postmaster)Johnson

However, comments inside quoted strings are not special, so the following produces a single atom:

"Bill(postmaster)Johnson"

Parentheses can exist inside of comments only if they are escaped with a backslash:

<root@host.domain> (The happy administrator ;-\))
                                              ↑
                                              note

Balancing special characters

Many of the special characters that are used in the header field and in addresses need to appear in balanced pairs. Table 25-2 shows these characters and the characters needed to balance them. Failure to maintain balance can lead to failed mail. Note that only parentheses can be nested. None of the other balanced pairs can nest.

Table 25-2. Balancing characters

Begin

End

"

"

(

)

[

]

<

>

You have already seen the quoted string and comments. The angle brackets (< and >) are used to specify a machine-readable address, such as <gw@wash.dc.gov>. The square brackets ([ and ]) are used to specify a direct Internet address (one that bypasses normal DNS name lookups), such as [123.45.67.89].

The sendmail program gives warnings about unbalanced characters only when it is attempting to extract an address from a header definition, from the header line of a mail message, or from the envelope. Beginning with V8.6, when sendmail finds an unbalanced condition, it tries to balance the offending characters as rationally as possible. Regardless of whether it can balance them, it prints one of the following warning messages:

Unbalanced ')'
Unbalanced '>'
Unbalanced '('
Unbalanced '<'
Unbalanced '"'

If it did not succeed in balancing them, the mail will probably bounce.

?flags? in Header Definitions

The name part of the H configuration command can be prefixed with a list of flags. This list, if present, must be surrounded by ? characters:

H?flags?name:field

The ? characters must immediately follow the H and immediately precede the name with no intervening spaces. If a space precedes the first ?, that ? is misinterpreted as part of the header name, rather than as the start of a list of flags, and this error message is printed:

header syntax error, line " ?flags?name: field"
                           ↑
                           note leading space

If the first ? is present but the second is absent, sendmail prints the same error message and skips that H configuration command. The flags that are listed between the ? characters correspond to flags that are listed with delivery agent F= equates. When processing a mail message for forwarding or delivery, sendmail adds a header line if a flag is common to both the H definition list of flags and the delivery agent’s list of flags. For example:

H?P?Return-Path: <$g>

This H definition begins with a P flag. This tells sendmail to add this header line to the mail message only if a selected delivery agent also contains that flag. Because the Return-Path: header (Return-Path: on page 1165) should be added only during final delivery, the P flag appears only in the prog and local delivery agent definitions:

Mprog,  P=/bin/sh,   F=lsDFMeuP,  S=10, R=20, A=sh -c $u
Mlocal, P=/bin/mail, F=rlsDFMmnP, S=10, R=20, A=mail -d $u
                               ↑
                               note

No check is made to ensure that the H flags correspond to existing delivery agent flags. Beware that if a corresponding F= flag does not exist in some delivery agent definition, that header can never be added to any mail message.

Care should be used to avoid selecting flags that have other meanings for delivery agents. Table 20-19 on page 759 lists all the delivery agent flags that have predefined meanings, including those traditionally used with header definitions.

Macros Force Header Inclusion

Beginning with V8.12, it is possible to add a header to a message by placing a sendmail macro between the ? characters instead of, or in addition to, using flags (see ?flags? in Header Definitions). But note that for V8.10 and V8.11 only, the ? character method was omitted, and only a macro could appear in that position:

H?flags?X-Added-Header:  valueall versions
H${macro name}X-Added-Header:  valueV8.10 and V8.11 only
H?${macro name}?X-Added-Header:  valueV8.12 and later
H?${macro name}flags?X-Added-Header:   valueV8.12 and later

In the last three examples, if the macro has a value (is defined and is non-null), the header will be added to the email message. If the macro lacks a value (was not defined or was defined to be an empty string), the header is not added to the message. The first and last examples cause the header to be added if a corresponding flag appears in the F= equate of the selected delivery agent.

Note that if the header is already in the message, it will remain there, regardless of whether the macro is defined, or whether a flag is in the appropriate F= equate.

To illustrate, consider dealing with a message that contains an illegally formed Message-Id: header:

LOCAL_CONFIG
Kstorage macro
HMessage-Id: $>ScreenMessageId
H?${MsgId}?X-Authentication-Warning: ${MsgId}
C{persistentMacros} {MsgId}

LOCAL_RULESETS
SScreenMessageId
R < $+ @ $+  >          $@ OK
R $*                    $: $(storage {MsgId} $@ Illegal Message-Id: $1 $)

The LOCAL_CONFIG part of this mc file declares a macro-type database map (macro on page 925) that is used to store a value into a sendmail macro via a rule set.

The LOCAL_CONFIG part of this mc file continues with two H configuration file commands. The first says that each Message-Id: header in the message must be screened by the ScreenMessageId rule set. The use of the $> operator (Rules Check Header Contents on page 1130) ensures that sendmail will strip RFC2822 parenthetical comments from the header’s value. The second H line uses the V8.12 (and later) form of a macro between the ? characters. This tells sendmail to add this header if the ${MsgId} has or is given a value. We discuss the {persistentMacros} declaration soon.

The LOCAL_RULESETS part of this mc file declares a single rule set. The ScreenMessageId rule set has two rules. The first rule checks the workspace which contains the value of the Message-Id: header with RFC2822 parenthetical comments stripped. If that value is formed by a user and host part separated by an @ character and surrounded by angle brace characters, the Message-Id: header is correctly formed. By returning anything other than the $#error delivery agent, the message is allowed.

The second rule in the ScreenMessageId rule set matches everything (the $* in the LHS), so the RHS is always called. The RHS calls the storage database map, which stores a value into the ${MsgId} macro. The value stored is the phrase Illegal Message-Id: followed by the value of the offending Message-Id: header.

By defining the ${MsgId}, sendmail will add a new header to the message because of the mc file line:

H?${MsgId}?X-Authentication-Warning: ${MsgId}

If a message were to arrive with a bad Message-Id: header, such as the following:

Message-Id: <167445390329650300582-mailer.exe v1.2>

the preceding rules would cause the following new header to be added to the message:

X-Authentication-Warning: Illegal Message-Id: <167445390329650300582-mailer.exe v1.2>

Note that sendmail macros in header definitions do not need the $& prefix because macros used in header declarations are not processed when the configuration file is read. They are instead processed when the header declaration line is processed.

As a precaution, only store values into macros that you define. By storing values into sendmail’s internally defined macros, you can easily corrupt the sendmail program’s operation, with unforeseen results.

Macro-Included Headers Don’t Survive Queueing

The inclusion of a header based on a macro’s value is guaranteed to work only when mail is first sent or delivered, and can fail if the message is queued. Consider, for example, the desire to include a header that prints one of the sendmail program’s macro values:

LOCAL_CONFIG
H?${dsn_envid}?X-ENVID: ${dsn_envid}

The intention here is to record the value of the DSN envelope identifier value in an X- header, if such an identifier was supplied during the SMTP transaction. If a message is received with a MAIL From: line such as the following, the envelope identifier and ${dsn_envid} macro’s value will be given the text following the ENVID= expression:

MAIL From: <bob@some.domain> ENVID=1234abcd5678

When this message is received, the ${dsn_envid} macro will contain a value (the string 1234abcd5678) which will cause the X-ENVID: header to be given a value:

X-ENVID: 1234abcd5678

If this message cannot be delivered right away and is deferred to the queue instead, the previous header will be stored in the queue like this:

H?${dsn_envid}?X-ENVID: 1234abcd5678

Note that the original mc file’s ?${dsn_envid}? test is included in the queue file. When this message is later delivered, the ${dsn_envid} macro will not have a value. That macro is given a value only when the message is first received with SMTP. As a consequence, when the message is delivered from the queue, the ${dsn_envid} macro will lack a value and thus the X-ENVID: header will not be included in the delivered message.

If you need to base header inclusion on such macros, you should add the macro’s name to the $={persistentMacros} class ($={persistentMacros} on page 873) to ensure that the macro’s value survives the queue process. Using this solution, the previous mc file declaration will instead look like this:

LOCAL_CONFIG
H?${dsn_envid}?X-ENVID: ${dsn_envid}
C{persistentMacros} {dsn_envid}

Macros saved in the $={persistentMacros} class will have their values saved when the message is queued and restored when the message is delivered from the queue.

Note, however, that the $={persistentMacros} class can be dangerous. To be safe, avoid adding any of sendmail’s internally defined macros to this class.

Rules Check Header Contents

Recall that a header line declaration looks like the following:

H?flags?name:field

Here, the H begins the line and tells sendmail that a header definition follows. The ?flags? expression causes sendmail to include the header only if one of the flags is found in the selected delivery agent’s F= equate. As you saw in the preceding section, beginning with V8.10, a macro name can replace the flags. The name and a colon then follow.

Beginning with V8.10, sendmail allows the name of a rule set to replace the field value. That rule set declaration can come in two forms:

Hname: $>  rule  set
Hname: $>+  rule  setdon't strip comments

Both forms basically say the same thing: if sendmail finds a header name already in a message it is processing, it passes the existing header field to the rule set indicated. The + in the second form tells sendmail to leave intact (not strip) parenthesized RFC2822 comments from the passed field:

text (comments)

The $> in the earlier declaration passes just text to the rule set, and $>+ passes the unstripped text with RFC2822 comments intact.

If the rule set specified is not a legal rule set name, or if it is missing, the following error will be printed and logged:

cf file name: line number: invalid rule set name: "bad name"

If the named rule set does not exist in the configuration file, the effect is the same as if it did exist and had returned a legal value.

Rule sets called to process headers can return two possible rejection values, a $#error or a $#discard. If a $#error is returned, the entire message is rejected. If a $#discard is returned, the message is accepted, then silently discarded. If anything else is returned, the message and that header are both allowed. To illustrate, consider the following code which rejects spam messages that are addressed with a To: header that contains unwanted usernames:

LOCAL_CONFIG
C{SpamUserNames} investor adult friend you ValuedCustomer Valued-Customer
HTo: $>ScreenTo
LOCAL_RULESETS
SScreenTo
R $* $={SpamUserNames} @ $*      $#error $: "553 To: header rejected"
R $*                             $: OK

In the LOCAL_CONFIG part of your mc file, the line beginning with C declares a class and assigns values to that class. The class name is {SpamUserNames} and the class contains as its values six usernames that commonly appear as the user part of addresses in the To: header.

The line beginning with H declares a To: header and a rule set to handle that header. The $> tells sendmail to strip parenthesized RFC2822 comments from the address that followed the To: in the message, and to pass that stripped address to the ScreenTo rule set.

The LOCAL_RULESETS part of this mc file contains a single rule set, the ScreenTo rule set, which contains two rules. The first rule asks whether the address in the workspace has a user part that matches any of the names listed in the class $={SpamUserNames}. If the address contains an objectionable username, the entire message is rejected by returning the error delivery agent with the expression $#error.

The last rule (the $*) causes all other addresses to return OK. Technically, the last rule is not needed because, even in its absence, the original workspace will be returned, and because that original workspace will contain neither $#error nor $#discard, the message will be allowed.

The $: part following the $#error is required. It tells sendmail how to reject the message. See error on page 720 for a description of how this process works.

Use $>+ to Include RFC2822 Comments

Some headers contain addresses, along with other important information, that appears as RFC2822 commentary. The Received: header is one such header:

                         RFC2822 commentary starts here
                     and ends here
                                  ↓                                    ↓
 Received: from some.other.domain (root@some.other.domain [29.22.14.17])
         by your.domain (8.12.4/8.12.4) with ESMTP id g5CMW6KF010979
         for <you@your.domain>; Wed, 12 Jun 2002 16:32:09 −0600 (MDT)

Other headers, such as the Subject: header, do not contain addresses:

Subject: Make money now (Adult Triple-X web site)

When screening such headers, it is important that they are not interpreted as addresses or information might be lost.

Consider the previous Subject: header’s value. If such a header were screened with an H configuration file line like this:

HSubject: $>ScreenSubject

the rule set named ScreenSubject would be given the following value to parse:

Make money now

Beginning with V8.10, sendmail offers the $>+ operator to prevent parenthetical RFC2822 comments from being stripped out of headers that do not contain addresses as values:

HSubject: $>+ScreenSubject
            ↑
          note

By using this new operator, the original subject is passed to the ScreenSubject rule set in a form that is much more intact:

Make money now(Adult Triple-X web site)

Note that because of the way sendmail splits up addresses and pastes them back together, the space between the now and the ( has been lost. But this does not matter because of the way rule matching operates.

As a side benefit, the ${currHeader} sendmail macro is filled with the header’s value, and so will contain the original header value unchanged and quoted. The fact that it is quoted is important because quoting prevents the value from being viewed by sendmail as tokens.

Consider the need to screen out messages that contain the text Adult Triple-X anywhere in the Subject: header.

LOCAL_CONFIG
KRegxxx regex -a@MATCH Adult Triple-X
HSubject: $>+ScreenSubject

LOCAL_RULESETS
SScreenSubject
R$*           $: $( Regxxx $&{currHeader} $)
R@MATCH       $#error $@ 5.7.0 $: "553 pornographic subject"

Here, the LOCAL_CONFIG part of this mc file contains two configuration commands. The first creates a regular expression database map (regex on page 932) called Regxxx. It says to return (the -a) the value @MATCH if the value looked up contains the text Adult Triple-X surrounded by any other text.

The second declares a header with the H configuration command. This tells sendmail to pass the value of all Subject: headers to the rule set named ScreenSubject. The addition of the + to the $ > prevents sendmail from stripping RFC parenthetical comments from the value.

The LOCAL_RULESETS part of this mc file contains a single rule set, the ScreenSubject rule set, which contains two rules. The first rule looks up the unaltered Subject:’s value in the ${currHeader} sendmail macro using the Regxxx database map. If the value in the ${currHeader} macro contains the text Adult Triple-X anywhere in it, the first rule returns the new workspace value @MATCH. If the text Adult Triple-X is not found, the value of the ${currHeader} macro is returned as the workspace.

The second rule looks for a match by detecting a workspace that contains only @MATCH. If there is a match, the message is rejected with the error message “553 pornographic subject.”

No balancing with $>+

Recall that header values can be passed to rule sets using the $> and $>+ operators:

Hname: $>  rule  set
Hname: $>+ rule  setdon't strip comments

Prior to V8.13, the $>+ operator caused a header’s value to be passed to the specified rule set with RFC2882 comments intact:

text (comments)
<address> commment

Also, prior to V8.13, the $>+ operator checked for special balancing characters and performed a correction when they were not found. For example, if a Subject: header’s value arrived like this:

Subject: ----> test <----

the $>+ operator would cause it to be corrected to the following:[439]

Subject: <----> test ----

The $>+ operator would then cause the result to be passed to the appropriate rule set. But if a rule set was designed to detect the first form (the ---> test), it would fail because it would actually receive the second form.

Beginning with V8.13 sendmail, however, the $>+ operator now no longer tries to balance special characters. And because header values are passed to rule sets as is, rule set header checking is now more accurate, and useless warnings about unbalanced characters have been eliminated.

The characters that used to be special (and that needed to be balanced) are shown in Table 25-3.

Table 25-3. Former $>+ balancing characters

Begin

End

"

"

(

)

[

]

<

>

See also As of V8.13, rules no longer need to balance on page 653 for a discussion of rules and how they, too, no longer need to balance.

Note that beginning with V8.14, header values are guaranteed to be 8-bit clean. Also note that beginning with V8.14, extra spaces following the colon are preserved as part of the header’s value.

Check the header’s length

Sometimes it can be desirable to reject headers based on their length. As we described in the preceding section, when a header is screened with $> or $>+, the unaltered value of the header is stored in the ${currHeader} macro. At the same time, the length of the header’s value is also stored in the ${hdrlen} macro.

To illustrate one possible use for this macro, consider the following abstract from your mc file:

LOCAL_CONFIG
Kcompute arith                 ← V8.10 and later
HSubject: $>ScreenSubject

LOCAL_RULESETS
SScreenSubject
R$*           $: $(compute l $@ 200 $@ $&{hdrlen} $)
RTRUE         $#error $@ 5.7.0 $: "553 Subject too long"

The LOCAL_CONFIG part of this mc file contains two configuration commands. The first declares an arith database map (arith on page 898) named compute. The second tells sendmail to screen all Subject: headers using the ScreenSubject rule set.

The LOCAL_RULESETS part of this mc file contains a single rule set, the ScreenSubject rule set, which has two rules. The first rule uses the compute database map to compare the value in the ${hdrlen} macro with the constant 200. The l asks whether 200 is less than the value in ${hdrlen}. If it is, this rule will return TRUE in the workspace. Otherwise, it will return FALSE.

The second rule says that if the first rule returned TRUE (200 is less than the header’s length, or the header’s length is greater than 200), reject the message.

H* a Default for All Headers

The preceding two sections have shown it is possible to screen specific headers for properties to accept or reject. There will be times, however, when you might wish to screen all headers that do not have their own rule sets. Using an * in place of the header name provides just such a mechanism:

H*: $>ScreenAll

The * tells sendmail to pass all headers, except those that have their own H configuration line rule set, to the ScreenAll rule set. Use $>+ instead of $>, if you want to prevent sendmail from stripping RFC2822 parenthetical comments from each header’s value.

Consider a site that sends email only to mailing lists. On such a site, it is desirable to prevent mail that is considered spam from going out. One way to do this is to reject all mail that contains addresses that are in either Cc: or Bcc: headers (good addresses should only be in To: headers). Such a site might have an mc file that contains the following:

LOCAL_CONFIG
C{BannedRecipientHeaders} Cc Bcc
H*:     $>CheckBanned

LOCAL_RULESETS
SCheckBanned
R $*                              $: $&{hdr_name}
R $={BannedRecipientHeaders}      $#error $@ 5.7.0 $: "553 Banned recipient header"

The LOCAL_CONFIG part of this mc file contains two configuration commands. The first declares a class called BannedRecipientHeaders and assigns to that class a list of header names that should be banned, those being the Cc: or Bcc: headers with the colon removed.

The second configuration command starts with the wildcard form of the H configuration command. The * in place of a header’s name causes all headers, other than those that have their own H configuration commands, to be screened by the CheckBanned rule set.

The LOCAL_RULESETS part of this mc file contains a single rule set, the CheckBanned rule set, which contains two rules. The first rule simply replaces the workspace with the value in the ${hdr_name} sendmail macro. That macro contains as its current value the name of the header passed to this rule set.

The second rule checks, on its LHS, to see if the header name is one of those listed in the class $={BannedRecipientHeaders}. If the header is found, the entire message is rejected.

Note that this example will also reject inbound mail that contains Cc: or Bcc: headers. A better design would include a test to be sure the message originated from the local machine.

The check_eoh Rule Set

After all headers have been processed by sendmail, a couple of statistics become available that can be of use in screening messages. One is the number of headers found. The other is the total number of bytes in all the headers (including the names, colons, whitespace, and values). If you should ever need this information, you can process it by declaring a special rule set named check_eoh. If that rule set exists, it will be passed the number of headers, and the total number of bytes in all the headers:

number of headers  $|    total bytes

If it exists, sendmail will call the check_eoh rule set after all headers have otherwise been processed.

Some users have been known to bury information in headers that should not leave a security-conscious site. Clearly, it is not possible to individually screen all possible headers. Instead, one approach might simply be to reject messages that contain more than 25 headers or more than 10,000 bytes of headers. The following extract from a site’s mc file does just that:

LOCAL_CONFIG
Kcompute arith

LOCAL_RULESETS
Scheck_eoh
R $* $| $*           $: $(compute l $@ 25 $@ $1 $) $| $2
R TRUE $| $*         $#error $@ 5.7.0 $: "553 Too many headers"
R $* $| $*           $: $(compute l $@ 10000 $@ $2 $)
R TRUE               $#error $@ 5.7.0 $: "553 Too many header bytes"

The LOCAL_CONFIG part of this mc file declares an arith database map (arith on page 898) named compute.

The LOCAL_RULESETS part of this mc file declares the specially named rule set check_eoh, which has four rules.

The first rule passes $1, the value to the left of the $| in the workspace, to the compute database map. A comparison is made to see whether 25 is less than that value. If it is, this rule will return TRUE, a $|, and $2 in the workspace. Otherwise, it will return FALSE, a $|, and $2.

The second rule checks to see whether the comparison was true. If it was (if 25 is less than the number of headers—that is, if the number of headers is greater than 25), the message is rejected.

The third rule passes the value to the right of the $| in the workspace, to the compute database map. A comparison is made to see whether 10,000 is less than that value—that is, less than the total number of bytes in the values of all the headers. If it is, this rule will return TRUE. Otherwise, it will return FALSE.

The fourth rule checks to see whether the comparison was true. If it was (if 10,000 is less than the number of bytes—that is, if the number of bytes is greater than 1,000), the message is rejected.

Note that this example could wrongly reject inbound mail. A better design would include a test to be sure the message originated from the local network.

Check for missing headers

The check_eoh rule set can also be used to detect missing headers. Although the Message-Id: is not mandatory, its absence often indicates that a message is spam.[440] The following abstract from an mc file shows one way to detect a missing header, and to reject a message based on that absence:

LOCAL_CONFIG
Kstorage macro
HMessage-Id: $>ScreenMessageId

LOCAL_RULESETS
SScreenMessageId
R $*                     $: $(storage {GotMessageId} $@ YES $) $1

Scheck_eoh
R $*                     $: < $&{GotMessageId} >
R $*                     $: $(storage {GotMessageId} $) $1
R < YES >                $@ OK
R < >                    $#error $@ 5.7.0 $: 553 Missing Header

The LOCAL_CONFIG part of this mc file contains two configuration commands. The first declares a macro-type database map (macro on page 925) which is used to store a value into a sendmail macro via a rule set. The second configuration command causes the Message-Id: header to be screened by the ScreenMessageId rule set.

The LOCAL_RULESETS part of this mc file declares two rule sets. The ScreenMessageId rule set has a single rule which simply stores the literal value YES into the ${GotMessageId} macro. This means that the Message-Id: header was found.

The check_eoh rule set, which contains five rules, is called after all headers have been processed. The first rule fetches the current value (the $& prefix) found in the {GotMessageId} macro and places that value (surrounded by angle braces) into the workspace. If the {GotMessageId} macro lacks a value (if no Message-Id: header was found), the workspace will contain angle braces with nothing between them.

The second rule clears the value from the ${GotMessageId} macro so that it can be reused for the next message that is processed by sendmail.

The third rule looks for a literal <YES> in the workspace, which would appear if the Message-Id: header had been found, and causes the message to be accepted by returning a $@OK on the RHS.

The last rule looks for nothing between the angle braces, which means there was no Message-Id: header in the message. The $#error causes the message to be rejected with the line error 553 5.7.0 Missing Header.

You probably should not use these rules as is because email that originates internally might not have a Message-Id: header and you will need to allow for such mail.

Header Behavior in conf.c

The sendmail program has a built-in understanding of many header names. How those names are used is determined by a set of flags in the source file conf.c supplied with the source distribution. Site policy determines which flags are applied to which headers, but in general, conf.c applies them in the way that is best suited for almost all Internet sites. If you desire to redefine the flags for a particular header name, look for the name’s declaration in the C-language structure definition HdrInfo in conf.c. Be sure to read the comments in that file. Changes to header flags represent a permanent site policy change and should not be undertaken lightly. (We illustrate this process after explaining the flags.)

The flags that determine header use are listed in Table 25-4. Note that each flag name is prefixed with an H_.

Table 25-4. Header flags in conf.c

Flag

§

Versions

Description

H_ACHECK

H_ACHECK Header Flag (V5 and Later) on page 1139

V5 and later

Always process ?flags?.

H_BCC

H_BCC Header Flag (V8.7 and Later) on page 1140

V8.7 and later

Strip value from header.

H_BINDLATE

H_BINDLATE Header Flag (V8.10 and Later) on page 1140

V8.10 and later

Expand macros only at time of delivery.

H_CHECK

H_CHECK Header Flag (V5 and Later) on page 1140

V5 and later

Process ?flags?.

H_CTE

H_CTE Header Flag (V8.7 and Later) on page 1140

V8.7 and later

Is “content transfer encoding”.

H_CTYPE

H_CTYPE Header Flag (V8.7 and Later) on page 1140

V8.7 and later

Is “content type”.

H_DEFAULT

H_DEFAULT Header Flag (V5 and Later) on page 1140

V5 and later

If already in headers, don’t insert.

H_ENCODABLE

H_ENCODABLE Header Flag (V8.8 and Later) on page 1141

V8.8 and later

Field can be RFC2047-encoded.

H_EOH

H_EOH Header Flag (V5 and Later) on page 1141

V5 and later

Terminates all headers.

H_ERRSTO

H_ERRORSTO (Was H_ERRSTO) (V8.7 and Later) on page 1141

V8.1 to V8.6

An Errors-to: header.

H_ERRORSTO

H_ERRORSTO (Was H_ERRSTO) (V8.7 and Later) on page 1141

V8.7 and later

An Errors-to:-type header.

H_FORCE

H_FORCE Header Flag (V5 and Later) on page 1141

V5 and later

Insert header (allows duplicates).

H_FROM

H_FROM Header Flag (V5 and Later) on page 1141

V5 and later

Contains a sender address.

H_RCPT

H_RCPT Header Flag (V5 and Later) on page 1141

V5 and later

Contains a recipient address.

H_RECEIPTTO

H_RECEIPTTO Header Flag (V8.7 and Later) on page 1141

V8.7 and later

Header field has return-receipt information.

H_RESENT

H_RESENT Header Flag (V5 and Later) on page 1142

V5 and later

Is a Resent- header.

H_STRIPCOMM

H_STRIPCOMM Header Flag (V8.10 and Later) on page 1142

V8.10 and later

Strip comments for header checks.

H_TRACE

H_TRACE Header Flag (V5 and Later) on page 1142

V5 and later

Count these to get the hop count.

H_USER

H_USER Header Flag (V8.11 and Later) on page 1142

V8.11 and later

Came from a local user via SMTP.

H_VALID

H_VALID Header Flag (V5 and Later) on page 1142

V5 and later

Has a validated field value.

Note that there is no flag that always causes a particular header to be removed, nor is there a flag that always causes a particular header to be replaced (but see Replace headers with H_ACHECK for one way around this limitation).

H_ACHECK Header Flag (V5 and Later)

The H_ACHECK flag marks a header that should normally be discarded unless a delivery agent’s F= flag calls for its inclusion. It is usually set for the Bcc: header, which is discarded for the privacy of a blind carbon copy list, and the Full-Name: header, which is intended as a way for a user to add a full name (see the $x macro, $x on page 851) when there is no full name defined in the passwd(5) file. Note that H_ACHECK, when combined with bogus ?flags? of a header configuration file declaration, can cause appropriate headers to always be deleted or replaced. Also note that under V8 sendmail, the H_ACHECK flag alone always causes a header to be replaced.

Replace headers with H_ACHECK

Some MUAs tend to insert their own Message-ID: header (Message-ID: on page 1159). This can cause difficulty when tracing email problems because those MUA headers lack the sendmail queue identifier. At sites that have a central mail hub machine, where client machines forward all mail to the hub, you can solve this problem by redefining Message-ID: in conf.c on the clients, to delete the bogus Message-ID:, so that a good one can be generated on the hub:

"message-id",           0,
"message-id",           H_ACHECK,       ← change to this

Here, we changed the 0 flag for the Message-ID: header into an H_ACHECK flag. We do this only on the client machine versions of sendmail but not on the hub. The Message-ID: header will then be stripped from every outgoing message on every client machine and a new one will be created (if missing) on the hub.

By default, only the Full-Name:, Return-Path:, and Content-Length: headers have this flag defined. The Message-ID: header does not have this flag defined by default because the Message-ID: values are logged. By removing and regenerating Message-ID: headers, you lose the ability to track any given message on the local machine and the hub using a common Message-ID: value.[441]

H_BCC Header Flag (V8.7 and Later)

The H_BCC flag indicates that a header is either a Bcc: (Bcc: on page 1152) or a Resent-Bcc: header. The disposition of those headers is covered under the NoRecipientAction option (NoRecipientAction on page 1060).

H_BINDLATE Header Flag (V8.10 and Later)

Ordinarily, header fields that contain sendmail macros have those macros expanded (their values inserted) when the header is first processed. Some headers, such as the Return-Path: header, should not have sendmail macros in their field expanded until just before final delivery. Such headers can have the initial macro expansion skipped by specifying this H_BINDLATE header flag.

H_CHECK Header Flag (V5 and Later)

If a header definition in the configuration file begins with a ?flags? conditional, this flag is set for that header. It tells sendmail to insert this header only if one of its ?flags? corresponds to one of the delivery agent’s F= flags (?flags? in Header Definitions on page 1126). This flag must never be specified in conf.c—it is set automatically when sendmail reads H lines with ?flags? header flags.

H_CTE Header Flag (V8.7 and Later)

The H_CTE flag specifies that a header is the MIME RFC2045 content transfer encoding header (Content-Transfer-Encoding: on page 1154).

H_CTYPE Header Flag (V8.7 and Later)

The H_CTYPE flag specifies that a header is a MIME RFC2045 content-type header (Content-Type: on page 1154).

H_DEFAULT Header Flag (V5 and Later)

The sendmail program automatically sets the H_DEFAULT flag for all headers declared in the configuration file. This flag tells sendmail to macro-expand the header just before it is used. Only one of each header that is marked with this flag is allowed to exist in the headers portion of a mail message. If such a header already exists, sendmail does not add another. The H_FORCE and H_TRACE flags override this flag in that regard. This flag must never be specified in conf.c—it is set automatically by the H configuration command (Overview on page 1120).

H_ENCODABLE Header Flag (V8.8 and Later)

The H_ENCODABLE flag tells sendmail that the field part can be encoded in the way described in RFC2047. As of V8.10, this flag is defined for the Comment: and Subject: headers. Prior to that, it was defined for no headers.

H_EOH Header Flag (V5 and Later)

Headers that are marked with the H_EOH flag cause sendmail to immediately stop all header processing and treat the rest of the header lines as message body. This is useful for separating RFC2822-compliant header lines from headers created by a noncompliant network.

H_ERRORSTO (Was H_ERRSTO) (V8.7 and Later)

The H_ERRSTO (V6 and earlier) and H_ERRORSTO (V7 and later) flags specify which headers can be used for returning error notification mail. Those headers take priority over all others for that notification if the UseErrorsTo option is true (UseErrorsTo on page 1115).

H_FORCE Header Flag (V5 and Later)

The H_FORCE flag causes sendmail to always insert a header. It is used in the conf.c file with selected trace and X-Authentication-Warning: headers. It can be thought of as allowing duplicates. That is, the header will be inserted even if one like it is already present.

H_FROM Header Flag (V5 and Later)

Headers that are marked with the H_FROM flag are assumed to contain a valid sender address. This flag is intended for use in the conf.c file.

H_RCPT Header Flag (V5 and Later)

Headers that are marked with the H_RCPT flag are assumed to contain valid recipient addresses in their fields. Only headers with this flag can lead to message delivery. These addresses will be rewritten. These headers are used to determine the recipient address only if the -t command-line switch (-t on page 248) is used.

H_RECEIPTTO Header Flag (V8.7 and Later)

Some headers contain information about to whom a return receipt should be sent. Return notification is triggered by the NOTIFY=SUCCESS extension to the RCPT To: command. If the PrivacyOptions option’s noreceipts (PrivacyOptions=noreceipts on page 1068) keyword is specified, no success return notification will be sent. Beginning with V8.10, if the RrtImpliesDsn option is set, the presence of any header with H_RECEIPTTO set will cause sendmail to act as though NOTIFY=SUCCESS was specified, even if it was not.

Prior to V8.10, no headers had this flag set. For V8.10 through V8.12, the only header with this flag set is the Return-Receipt-to: header (Return-Receipt-To: on page 1165). Beginning with V8.13, the Delivery-Receipt-To: header (Return-Receipt-To: on page 1165) also has this flag set.

H_RESENT Header Flag (V5 and Later)

The H_RESENT flag tells sendmail that the header line is prefixed with the resent- string. Only headers that are marked with this flag can tell sendmail that this is a “forwarded” message. If no “forwarded” headers are found, sendmail strips any bogus resent- header lines from the message’s header.

H_STRIPCOMM Header Flag (V8.10 and Later)

The $> operator with header definitions causes the RFC2822 commentary to be removed from the field before it is passed to a rule set. The $>+ operator with header definitions causes the RFC2822 commentary to be retained. This flag is set to tell sendmail how to handle that commentary. It is not set by default for any header, but is set based on the absence of the + with the $> for header rule sets. You should never define this in conf.c.

H_TRACE Header Flag (V5 and Later)

Headers that are marked with the H_TRACE flag are counted in determining a mail message’s “hop” count. This flag is intended for use in the conf.c file. By default, only the Received:, X400-Received:, Via, and Mail-From: headers have this flag defined.

H_USER Header Flag (V8.11 and Later)

Certain headers are set by the submitting user, such as Subject:, whereas others can be added by sendmail, such as Message-Id:. Those that were supplied in the submitted message are marked with this flag so that sendmail can differentiate them from headers it generated itself.

No headers have this flag defined by default, and you should never define it in conf.c.

H_VALID Header Flag (V5 and Later)

The H_VALID flag is set and cleared internally by sendmail to indicate to itself that a particular header line has been correctly processed and can now be used as is. This flag should never be set in the conf.c file.

Headers and mc Configuration

V8 sendmail offers a number of m4 macros for use in your mc configuration file that deal directly with headers. They are shown in Table 25-5.

Table 25-5. Header-related mc macros

Macro

§

Sets what

confFROM_HEADER

From: on page 1157

Define the format for the From: header.

confRECEIVED_HEADER

Received: on page 1162

Define the format for the Received: header.

confOLD_STYLE_HEADERS

OldStyleHeaders on page 1061

Declare the OldStyleHeaders option.

confMAX_HEADERS_LENGTH

MaxHeadersLength on page 1045

Declare the MaxHeadersLength option.

confMAX_MIME_HEADER_LENGTH

MaxMimeHeaderLength on page 1047

Declare the MaxMimeHeaderLength option.

confSINGLE_LINE_FROM_HEADER

SingleLineFromHeader on page 1092

Declare the SingleLineFromHeader option.

confUSE_ERRORS_TO

UseErrorsTo on page 1115

Declare the UseErrorsTo option, which affects the Errors-To: header.

confNO_RCPT_ACTION

NoRecipientAction on page 1060

Declare the NoRecipientAction option, which affects the To:, Cc:, and Bcc: headers.

confRRT_IMPLIES_DSN

RrtImpliesDsn on page 1083

Declare the RrtImpliesDsn option, which affects the Return-Receipt-To: header.

Headers by Category

The sendmail program contains an internal list of header names that are organized conceptually into categories. The names and categories are defined in conf.c (Header Behavior in conf.c on page 1138). Each category is defined by one or more H_ flags in that file, the names of which are listed under the Flags column of all the tables that follow.

Every sendmail.cf file should have a minimal complement of header definitions. Here we present a recommendation. Don’t use this as is. The details are not generic to all versions of sendmail, nor are they appropriate for all sites:

H?P?Return-Path: $g
HReceived: $?sfrom $s $.by $j ($v/$V) id $i; $b       ← mandatory
H?D?Date: $a                                          ← mandatory
H?F?From: $q                                          ← mandatory
H?x?Full-Name: $x
H?M?Message-Id: <$t.$i@$j>                      ← mandatory
H?D?Resent-Date: $a                                   ← mandatory
H?F?Resent-From: $q                                   ← mandatory
H?M?Resent-Message-Id: <$t.$i@$j>                     ← mandatory

Each of these is described individually at the end of this chapter. Except for Received: (Received: on page 1162), none is added to any mail message that already has that particular header present.

The Return-Path: header (Return-Path: on page 1165) is removed if present, and is added only if the delivery agent for the recipient has the F=P flag present. Similarly, the Date: relies on F=D, the From: relies on F=F, the Full-Name: relies on F=x, and the Message=Id: relies on F=M.

Of those shown, only the seven indicated are truly mandatory and must be declared in every configuration file. The others are highly recommended.

Sender Headers

Certain header names are assumed by sendmail to contain information about the various possible senders of a mail message. They are listed in Table 25-6 in descending order of significance. Addresses with the H_FROM flag (H_FROM Header Flag (V5 and Later) on page 1141) are rewritten as sender addresses.

Table 25-6. Sender headers (most to least significant)

Header

§

Flags

Defined by

Resent-Sender:

Forwarding with Re-Sent Headers on page 1147

H_FROM, H_RESENT

RFC2822

Resent-From:

From: on page 1157

H_FROM, H_RESENT

RFC2822

Resent-Reply-To:

Forwarding with Re-Sent Headers on page 1147

H_FROM, H_RESENT

RFC2822

Sender:

Sender: on page 1166

H_FROM

RFC2822

From:

From: on page 1157

H_FROM

RFC2822

Apparently-From:

Apparently-From: on page 1150

n/a

Smail 3.0

Reply-To:

Reply-To: on page 1164

H_FROM

RFC2822

Disposition-Notification-To:

Disposition-Notification-To: on page 1156

H_FROM

RFC2298

Return-Receipt-To:

Return-Receipt-To: on page 1165

H_RECEIPTTO

Obsolete

Errors-To:

Errors-To: on page 1156

H_FROM, H_ERRORSTO

sendmail (deprecated)

Full-Name:

Full-Name: on page 1158

H_ACHECK

UUCP (obsolete)

When returning bounced mail, sendmail always uses the envelope sender’s address. If the special header Errors-To: appears in the message, and if the UseErrorsTo option (UseErrorsTo on page 1115) is set, a copy of the bounced mail is also sent to the address in that header.

Recipient Headers

Recipient headers are those from which one or more recipients can be parsed. Addresses in headers with the H_RCPT flag (H_RCPT Header Flag (V5 and Later) on page 1141) are rewritten as recipient addresses. When sendmail is invoked with the -t command-line switch, it gathers a list of recipients from all the headers marked with an H_RCPT flag and delivers a copy of the message to each.

The list of recipient headers used by sendmail is shown in Table 25-7.

Table 25-7. Recipient headers

Header

§

Flags

Defined by

To:

To: on page 1167

H_RCPT

RFC2822

Resent-To:

Forwarding with Re-Sent Headers on page 1147

H_RCPT, H_RESENT

RFC2822

Cc:

Cc: on page 1152

H_RCPT

RFC2822

Resent-Cc:

Forwarding with Re-Sent Headers on page 1147

H_RCPT, H_RESENT

RFC2822

Bcc:

Bcc: on page 1152

H_RCPT, H_BCC

RFC2822

Resent-Bcc:

Forwarding with Re-Sent Headers on page 1147

H_RCPT, H_BCC,H_RESENT

RFC2822

Apparently-To:

Apparently-To: on page 1151

H_RCPT

Obsolete

Identification and Control Headers

Some headers serve to uniquely identify a mail message. Others affect the way sendmail processes a mail message. The complete list of all such identification and control headers is shown in Table 25-8.

Table 25-8. Identification and control headers

Header

§

Flags

Defined by

Message-ID:

Message-ID: on page 1159

None

RFC2822

Resent-Message-Id:

Forwarding with Re-Sent Headers on page 1147

H_RESENT

RFC2822

Message:

Message: on page 1160

H_EOH

Obsolete

Text:

Text: on page 1167

H_EOH

Obsolete

Precedence:

Precedence on page 1148

n/a

All sendmails

Priority:

Priority: on page 1161

n/a

Many (maps to X.400)

Note that the Precedence: and Posted-Date: headers (discussed next) are hardcoded into sendmail rather than being declared in conf.c.

Date and Trace Headers

Date headers are used to document the date and time that the mail message was sent or forwarded. Trace headers (those with an H_TRACE header flag; H_TRACE Header Flag (V5 and Later) on page 1142) are used to determine the hop count of a mail message and to document the message’s travel from machine to machine. The list date and trace headers are shown in Table 25-9.

Table 25-9. Date and trace headers

Header

§

Flags

Defined by

Date:

Date: on page 1155

None

RFC2822

Posted-Date:

Posted-Date: on page 1161

n/a

Obsolete

Resent-Date:

Forwarding with Re-Sent Headers on page 1147

H_RESENT

RFC2822

Received:

Received: on page 1162

H_TRACE, H_FORCE

RFC2822

Via:

Via: on page 1167

H_TRACE, H_FORCE

Obsolete

Mail-From:

Mail-From: on page 1159

H_TRACE, H_FORCE

Obsolete

X-Authentication-Warning:

X-Authentication-Warning: on page 1167

H_FORCE

V8 sendmail

X400-Received:

X400-Received: on page 1168

H_TRACE, H_FORCE

IDA and V8 only

Other Headers

Other headers that you will see in mail messages are defined by the RFC2822 standard but are not otherwise internally defined by sendmail. A few of them, such as Return-Path:, should be declared in the configuration file. The others are usually inserted by MUAs. Table 25-10 lists these other headers.

Table 25-10. Other headers

Header

§

Flags

Defined by

Return-Path:

Return-Path: on page 1165

H_FORCE, H_ACHECK, H_BINDLATE

RFC2822

In-Reply-To:

In-Reply-To: on page 1158

n/a

RFC2822

References:

References: on page 1164

n/a

RFC2822

Keywords:

Keywords: on page 1159

n/a

RFC2822

Subject:

Subject: on page 1166

H_ENCODABLE

RFC2822

Comments:

Comments: on page 1152

H_FORCE, H_ENCODABLE

RFC2822

Encrypted:

Encrypted: on page 1156

n/a

RFC822

Content-Length:

Content-Length: on page 1154

H_ACHECK

SysV

MIME Headers

MIME is documented in RFC2045, RFC2046, RFC2047, RFC2048, and RFC2049. The sendmail program cares about MIME only when bouncing messages and when determining how to convert the message body between 8 and 7 bits. Those MIME headers for which sendmail contains special knowledge are shown in Table 25-11.

Table 25-11. MIME headers

Header

§

Flags

Defined by

MIME-Version:

MIME-Version: on page 1160

n/a

RFC2045

Content-Disposition:

Content-Disposition: on page 1153

n/a

RFC2183

Content-Id:

Content-Id: on page 1153

n/a

RFC2045

Content-Transfer-Encoding:

Content-Transfer-Encoding: on page 1154

H_CTE

RFC2045

Content-Type:

Content-Type: on page 1154

H_CTYPE

RFC2045

Forwarding with Re-Sent Headers

Some MUAs allow users to forward (resend, bounce, or redirect) messages to other users. For example, the mush(1) MUA forwards the current message to the user named fred with the following command:

message 1 of 3> m -f fred

Messages can also be forwarded with dist(1) from mh(1) and from within other MUAs.

When messages are forwarded, header lines that describe the forwarding user must begin with the Resent- prefix. When fred receives this message, he sees two similar header lines:

From: original-sender
Resent-From: forwarding-sender

When both the original From: and the forwarded Resent-From: appear in the same header, the Resent- form is always considered the most recent.

The sendmail program examines only a few header names to see whether a mail message has been forwarded. Those that it knows are listed in Table 25-12.

Table 25-12. Known re-sent headers

Resent- form of

Header

Resent-Bcc:

Bcc:

Resent-Cc:

Cc:

Resent-Date:

Date:

Resent-From:

From:

Resent-Message-ID:

Message-ID:

Resent-To:

To:

If sendmail finds any header with a name beginning with Resent-, it marks that message as one that is being forwarded, preserves all Resent- headers, and creates any needed ones.

Remove and Re-create the From: Header

Regardless of whether the message is forwarded, sendmail compares the sender envelope address to the address in the From: header (or Resent-From: if present). If they are the same, sendmail deletes the From: (or Resent-From:). The purpose of this deletion is to add the sender’s full name (the $x macro, $x on page 851) to the address. If the envelope and sender addresses are the same, it is safe to delete and regenerate those header lines. If the message is being forwarded, sendmail re-creates the Resent-From: header; otherwise, it re-creates the From: header (-d31.2 on page 561).

This re-creation is useful because some old versions of mh(1) added a From: header without the full name ($x). It is also useful in mail client/server arrangements in which all mail is sent to the server. Because that mail is sent with the TCP delivery agent, no $x full name is added. On the server, the From: is discarded, and there is a second chance to add the $x. However, this can happen only if the address in the envelope and the address in the From: are identical. Because the address in the envelope is surrounded with angle brackets, the address in the From: header must be as well. One way to ensure that they are the same is by defining the From: header with $g in angle brackets, as <$g> in the client’s configuration file.

Precedence

The cost of a mail message determines its ability to be sent despite a high machine load (and its position in the queue depending on the setting of the QueueSortOrder option, QueueSortOrder on page 1073). Each mail message has a precedence and a cost. The initial precedence (sometimes called class) of a mail message is defined by the optional presence of a Precedence: header line inside the message with a symbol corresponding to a value defined by the P configuration command.

For example, if your sendmail.cf file contained this line:

Pspecial-delivery=100

and your mail message header contained this line:

Precedence: special-delivery

your mail message would begin its life with a precedence class of 100. We’ll cover how this is done soon.

After the message’s initial class value is set, that value is never changed. As soon as the class is determined, the initial cost is calculated. This cost is the value that is used to determine whether a message will be sent despite a high machine load (defined by the RefuseLA option, RefuseLA on page 1078, and the QueueLA option, QueueLA on page 1072) and to determine its order in queue processing. The formula for the initial calculation is the following:

cost = nbytes - (class * z) + (recipients * y)

where nbytes is the total size in bytes of the message, recipients is the number of recipients specified in the To:, Cc:, and Bcc: header lines (after alias expansion), and z and y are the values of the ClassFactor option (RefuseLA on page 1078) and the RecipientFactor option (QueueLA on page 1072).

The Precedence: header should rarely be declared in the configuration file. Instead, it is added to messages by MUAs and by mailing-list software. If it is declared in the configuration file, it should be prefixed with an appropriate ?flag? (?flags? in Header Definitions on page 1126) so that it is inserted only for an appropriate delivery agent.

The P Configuration Command

The P configuration command must begin a line. This command is composed of four parts:

Pstring=value

The string is text, such as special-delivery. Everything between the P and the = (including any whitespace) is taken as is for string. The value is evaluated as a signed integer and can be decimal, octal (with a leading 0), or hexadecimal (with a leading 0x).

Although you can define any string you choose, only five have any universal meaning. Those five usually appear in sendmail.cf files like this:

Pspecial-delivery=100
Pfirst-class=0
Plist=-30
Pjunk=-60
Pbulk=-200

You can, of course, define your own precedence strings for internal mail, but they will be ignored (evaluate to 0) by all outside sendmail programs.

The classes junk and bulk are also recognized by many other programs. Newer versions of the vacation(1) program, for example, silently skip replying to messages that have a Precedence: header line of junk or bulk.

As a general rule, special-delivery is rarely used. Most mail has a class of first-class. Mailing lists should always have a class of list or bulk.

Because your local sendmail.cf file is where values are given to these class names, you are free to modify those values locally. The values affect only the delivery at your site.

Old versions of sendmail didn’t return errors on messages with a negative precedence. V8 sendmail does but omits the message body.

Pitfalls

  • Not all MTAs are as RFC2822-compliant as sendmail. Occasionally, headers appear that were legal under the long-time defunct RFC733. The In-Reply-To: header (In-Reply-To: on page 1158), for example, used to be a comma-separated list of addresses under RFC733 and can cause problems. Note also that RFC733 date and time syntax differs from that of RFC2822 and RFC1123.

  • When generating an Apparently-To: header, sendmail checks for the absence of only the To:, Cc:, Bcc:, and Apparently-To: headers. The H_RCPT flag (H_RCPT Header Flag (V5 and Later) on page 1141) in conf.c is ignored. V8.7 and later sendmail will produce an Apparently-To: header only if the NoRecipientAction option is set to add-apparently-to.

  • Precedence values are stored in integer variables, so care should be exercised on 2-byte integer machines to avoid having priorities wrap unexpectedly.

  • Macros are not expanded in the P command. That is, expressions such as $U do not have the desired effect. The literal text $U is wrongly listed as the name or the value.

  • The $={persistentMacros} class should not be used without first researching the macros to be included in that class. The sendmail program can be harmed by including an improper macro in that class because that macro’s value will survive queue runs. This creates a danger in the use of the H?${macro}? header expression. The only way to use a sendmail program’s internal macro in that expression is by also including that macro in the $={persistentMacros} class. If a macro is not in that class, its value will not survive queueing, and the included header might not appear when delivered from the queue.

Alphabetized Header Reference

Some header lines need to be declared in the configuration file by using the H command. Others are created internally by sendmail. Still others are created by mail MUAs. These differences are described individually with each header-line name. The following discussion of header names is in alphabetical order.

Apparently-From:

The unknown sender send mail

The Smail 3.x program (a UUCP-oriented replacement for sendmail) produces an Apparently-From: header when it is unable to find any of the official sender headers in a mail message. The address that it provides to this nonstandard header is taken from the envelope of the message.

The sendmail program, on the other hand, places the envelope sender into a From: header in this situation. If there is no envelope sender and if the sender was not specified in the command line, sendmail sets the sender to be the postmaster.

The Apparently-From: header is mentioned here only because it can appear in messages received at sites that run sendmail. It shouldn’t cause problems because a good sender address still appears in the SMTP envelope.

The Apparently-From: header should never be declared in the configuration file and should not be added to conf.c.

Apparently-To:

When the message lacks a recipient sendmail

If the header of a mail message lacks recipient information (lacks all of the To:, Cc:, and Bcc: header lines), sendmail adds an Apparently-To: header line and puts the recipient’s address from the envelope into the field of that line. This behavior is hardcoded into pre-V8.7 sendmail, but beginning with V8.7, it can be tuned with the NoRecipientAction option (NoRecipientAction on page 1060).

The Apparently-To: header name is not defined in RFC2822. It is added by pre-V8.7 sendmail because RFC2822 requires at least one To: or Cc: header, and neither is present.

RFC2821 specifically recommends against the use of the Apparently-To: header, so that header should never be defined in the configuration file.

Auto-Submitted:

Why the bounce sendmail

When a message is returned because of an error or because a return receipt was requested, V8 sendmail adds an Auto-Submitted: header. This header describes the reason for the return:

Auto-Submitted: auto-generated (reason)
Auto-Submitted: auto-replied (reason)V8.12 and later

The reason can be one of four things. It can be warning-timeout if the message has reached its Timeout.queuewarn option threshold (Timeout on page 1097). It can be postmaster-warning if the failure was delivered to the postmaster as a result of a problem that the postmaster should fix, such as an MX configuration error. It can be return-receipt if the message was returned because of a Return-Receipt-To: header (Return-Receipt-To: on page 1165) or a DSN NOTIFY=SUCCESS request (RFC1891). Finally, it can be failure for any other reason.

In all instances, sendmail also adds a Subject: header that contains a generic bounce message.

The Auto-Submitted: header should never be defined in the configuration file.

Bcc:

Blind carbon copy RFC2822

A blind carbon copy is a copy of the mail message that is sent to one or more recipients without the knowledge of the primary recipients. Primary recipients are listed in the To: and Cc: lines. When there are multiple blind carbon copy recipients, knowledge of each other is also hidden.

When run with a -t command-line switch (to gather recipients from the headers), the sendmail program achieves this end by saving a list of all the blind carbon copy recipients, deleting the Bcc: header line, and then delivering to each blind carbon copy recipient. (See the Apparently-To: header.)

The Bcc: header should never be declared in the configuration file.

The field for the Bcc: header must contain one or more properly formed addresses. Where there is more than one, each should be separated from the others by commas.

Cc:

Carbon copy RFC2822

The Cc: header is one of a few that specify the list of primary recipients. The sendmail program treats the Cc: header no differently from the way it treats the To: header. From the user’s point of view, the Cc: header implies that there are recipients to whom an informational copy of the message was supplied.

The Cc: header should never be declared in the configuration file.

The field for the Cc: header must contain one or more properly formed addresses, where multiple addresses must be separated by commas.

Comments:

Header commentary RFC2822

The Comments: header is used to place explanatory text into the header portion of an email. The field portion of the Comments: header can contain arbitrary text.

One possible use for a Comments: header would be to notify recipients that one person is replying to mail for another:

Comments: Ben is in France for the next month or
          so gathering information for the meeting.
          I am handling his mail while he is away.
   ↑
   whitespace

The Comments: header should rarely be declared in the configuration file. If it is, it should be prefixed with appropriate ?flags?. For example:

H?B?Comments: Local delivery is experimentally being handled
       by a new program. Complaints to root.

This comment is included only in headers that are delivered via the local delivery agent because that delivery agent is the only one to include the F=B flag:

Mlocal, P=/bin/mail, F=rlsDFMmnPB, S=10, R=20, A=mail -d $u

This declaration causes the new Comment: header to be added to the mail message.

Content-Description:

Description of MIME message or part RFC2145

The MIME Content-Description: header describes the content of the MIME message, or in a multipart MIME message the content of a part. The value portion of this header is unstructured text. For example, a MIME-encapsulated image might contain this header:

Content-Description: Your cousin's new son's picture taken at the hospital.

Content-Disposition:

How MIME contents should be disposed RFC2183

The MIME Content-Disposition: header specifies how a MIME attached file should be handled. The form of the Content-Disposition: header looks like this:

Content-Disposition:  type; parameter=value ...

Here, the value for this header is a sequence of one or more equates, each separated from the others by a semicolon and one or more space or tab characters. The legal parameters are shown in Table 25-13.

Table 25-13. Content-Disposition: parameters

Parameter

Description of value

filename

The name of the file into which to save the contents. This can be a full path specification. In general, automatically honoring this equate represents a risk.

creation-date

The original time and date the content was created.

modification-date

The time and date the content was last modified.

read-date

The time and date the content was last read.

size

The size in bytes of the content.

In general, the Content-Disposition: header should be advisory.

Content-Id:

A MIME part content identifier RFC2392

The MIME Content-Id: header obeys the same rules for its value as does the Message-Id: header (Message-ID: on page 1159). The difference is that the Message-Id: header identifies the entire email message, whereas the Content-Id: header identifies only a given part of a MIME message.

Content-Length:

The size of the body of the message System V Release 4

The Content-Length: header describes the exact size of the body of a message. The size is always a decimal expression of the number of bytes occupied by the body:

Content-Length: 5678

It is used by some MUAs to find the end of the message in a large file of many messages. It is always created or added by MUAs or delivery agents and never by MTAs. It should never be declared in the configuration file.

Content-Transfer-Encoding:

Auxiliary MIME encoding RFC2045

The MIME Content-Transfer-Encoding: header describes what auxiliary encoding was applied to the message body to allow it to pass through email transport mechanisms that might have data or character set limitations. Specifically, RFC821 requires message bodies to contain only 7-bit data. To transport 8-bit data (such as images and sounds) unless 8-bit is negotiated, it is necessary to convert that data to 7 bits. The Content-Transfer-Encoding: header specifies precisely how that conversion was done:

Content-Transfer-Encoding: how

Here how is defined by RFC2045 to be one of the following: base64 (RFC2045), quoted-printable (RFC2045, EightBitMode on page 1025), 8bit (meaning that the message body contains unencoded 8-bit data in line length suitable for SMTP transport), 7bit (the message body contains 7-bit, SMTP-compliant data), or binary (the message body contains 8-bit data in a form that is completely unsuitable for SMTP transport).

See the EightBitMode option (EightBitMode on page 1025) for a description of how V8 sendmail converts between 8- and 7-bit data. The Content-Transfer-Encoding: header should never be declared in the configuration file.

Content-Type:

The nature of the body of the message RFC2045

The Content-Type: header describes the nature of the body of a mail message. In the absence of such a header, the body is presumed to be composed of ASCII characters that have their high (most significant) bits turned off. One possible setting for this header might look like this:

Content-Type: text/plain; charset=ISO-8859-1

This header says that the body is plain text (i.e., contains no markup language) and is represented in the ISO-8859-1 character set.

This header is usually created by the originating MUA. It should never be declared in the configuration file of pre-V8.7 versions of sendmail. Beginning with V8.7, the charset for 8- to 7-bit MIME conversions can be declared with the DefaultCharSet option (DefaultCharSet on page 1000).

When bouncing mail, V8 sendmail creates a MIME-compliant message and includes a Content-Type: header such as this:

Content-Type: multipart/mixed; boundary="boundary"

If sendmail was compiled to include DSN support (DSN on page 111), the Content-Type: header will look like this:

Content-Type: multipart/report; report-type=delivery-status;
        boundary="boundary"

Date:

The origin date RFC2822

The Date: header specifies the date and time that the mail message was originally sent. All mail messages must include this header line. Consequently, the Date: header must be declared in the configuration file like this:

H?D?Date: $a

The $a macro ($a on page 802) is mandatory in the field for this header. The value in $a is the current time in RFC2822 format. (See Support SMTP AUTH in RFC2822 and Section 5.2.14 in RFC1123.) Only the $a macro should be used with the Date: header because it is the only one that is guaranteed to contain the current date and time in RFC2822 (and RFC1123) format.

The ?D? flag is always included with the Date: declaration in the configuration file. All the standard delivery agents always include an F=D flag (F=D on page 769). The ?D? allows custom delivery agents to be designed that do not need a Date: header.

Delivery-Receipt-To:

Like the Return-Receipt-To: header Sun Internet Mail System

See the Return-Receipt-To: header (Return-Receipt-To: on page 1165).

Delivered-To:

Mark a mailing list expansion qmail

The qmail program uses a Delivered-To: header to trace all the alias and mailing list expansions through which an email message passes. This is similar to the way Received: headers are used to trace machine hops. When qmail expands a mailing list, it adds a Delivered-To: header to the top of the message:

Delivered-To: list@host

If an identical header is already present, qmail bounces the message. This prevents several kinds of mail loops. (Note that the SmartList program supports an X-Loop: header with the same function.)

The Delivered-To: header should never be declared in the configuration file.

Disposition-Notification-To:

Final message disposition RFC2298

Even after a message is delivered to the final recipient, later recipient actions can alter the eventual disposition of that message. The recipient can choose to delete the message without reading it, read the message but not reply to it, forward the message, or do any number of other things to it. The Disposition-Notification-To: header was devised as a way to notify the sender about the ultimate disposition of the message. This header is advisory only, not mandatory, and is used like this:

Disposition-Notification-To: 1#address

Here, the 1# is literal. The domain part of the address is compared to the domain part of the address in the Return-Path: header (Return-Path: on page 1165), and if they differ, or if the Return-Path: header is absent, no disposition notice is sent. If the two domains are the same, and if the recipient allows the response, notification of the message disposition is mailed back to the address using a special format.

See RFC2298 for a complete description of this header and the methods used to convey disposition notification.

The Disposition-Notification-To: header should never be declared in the configuration file.

Encrypted:

Message is transformed RFC822

The Encrypted: header is used to describe a translation that has been performed on the body of the mail message. Although encryption is implied, other forms of translation, such as compression and uuencode(1), are perfectly legal.

The sendmail program ignores the Encrypted: header. This header is intended for use by MUAs. Unfortunately, most (if not all) Unix MUAs also ignore this header. The form for the Encrypted: header is:

Encrypted: prog key

The field contains one mandatory item, the prog, and one optional item, the key. The prog is the name of the program that was used to transform the message body. The optional key is a decryption key.

If translating the message body into a different form, be aware that many versions of sendmail strip the eighth bit from all bytes of the body during transmission.

The Encrypted: header is deprecated and was dropped from RFC2822. The Encrypted: header should never be declared in the configuration file.

Errors-To:

Error notification redirect sendmail, deprecated

Ordinarily, errors are bounced to the envelope sender. The Errors-To: header specifies the address, or addresses, to which sendmail should send additional notification of delivery errors.

The Errors-To: header is intended for use by mailing lists to prevent errors in a list from being rebroadcast to the list as a whole. For example, consider the mailing list allusers. Mail that is sent to this list should contain the following header lines:

To: allusers
From: allusers-submit
Errors-To: allusers-errors

The From: header allows reply mail to be submitted for distribution to the list. The Errors-To: header causes error notification to be sent to allusers-errors so that the maintainer can fix any errors in the list. The original sender also gets error notification unless the mailing list software represents the maintainer in the envelope (Reply Versus Bounce on page 492).

Under SunOS and V8 sendmail, the Errors-To: header is flagged in conf.c with the H_ERRORSTO header flag (H_ERRORSTO (Was H_ERRSTO) (V8.7 and Later) on page 1141). This allows other headers to be declared in that file as error redirect headers. Under pre-V8 SunOS sendmail, the Errors-To: header is ignored if the error mode set by the ErrorMode option is m (ErrorMode=m on page 1029).

Under V8 sendmail, the Errors-To: header is ignored unless the UseErrorsTo option (UseErrorsTo on page 1115) is true. It does this because the Errors-To: header violates RFC1123. Errors-To: was needed only to take the place of the envelope sender in the days when most Unix delivery agents couldn’t differentiate between header and envelope.

The Errors-To: header should never be declared in the configuration file.

From:

The sender RFC2822

The From: header lists the address of one or more senders, where each sender address can be in one of four legal forms:

address
 <address>
Full Name <address>
address (comment)

When the From: header lists multiple senders (in the sense that there can be multiple authors) each must be separated from the others by commas:

From: address, address

Here, address specifies sender mailboxes, and each can be in any of the four basic forms shown earlier. When multiple senders (authors) are in the From: header, the presence of the Sender: header (Sender: on page 1166) is mandatory and must show the address of the agent responsible for actual transmission. When a single author is in the From: header, and when the author and transmitter differ, the Sender: header must show the address of the actual transmitter. When author and transmitter are the same, the Sender: header can be omitted.

A From: header must be declared in the configuration file, and its field is composed of the $x ($x on page 851) and $g ($g on page 824) macros. For example:

H?F?From: $?x$x <$g>$|$g$.

$g contains the official return address of the sender. $x contains the full name for the sender. $x can be undefined for some addresses, so it should be wrapped in the $? and $. conditional operators (Macro Conditionals: $?, $|, and $. on page 794).

The From: header must be prefixed by the ?F? flag because all the traditional delivery agents use the F=F flag (F=F on page 771) to force inclusion of that header. Use of the ?F? flag allows new delivery agents to be written that don’t require the From: header.

The resent- form of the From: header must also be declared in the configuration file:

H?F?Resent-From: $?x$x <$g>$|$g$.

This ensures that every mail message has a sender, even if the mail message has been re-sent.

Note that sendmail does not add the From: header or its resent- form if a From: header already exists in the header portion of the mail message. A possible exception occurs if the envelope sender is identical to the address in the From: header. In that instance, the From: header is discarded and a new one is created (Remove and Re-create the From: Header on page 1148).

Full-Name:

The sender’s full name sendmail

The Full-Name: header is used to list the sender’s full name if it is known. The field for this header can be arbitrary text but is usually the value in the $x macro ($x on page 851):

H?x?Full-Name: $x
H?x?Full-Name: (User names hidden for security)

The Full-Name: header should be prefixed with the ?x? flag so that selected delivery agents can require inclusion of that header. This heade0 Early versions of UUCP could not accept full names in From: header lines:

From: host!user ( full name )     ← did not work for early UUCP

The Full-Name: header can be specified in the configuration file. If this header is already in the mail message, sendmail does not replace it.

In-Reply-To:

Identify previous correspondence RFC2822

The In-Reply-To: header is used to identify previous correspondence that the current message is in reply to. This header is generated by MUAs, not by sendmail. Prior to RFC2822, the field for this header was arbitrary text with one restriction. If that text included the message identifier, that identifier had to be enclosed in angle brackets (< and >) and had to adhere to the format for all message identifiers.

Beginning with RFC2822, the In-Reply-To: header can contain only message identifiers, each surrounded by angle braces, and each separated from the next by a comma.

A typical use of the In-Reply-To: header might look like the following:

In-Reply-To: <847.193925.780455@hostA.com>, <1021169802.330@HostB.co.th>,
       <200106020731.BAA20313@HostC.br.ca>
   ↑
   whitespace

The In-Reply-To: header should never be declared in the configuration file.

Keywords:

Index to contents RFC2822

The Keywords: header is used to list significant words from the body of the mail message that aid in the indexing of its contents. This header is never added by sendmail. Although some MUAs can create this header, it is usually created by Usenet news-posting programs.

The field for the Keywords: header is arbitrary text. This header should never be declared in the sendmail configuration file.

Mail-From:

Synonym for Received: Obsolete

The Mail-From: header is not defined by any of the RFCs and is rarely seen in message headers. The sendmail program defines it internally as a synonym for the Received: header. The Mail-From: header is obsolete.

Message-ID:

Unique identifier for message RFC2822

The Message-ID: header is used to uniquely identify each mail message. This header must be declared in the configuration file. The field for this header must be an expression in the syntax of a legal address enclosed in angle brackets (< and >). The address must be composed of elements that create an identifier that is truly unique worldwide. The Message-ID: header is declared in the configuration file:

H?M?Message-Id: <$t.$i@$j>

Here, the field is an address of the form identifier@domain, which is enclosed in angle brackets. The $t macro ($t on page 846) is an integer representation of the current time to the nearest second. The $i macro ($i on page 826) is the unique queue identifier that is used to identify this message locally. The $j macro ($j on page 830) is the fully qualified domain name of the local host. The Message-ID: header as it might appear in an actual mail message would look like this:

Message-Id: <200210141542.g9EFg2bb006638@nic.cerf.net>

The Message-ID: header should be prefixed with a ?M? flag so that it is inserted only into headers of messages whose delivery agents have the F=M flag set. The standard delivery agents include this flag.

The resent- form of the Message-ID: header must also be declared in the configuration file:

H?M?Resent-Message-Id: <$t.$i@$j>

This ensures that every mail message has a message identifier even if the message is forwarded.

Note that sendmail does not add a Message-ID: header or its Resent- form if a Message-ID: header already exists in the header portion of a mail message. Furthermore, the Resent- form is added only if sendmail determines that the message is a re-sent message.

Also note that you should never try to replace an existing Message-ID: header with one of your own. This could result in the loss of important information needed to trace the origin of a message (but see also H_ACHECK Header Flag (V5 and Later) on page 1139).

As of V8.13, an mc macro makes it much easier to define a new value for the Message-Id: header:

define(`confMESSAGEID_HEADER', `newvalue')

Here newvalue is the address part for the header. Be sure the newvalue address part is enclosed in angle braces because sendmail will not add them if you omit them.

As of V8.13, when a Message-Id: header is found in the message, sendmail assigns its value to the ${msg_id} defined macro (${msg_id} on page 834).

Message:

Marks end of headers sendmail

The Message: header is used to mark an early end to a mail message’s headers. When sendmail finds this header, it immediately stops gathering the message’s header lines and treats the rest of the header as the start of the message body. This header is useful for including non-Internet headers in the header portion of a mail message. For example:

To: george@wash.dc.gov (George Washington)
Subject: Re: More text
Date: Sun, 6 May 2001 17:32:45 EDT
Message-Id: <200105061723.f46NIY7f028392@wash.dc.gov>
Received: by wash.dc.gov (4.1/1.12 $)
        id AA01513; Sun, 6 May 2001 17:32:45 EDT
From: Ben Franklin <ben@philly.dc.gov>
Message:
ROUTED BY BITNET/CO=US/ROUTE=INTERNET/
FORMAT OF MESSAGE /LANG=USENGLISH/FORM=PLAINTEXT/

Here, the last two header lines are non-Internet headers that might confuse some programs. But the Message: header that precedes them tells sendmail to treat them as message body, and problems are avoided.

Note that Message: is not defined by any RFC but is a convention that is shared by all versions of sendmail and a few other MTAs. It is included in sendmail for backward compatibility with a few old messaging systems, so it should be considered deprecated. The Message: header should never be declared in the configuration file, and should probably never be used.

MIME-Version:

This message conforms to MIME standards RFC2045

MIME is documented in RFC2045, RFC2046, RFC2047, RFC2048, and RFC2049. The sendmail program cares about MIME only when bouncing messages and when determining how to convert the message body between 8 and 7 bits. If the SendMimeErrors option (SendMimeErrors on page 1086) is set, V8 sendmail includes the following header in all returned (bounced) mail:

MIME-Version: 1.0

This is hardcoded into sendmail. See the SendMimeErrors option for further details about this header.

The MIME-Version: header should never be declared in the configuration file.

Posted-Date:

Date submitted sendmail

The Posted-Date: header is used by some old Usenet news software and some mailing-list software to indicate the date and time that a mail message was posted (submitted for distribution). The Date: header, on the other hand, shows when the message was mailed. In actual practice, the two usually show the same date and time.

When sendmail tries to determine the originating date of a mail message, it first looks for a Posted-Date: header. If one is found, it uses that date. Otherwise, it uses the date from the Date: header. Whichever is used, the result is stored into the $a macro ($a on page 802).

The Posted-Date: header is not a part of the RFC2822 standard, so it should not be declared in the sendmail configuration file.

Precedence:

Set ordering in queue sendmail

The Precedence: header, when the QueueSortOrder option (QueueSortOrder on page 1073) is appropriately set, is used internally by sendmail to order the processing of messages in its queue. A full description of the possible field values for this header is given in The P Configuration Command on page 1149. The effect of those values on ordering the queue is described in How the Queue Is Processed on page 426.

The Precedence: header should never be declared as an H line in the configuration file. However, P precedence lines should be declared in that file.

Priority:

Determine timeouts in the queue sendmail

Mail messages can be placed into the queue either intentionally or because they could not be delivered immediately. Once they are in the queue, two time periods come into play. First is the period of time that the message should remain in the queue before a warning is issued to the sender. Second is the total period of time that the message should remain in the queue before it is bounced as a failed message.

Beginning with V8.7 sendmail, it is possible to tailor these intervals on the basis of three distinct priorities of mail. The new Priority: header tells sendmail which priority a message possesses:

Priority: pri

Here, pri can have one of three possible values: urgent, normal, and non-urgent. These values correspond directly to the priorities specified by the Timeout.queuewarn option (Timeout.queuewarn (V8.7 and later) on page 1107) and Timeout.queuereturn option (Timeout.queuereturn (V8.7 and later) on page 1106):

O Timeout.queuereturn.urgent=1d
O Timeout.queuereturn.normal=2d
O Timeout.queuereturn.non-urgent=4d

Here, a Priority: header of normal will cause the message containing it to bounce after it has remained in the queue for two days.

The Priority: header should never be declared in the configuration file.

Received:

Trace routing of mail RFC2822

The Received: header is used to record information about every site a mail message passes through on its way to ultimate delivery. First this header is inserted by the original sending site, then another is added by each site that the message passes through, including the site performing final delivery. Each new header is added to the list of Received: headers, forming a chronological record (reading bottom up through the headers) of how the mail message was handled.

The contents of the Received: header’s field are narrowly defined by RFC2821. The field’s defined form looks like this:

Received: "from" host "by" host ["via" atom] ["with" atoem]
       ["id" string] ["for" addr] ";" date
   ↑
   whitespace

The field is composed of six items that can be split over multiple lines by using whitespace to indent the second line. Each item is composed of two parts: a word (shown in quotation marks) and a value. Optional items are indicated by the enclosing square brackets in the previous example, but those brackets are not a part of the item and must be excluded when the item is actually used. Items, when present, must be in the following order:

from

Full canonical name of the sending host (required).

by

Full canonical name of the receiving host (required).

via

Physical network that was used to transmit the message, such as TCP, INTERNET, JANET, or XNS (optional).

with

Protocol used to receive the message, such as ESMTP or SMTP (optional).

id

Identifier assigned by the local host, such as the Message-Id: header’s value (optional).

for

Initial, untranslated address of the recipient—when there is a single recipient, sendmail always includes this item (optional).

;date

Date this message was received (required).

The Received: header must be declared in the configuration file. It is a mandatory header, so it should never be prefixed with ?flags?. The typical declaration of this header has evolved from version to version of sendmail (some of these examples have been wrapped to fit the page):

V8.12:
HReceived: $?sfrom $s $.$?_($?s$|from $.$_)
        $.$?{auth_type}(authenticated$?{auth_ssf} bits=${auth_ssf}$.)
        $.by $j ($v/$Z)$?r with $r$. id $i$?{tls_version}
        (version=${tls_version} cipher=${cipher} bits=${cipher_bits}
        verify=${verify})$.$?u                        ← line wrapped to fit page
        for $u; $|;
        $.$b
V8.11:
HReceived: $?sfrom $s $.$?_($?s$|from $.$_)
        $.$?{auth_type}(authenticated$?{auth_ssf} (${auth_ssf} bits)$.)
        $.by $j ($v/$Z)$?r with $r$. id $i$?{tls_version}
        (using ${tls_version} with cipher ${cipher} (${cipher_bits} bits)
        verified ${verify})$.$?u                      ← line wrapped to fit page
        for $u; $|;
        $.$b
V8.10:
HReceived: $?sfrom $s $.$?_($?s$|from $.$_)
        $.$?{auth_type}(authenticated)
        $.by $j ($v/$Z)$?r with $r$. id $i$?u
        for $u; $|;
        $.$b
V8.9:
HReceived: $?sfrom $s $.$?_($?s$|from $.$_)
        $.by $j ($v/$Z)$?r with $r$. id $i$?u
        for $u; $|;
        $.$b

The complexity of the Received: header has changed mostly due to the addition of authentication information. Despite those additions, however, the following seven key items remain common among all the versions:

$?sfrom $s $.

If the $s macro contains a value, the word from and that value are inserted into the header. The $s macro ($s on page 844) contains the full canonical name of the sender’s host.

$?_($?s$|from $.$_) $.

This is a nested conditional. If the $_ macro contains a value, the parentheses and all the information inside them are inserted into the header. If the $_ macro lacks a value, this information is not inserted into the header.

Inside the parentheses the value of $_ is inserted into the header. Another conditional expression determines whether the $_ just inserted should also be prefixed with the word from. If the $s macro lacks a value, the word from is inserted in front of the $_. The $_ macro contains the RFC1413 identd(8) identity of the connecting host and any IP routing information ($_ on page 801).

by $j ($v/$Z)

The $j macro contains the full canonical name of the local host. The parentheses surround a comment that is formed from $v ($v on page 849), the version of the sendmail program, and $Z ($Z on page 853), the version of the configuration file.

$?r with $r$.

If the $r macro contains a value, the word with followed by the value of $r are inserted into the header. The $r macro ($r on page 842) contains a string that indicates the protocol used to receive the message (such as SMTP or ESMTP).

id $i

The $i macro contains the identifier created by sendmail to uniquely identify this mail message at this host ($i on page 826).

$?u for $u$.

If the $u macro contains a value, the word for followed by the value of $u is inserted into the header. The $u macro ($u on page 848) contains the recipient’s username.

; $b

The $b macro contains the current date and time in RFC2822 format ($b on page 807).

The Received: declaration shown earlier is the one typically used by most sites running V8 sendmail.

References:

Reference to original message RFC2822

The References: header is used by mail-reading programs to include a reference to the original message in replies. This header must have as its value a copy of the original Message-ID: header field:

References: <200210141542.g9EFg2bb006638@wash.dc.gov>

Notice that the message identifier is wrapped in angle brackets, which causes it to look like an address.

The References: header should never be declared in the configuration file.

Reply-To:

Alternative reply address RFC2822

The Reply-To: header requests that replies to messages go to an address that is different from that of the original sender. This header is usually inserted by mailing-list software, where the From: is the address of the author of the message and the Reply-To: is the address of the list.

The field for the Reply-To: header must obey the same rules as those for the From: header’s field. One example of the use of this header might look like this:

From: bob@list.server.domain
Reply-To: mailinglist@list.server.domain

The Reply-To: header should never be declared in the configuration file.

Return-Path:

Return address of sender RFC2822

The Return-Path: header is intended to show the envelope address of the real sender as opposed to the sender used for replying (the From: and Reply-To: headers). In posting Usenet news, for example, the Return-Path: shows “news” and the From: shows the address of the posting user. But in general, Return-Path: should never be used for replying to mail. It is intended to be used solely for notification of delivery errors.

There must be only one Return-Path: header in any mail message, and it should be placed there by the site performing final delivery. This header should be declared in the configuration file like this:

H?P?Return-Path: $g

The ?P? flag ensures that only delivery agents that perform final delivery insert this header. Those delivery agents are usually prog and local, which usually contain an F=P delivery agent flag.

The $g macro ($g on page 824) contains as its value the address of the sender relative to the recipient.

Unfortunately, two circumstances can cause the Return-Path: header to contain incorrect information. First, the message might arrive at your site with this header already there. If this happens, that wrong header will normally not be replaced. You can, however, define H_ACHECK (Replace headers with H_ACHECK on page 1139) in conf.c and cause this header to be replaced even if it is already in the message.

The second problem stems from the fact that final delivery might not really be final. The local delivery agent program might be something such as procmail(8), which allows mail to appear to be locally delivered, while also allowing users to run shell scripts that can forward their mail to another site.

To minimize these problems, always declare the Return-Path: header with the proper ?flags? in the configuration file. Doing this ensures that it will be inserted when legal and that the address your site places in it is usually correct.

Return-Receipt-To:

Verify delivery sendmail

The Return-Receipt-To: header should never be declared in the configuration file and, in fact, should rarely be used at all. It is not intended as a routine delivery-verification mechanism, but rather is intended for occasional use in debugging delivery problems. It is especially dangerous when used in outgoing mailing-list mail because it can cause an avalanche of returned mail and can possibly bring a host to its knees.

Beginning with V8.6 sendmail, a receipt is sent when the mailing list is first expanded, and the Return-Receipt-To: header is removed before forwarding the message to the list.

Beginning with V8.7 sendmail, processing of all Return-Receipt-To: headers can be skipped by specifying noreceipts with the PrivacyOptions option (PrivacyOptions on page 1065). Return notification is triggered by a NOTIFY=SUCCESS extension (“-N” in ) to the RCPT To: command. If the PrivacyOptions option’s noreceipts (PrivacyOptions=noreceipts on page 1068) keyword is specified, no success return notification will be sent.

Beginning with V8.10, if the RrtImpliesDsn option (RrtImpliesDsn on page 1083) is set, the presence of a Return-Receipt-to: header will cause sendmail to act as though NOTIFY=SUCCESS was specified, even if it was not. In this instance, the value of the Return-Receipt-to: header is ignored. Other than with the RrtImpliesDsn option, the Return-Receipt-to: header is otherwise ignored.

Beginning with V8.13, the Delivery-Receipt-To: header under SIMS (Sun Internet Mail System) is treated the same as this Return-Receipt-To: header. That is, sendmail now converts it to a DSN reply.

Sender:

The real sender RFC2822

The Sender: header is like the From: header. But whereas the From: header shows the address of one sender (RFC822) or many authors (RFC2822), the Sender: header shows the address of the actual sender. For example, an assistant can mail a letter for the boss using the boss’s account. The boss’s address is in the From: header, and the assistant’s address is in the Sender: header. See the From: header (From: on page 1157) for a description of the syntax and rules for this Sender: header.

Newer MUAs allow the user to create a custom Sender: header. The Sender: header should never be declared in the configuration file.

Subject:

Topic of the message RFC2822

The Subject: header can be included in mail messages to give the topic of the message. Most user mail-reading programs display the arbitrary text that forms the field of this header when listing received messages. Although such text can legally extend over multiple indented lines, most mail-reading programs recognize only the first such line:

Subject: About yesterday's meeting, I had some second
       thoughts about why the shape of the bonnet should
       remain so sharply curved at the ends.
   ↑
   whitespace

This would be displayed by the mailx(1) program in truncated form as:

14   gw@wash.dc.gov Fri Aug  7 12:57  22/770 "About yesterday's meeting"

The Subject: header is not used by sendmail, but it is often wrongly (albeit harmlessly) included in the configuration file:

HSubject:            ← this actually does nothing

Text:

A synonym for Message: sendmail

The Text: header is the same as the Message: header. Both cause all lines that follow in the header portion of a mail message to be treated as the message body.

The Text: header should never be declared in the configuration file, and should probably never be used.

To:

The primary recipients RFC2822

The To: header lists one or more of the recipients of the mail message. Other headers, such as Cc:, also list recipients.

If the header of a mail message lacks recipient information (To:, Cc:, and Bcc: header lines), pre-V8.7 sendmail added an Apparently-To: header line and put the recipient’s address from the envelope into the field of that header. Beginning with V8.7, the way a message with no recipients is handled is determined with the NoRecipientAction option (NoRecipientAction on page 1060).

Via:

An unofficial trace header Obsolete

The Via: header is not defined by RFC2822 but occasionally appears in mail messages that sendmail needs to process. It is used by a few other networks to mark a mail message’s transit through a forwarding host. It is an early, and now obsolete, version of the Received: header. The sendmail program counts the Via: header when determining the hop count but has no other use for it.

The Via: header should never be declared in the configuration file.

X-Authentication-Warning:

Notification of security matters V8 sendmail

If the PrivacyOptions option (PrivacyOptions on page 1065) is declared with authwarnings, V8 sendmail inserts a special header line for possible security concerns. That header line looks like this:

X-Authentication-Warning: host: message

Here, host is the canonical name of the host that inserted this header. The message is one of the following:

Processed by user with -C file

An attempt was made by a user other than root to run sendmail with the -C command-line switch. That switch caused sendmail to read file in place of the system sendmail.cf file.

User set sender to other using -f

A user or program’s user identity used the -f command-line switch to change the identity of the sender to other (and user was not listed with the T configuration command). This can be legitimate when the user is uucp or daemon. It can also be legitimate when the user is sending to some mailing lists (Security Features on page 173). Such a warning can also indicate that someone is trying to forge mail.

User owned process doing -bs

A user or program’s user identity used the -bs command-line switch to make sendmail receive a mail message via its standard input/output using the SMTP protocol (and user was not listed with the T configuration command). This parallels network notification set up by defining IDENTPROTO when compiling sendmail and by use of the $_ macro ($_ on page 801) in Received: headers.

Processed from queue dir

A user other than root used the -oQ (or similar) switch (QueueDirectory on page 1070) to process mail from a queue directory (dir) that was different from the one specified with the QueueDirectory option in the configuration file. The sendmail program can run as an ordinary user because this or some other command-line switch caused it to give up its special privileges.

Host name1 claimed to be name2

In the HELO message of an SMTP conversation, the remote host name1 specified its canonical name as name2, and the two didn’t match. This always indicates a problem. Either the remote host is misconfigured (a bad value in $j, $j on page 830), the DNS information for that host is wrong, or someone is trying to spoof the local sendmail.

Host name didn’t use HELO protocol

Every SMTP conversation for transfer of mail must start with the HELO (or EHLO) greeting. If a MAIL command was first instead, this header is inserted in the incoming message. The most likely cause of a missing HELO or EHLO is the mistake of someone attempting to carry on an SMTP conversation by hand.

X400-Received:

Received via X.400 X.400

The X400-Received: header is added by IDA sendmail to document receipt of a mail message from an X.400 network. This header is used by both IDA and V8 to count the number of forwarding sites when computing the hop count of a mail message.

The X400-Received: should never be declared in the configuration file.



[435] * Prior to V8 sendmail, all headers were converted to lowercase and stored. Later, when mail was sent, they were then capitalized in a way similar to that of proper names, in which the first letter of each word was capitalized.

[436] * Beginning with V8.10, the field can also contain a call to a rule set for special processing (Rules Check Header Contents on page 1130).

[437] This discussion is adapted from RFC2822.

[438] * Note that the backslash itself cannot appear within full quotation marks.

[439] * Warnings would also be syslog’d complaining about unbalanced angle braces.

[440] * But be aware that header checks are also performed for command-line submitted mail. If a program such as cron(8) or lpd generates mail lacking a Message-Id: header, that mail will also be rejected. So, avoid placing rules such as these in your submit.cf file.

[441] * Some mail-sending programs also use Message-ID: headers of their own design to track messages.