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.
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:fieldThe 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 : field ↑ from 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 set ← see §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
↑
tabWhen 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
↑
tabThe \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.
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.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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.
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]
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).
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.
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 (\).
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 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.
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 legalInstead, the atom to the left of the @ must be isolated with
quotation marks:
"Full Name"@domain ← legalRecall 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"
↑
whitespaceThe 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 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)
↑
whitespaceA 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 ;-\))
↑
noteMany 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.
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.
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:fieldThe ? 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 spaceIf 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.
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: value ← all versions H${macro name}X-Added-Header: value ← V8.10 and V8.11 only H?${macro name}?X-Added-Header: value ← V8.12 and later H?${macro name}flags?X-Added-Header: value ← V8.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.
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: 1234abcd5678Note 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.
Recall that a header line declaration looks like the following:
H?flags?name:fieldHere, 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 set ← don'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 $* $: OKIn 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.
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
↑
noteBy 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.”
Recall that header values can be passed to
rule sets using the $> and $>+ operators:
Hname: $> rule set Hname: $>+rule set← don'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.
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.
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.
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.
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.
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 HeaderThe 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.
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_.
|
Flag |
§ |
Versions |
Description |
|
H_ACHECK |
H_ACHECK Header Flag (V5 and Later) on page 1139 |
V5 and later |
Always process |
|
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 |
|
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 |
|
H_ERRORSTO |
H_ERRORSTO (Was H_ERRSTO) (V8.7 and Later) on page 1141 |
V8.7 and later |
An |
|
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 |
|
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).
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.
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 thisHere, 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]
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).
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.
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.
The H_CTE flag specifies that a header is the MIME RFC2045 content transfer encoding header (Content-Transfer-Encoding: on page 1154).
The H_CTYPE flag specifies that a header is a MIME RFC2045 content-type header (Content-Type: on page 1154).
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).
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.
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.
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).
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.
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.
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.
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.
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.
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.
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.
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.
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.
|
Macro |
§ |
Sets what |
|
|
From: on page 1157 |
Define the format for the |
|
|
Received: on page 1162 |
Define the format for the |
|
|
OldStyleHeaders on page 1061 |
Declare the |
|
|
MaxHeadersLength on page 1045 |
Declare the |
|
|
MaxMimeHeaderLength on page 1047 |
Declare the |
|
|
SingleLineFromHeader on page 1092 |
Declare the |
|
|
UseErrorsTo on page 1115 |
Declare the |
|
|
NoRecipientAction on page 1060 |
Declare the |
|
|
RrtImpliesDsn on page 1083 |
Declare the |
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.
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.
|
Header |
§ |
Flags |
Defined by |
|
|
Forwarding with Re-Sent Headers on page 1147 |
|
RFC2822 |
|
|
From: on page 1157 |
|
RFC2822 |
|
|
Forwarding with Re-Sent Headers on page 1147 |
|
RFC2822 |
|
|
Sender: on page 1166 |
|
RFC2822 |
|
|
From: on page 1157 |
|
RFC2822 |
|
|
Apparently-From: on page 1150 |
n/a |
Smail 3.0 |
|
|
Reply-To: on page 1164 |
|
RFC2822 |
|
|
Disposition-Notification-To: on page 1156 |
|
RFC2298 |
|
|
Return-Receipt-To: on page 1165 |
|
Obsolete |
|
|
Errors-To: on page 1156 |
|
sendmail (deprecated) |
|
|
Full-Name: on page 1158 |
|
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 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.
|
Header |
§ |
Flags |
Defined by |
|
|
To: on page 1167 |
|
RFC2822 |
|
|
Forwarding with Re-Sent Headers on page 1147 |
|
RFC2822 |
|
|
Cc: on page 1152 |
|
RFC2822 |
|
|
Forwarding with Re-Sent Headers on page 1147 |
|
RFC2822 |
|
|
Bcc: on page 1152 |
|
RFC2822 |
|
|
Forwarding with Re-Sent Headers on page 1147 |
|
RFC2822 |
|
|
Apparently-To: on page 1151 |
|
Obsolete |
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.
|
Header |
§ |
Flags |
Defined by |
|
|
Message-ID: on page 1159 |
None |
RFC2822 |
|
|
Forwarding with Re-Sent Headers on page 1147 |
|
RFC2822 |
|
|
Message: on page 1160 |
|
Obsolete |
|
|
Text: on page 1167 |
|
Obsolete |
|
|
Precedence on page 1148 |
n/a |
All sendmails |
|
|
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 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.
|
Header |
§ |
Flags |
Defined by |
|
|
Date: on page 1155 |
None |
RFC2822 |
|
|
Posted-Date: on page 1161 |
n/a |
Obsolete |
|
|
Forwarding with Re-Sent Headers on page 1147 |
|
RFC2822 |
|
|
Received: on page 1162 |
|
RFC2822 |
|
|
Via: on page 1167 |
|
Obsolete |
|
|
Mail-From: on page 1159 |
|
Obsolete |
|
|
X-Authentication-Warning: on page 1167 |
|
V8 sendmail |
|
|
X400-Received: on page 1168 |
|
IDA and V8 only |
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.
|
Header |
§ |
Flags |
Defined by |
|
|
Return-Path: on page 1165 |
|
RFC2822 |
|
|
In-Reply-To: on page 1158 |
n/a |
RFC2822 |
|
|
References: on page 1164 |
n/a |
RFC2822 |
|
|
Keywords: on page 1159 |
n/a |
RFC2822 |
|
|
Subject: on page 1166 |
|
RFC2822 |
|
|
Comments: on page 1152 |
|
RFC2822 |
|
|
Encrypted: on page 1156 |
n/a |
RFC822 |
|
|
Content-Length: on page 1154 |
|
|
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.
|
Header |
§ |
Flags |
Defined by |
|
|
MIME-Version: on page 1160 |
n/a |
RFC2045 |
|
|
Content-Disposition: on page 1153 |
n/a |
RFC2183 |
|
|
Content-Id: on page 1153 |
n/a |
RFC2045 |
|
|
Content-Transfer-Encoding: on page 1154 |
|
RFC2045 |
|
|
Content-Type: on page 1154 |
|
RFC2045 |
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 fredMessages 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.
|
Resent- form of |
Header |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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.
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.
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 must begin a line. This command is composed
of four parts:
Pstring=valueThe 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.
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.
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.
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.
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.
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.
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.
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.
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.
↑
whitespaceThe 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 $uThis declaration causes the new Comment: header to be
added to the mail
message.
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.
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.
|
Parameter |
Description of value |
|
|
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. |
|
|
The original time and date the content was created. |
|
|
The time and date the content was last modified. |
|
|
The time and date the content was last read. |
|
|
The size in bytes of the content. |
In general, the Content-Disposition: header should be
advisory.
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.
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.
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: howHere 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.
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"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.
Like the Return-Receipt-To: header Sun Internet Mail System
See the Return-Receipt-To: header (Return-Receipt-To: on page
1165).
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@hostIf 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.
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#addressHere, 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.
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 keyThe 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.
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.
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, addressHere, 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).
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 UUCPThe Full-Name:
header can be specified in the configuration file.
If this header is already in the mail message,
sendmail does not replace
it.
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>
↑
whitespaceThe In-Reply-To:
header should never be declared in the configuration
file.
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.
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.
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).
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.
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.
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.
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.
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: priHere, 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.
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
↑
whitespaceThe 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:
fromFull canonical name of the sending host (required).
byFull canonical name of the receiving host (required).
viaPhysical network that was used to transmit the message, such as TCP, INTERNET, JANET, or XNS (optional).
withProtocol used to receive the message, such as ESMTP or SMTP (optional).
idIdentifier assigned by the local host, such
as the Message-Id: header’s value
(optional).
forInitial, untranslated address of the recipient—when there is a single recipient, sendmail always includes this item (optional).
;dateDate 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):
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; $|;
$.$bHReceived: $?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; $|;
$.$bHReceived: $?sfrom $s $.$?_($?s$|from $.$_)
$.$?{auth_type}(authenticated)
$.by $j ($v/$Z)$?r with $r$. id $i$?u
for $u; $|;
$.$bHReceived: $?sfrom $s $.$?_($?s$|from $.$_)
$.by $j ($v/$Z)$?r with $r$. id $i$?u
for $u; $|;
$.$bThe 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
$iThe $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.
;
$bThe $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.
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.
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 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.
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.
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.
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.
↑
whitespaceThis 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 nothingA 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.
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).
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.
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: messageHere, host is the canonical
name of the host that inserted this header. The
message is one of the
following:
-C
fileAn 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.
-fA 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.
-bsA 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.
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.
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.
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.
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.