In the LHS of rules, it is sometimes advantageous to compare individual tokens to multiple strings when determining a match. The configuration class command provides this ability. The class command is similar to the macro definition command, except that instead of assigning a single value to a macro, it assigns many values to a class. Classes differ from macros in that they can be used only in the LHS of rules, whereas macros can be used in either the RHS or the LHS.
Two different configuration commands can be used to assign values to a
class. The C configuration
command is used to assign values from within the configuration file.
The F configuration command is
used in three ways: to assign values by reading them from a disk
file, to assign values by looking up a key in a database, or to
assign values by running a program and reading the output. These
commands can be intermixed to create a single class, or used
separately to create multiple classes.
The five forms for the class configuration command are the following:
CX list ← values from configuration file CX $=Y ← copy values from another class (V8.10 and later) FX /file ← values from a disk file FX |program ← values via another program FX key@database ← values from a database map (V8.12 and later)
The class configuration command starts with either the letter
C or the letter
F, which must
begin a line. The C says
values will be assigned as a part of the configuration
command. The F says
values will be assigned from an external file, program, or
database map.
The C or F is immediately followed
(with no intervening whitespace) by the name of the class
(the X in the preceding
commands). A class name is any single ASCII character or,
beginning with V8.7 sendmail, a
multicharacter name enclosed in curly braces:
CX list ← all versions C{LongName} list ← beginning with V8.7
See Multicharacter Names on page 790 for a full discussion of how to use multicharacter names.
Note that classes are separate from macros, so they can both use the same letter or name with no conflict.
The sendmail program reserves the lowercase letters for its own use as internally defined class names. All uppercase letters and all names that begin with uppercase letters are available for your use.
The C form of the
class command causes values to be assigned from
within the configuration file. In general, the
C class command
looks like this:
CX list ← values from configuration file C{XX} list ← values from configuration file
Here, list is a list of
string elements (delimited by whitespace) that
follows on the same line as the C command. Each word in
list is added to the
collection of values in the class
$=X in the first case
and to the class $={XX} in the second.[331]
Multiple declarations of the same named class can coexist in the configuration file. Each declaration after the first adds its string elements to those already in the collection. That is:
CX string1 string2 CX string3 string4
produces the same collection of class strings as does:
CX string1 string2 string3 string4
Both create a class containing four strings.
Whitespace separates one value from another.
Whitespace is defined by the C-language
isspace(3) routine and
usually includes the space, tab, newline, carriage
return, and form feed characters. Each line of text
assigned to a class is broken up by
sendmail into
whitespace-delimited words when the C configuration command
is parsed.
When a line is indented with a space or a tab, that
line is joined by sendmail to
the preceding line. Thus, the following three
declarations also add four words to the class
$=X:
CX string1
CX string2
CX string3
string4
↑
tabWords that are added to a class cannot be removed after sendmail has read them. Instead, they must be edited out of whatever file or program produced them, and the sendmail daemon must be restarted.
The list of words in a class declaration can include
macros. For example, the following assigns the same
values to class $=X as did the earlier example:
D{LIST} string1 string2 string3 string4
CX ${LIST}Macros used in class declarations are expanded when
the configuration file is read. Deferred macros
(those with the $& prefix) cannot be used in class
declarations. But conditionals can:
CX ourhost$?{Domain}.${Domain}$.Beginning with V8.10 sendmail, it is possible to copy and add values from one class to another. The declaration to do this looks like the following:
C{To} $={From}Here, the values stored in the $={From} class are added
to the values stored in the $={To} class. If
$={To} does not
exist, it will create them.
This effect is caused by the fact that class
macros are now expanded when placed on a C configuration line. To
illustrate, consider the following mini
configuration file, which we call
x.cf:
V10 CA 1 2 3 CB 7 8 9 CX $=A 4 5 6 $=B
When this configuration file is read, first
the class $=A
is filled with three values: 1, 2, and 3. Then the
class $=B is
filled with three different values: 7, 8, and 9.
Finally, the class $=X is filled first with the values
from $=A (1, 2,
and 3), then with its own values (4, 5, and 6),
and lastly with the values from $=B (7, 8, and 9). The
result can be seen by running
sendmail on this mini
configuration file in rule-testing mode:
%/usr/sbin/sendmail -bt -C x.cfADDRESS TEST MODE (ruleset 3 NOT automatically invoked) Enter <ruleset> <address> >$=X2 3 1 6 7 4 5 8 9 >
Ignore the fact that the values you put in are printed in a different order. This is an artifact of the way sendmail stores class values in its symbol table and actually improves the efficiency with which they are later looked up.
Class macros that you list as values for a
C configuration
line need not be previously declared or even hold
any values. If they hold values, those values will
be added to the target class. Valueless and
undeclared classes will simply be ignored.
The F form of the
class configuration command allows values to be
appended to a class from outside the configuration
file. In general, the file command looks like one of
the following:
FX file ← values from a disk file FX |program ← values via another program (V8.7 and later) FX key@dbmap ← values from a database map (V8.12 and later)
The F is
immediately followed by the name of the class. This
can be either a single-character name, as shown, or
a multicharacter name. The name is followed by
optional whitespace and then a filename, a program
name, or a database-map lookup. If the name begins
with the pipe character (|), it is taken to be the name of a
program to run.[332] If the name includes an @ character, it is taken
to be a key to look up, and the name of a database
map. Otherwise, it is taken to be the name of a file
to read.
If SCANF (SCANF on page 137) was
defined when sendmail was
compiled, each line that is read from a file or
program (but not from a database map) is parsed by
the C-language scanf(3) library
routine. The formatting pattern given to
scanf(3) is %s, which tells
scanf(3) to read only the
first whitespace-delimited word from each line of
text.
When the configuration file is processed, the file is opened for reading, or the program is executed, or the database map is opened for lookups. If any cannot be opened (for reading, execution, or lookups), the following error is logged and sendmail ignores that configuration command:
fileclass: cannot open what: whyHere, the what is the exact
text that was given in the configuration file, and
why is the text of a
system error.
A file, program, or database map can also fail to open because of defective permissions. See Permissions on page 164 to learn why permissions are important, and Recommended Permissions on page 167 for a list of recommended permissions.
For the file form only, if the file can optionally not
exist, you can prefix its name with a -o switch:
FX -o file ← OK for file to not exist
This tells sendmail to remain
silent if the file does not exit. The -o switch is useful when
a configuration file is shared by several machines,
only some of which need the external class macro
file. But be aware that there can be grave risk to
not knowing when a critical file disappears.
The C and F forms of the
configuration command can be intermixed for any
given class name. For example, consider a file named
/etc/mail/localnames with the
following contents:
string3 string4
The following two configuration commands add the same
four strings to the class X as did the C command alone in the previous
section:
CX string1 string2 FX /etc/mail/localnames
This creates a class with four strings as elements.
Whitespace delimits one string from the others in
the C line
declaration. The file
/etc/local/names is then
opened and read, and each of the two words in that
file is added to the two words that are already in
the class.
The file form of the class configuration
command allows different formatting patterns to be
used with scanf(3).[333] But the program form does not allow
any variation, and so its
scanf(3) pattern is always
%s, which tells
scanf(3) to read only the
first whitespace-delimited word from each line of
text:
FX file pat ← with scanf(3) pattern FX |program ← always "%s" FX key@dbmap ← cannot be used with scanf(3)
If the optional pat argument to the file form is
missing, the pattern given to
scanf(3) is %s. The optional
pat argument is
separated from the file argument by one or more spaces or
tabs. It should not be quoted, and it consists of
everything from its first character to the end of
the line. Internally,
scanf(3) is called
with:
sscanf(result, pat, input)
Here, result is the string array element to
be added to the class definition. The pat is the
scanf(3) pattern, and
input is the
line of text read from the file.
After each line of text is read from the file and filtered with the scanf(3) pattern, it is further subdivided by sendmail into individual words. That subdividing uses whitespace (as defined by the C-language isspace(3) routine) to separate words. Each separate word is then appended as an individual element to the class array.
Consider the contents of the following file named /etc/mail/localhosts:
server1 server2 # my two nets uuhost # my uucp alias #mailhost # mail server alias (retired 06,23,91)
This file contains three hostname aliases to
be added to a class—say, H. The following configuration command
does just that:
FH /etc/mail/localhosts %[^#]
The pattern %[^#] causes
scanf(3) to read all
characters in each line up to, but not including,
the first #
character. The first line includes two
whitespace-delimited words that are appended to
the class H.
The second line contains one word, and the third
contains none.
Beginning with V8.12, you can declare class values by specifying and using database maps. Database maps are described in Chapter 23 on page 878. In its simplest form, such a declaration looks like this:
FXkey@ type:detail F{Name}key@ type:detail
Each such declaration begins with the F configuration command,
which is immediately followed (with no intervening
space) by the name of the class that will be filled
with values. The first line shows the
single-character name form (the X) and the second line
shows the multicharacter name form (the {Name}).
The name of the class is immediately followed by the key to look up in the database map. Note that you must be very careful to specify a key that actually exists. If the key is not found in the database map, sendmail silently ignores the error.
The key is immediately
followed by a literal @ character, which in turn is
immediately followed by the
type of the database
map. A db-type database map,
for example, could have a
type of either hash or btree. An
ldap-type database map, for
example, would have a
type of ldap. (We discuss
ldap in detail in the next
section.) A complete list of
types can be found in
the leftmost column of Table 23-2 on page
883.
The type is immediately
followed by a colon and then by the
detail. The nature of
the detail varies
depending on what you want this command to do. To
illustrate, consider the following addition to an
mc configuration file:
LOCAL_CONFIG FwCWhosts@hash:/etc/mail/access
Here, under the LOCAL_CONFIG part of the
mc file, we place an F configuration command.
The class that will be filled with values is the
$=w class
($=w on page 876), a
special one that contains all the names by which the
local host can be known.
It will be filled with values by looking up the key
CWhosts in the
hash-type
database that is contained in the file
/etc/mail/access.
The key is optional, and it is not an error to omit
it. This property can be useful for ldap-type maps, but is
generally not useful for other database maps. For
most database-map types, a missing key will simply
match nothing and result in no values filling the
class.
The type is mandatory. If
it is missing (for example, if hash were omitted from
the preceding declaration), the following error
would be printed and logged:
fileclass: cannot open 'CWhosts@:/etc/mail/access': No such file or directory
If the type is misstated as
one that does not exist (for example, if foo replaced hash), the following
would be printed and logged:
fileclass: F{w}: class foo not availableIf there is a problem with the
detail (for example, if
access were misspelled as
acess), the following error
would be printed and logged:
hash map "w": missing map file /etc/mail/acess.db: No such file or directory
If the key contains an
@ character
(as, for example, gw@wash.dc.gov),
the part to the left of the first @ is taken as the
key
(gw) and the rest of the line
through the : is taken as the
type
(wash.dc.gov@hash), yielding
the following error:
F{w}: class wash.dc.gov@hash not availableThere is no possible way to put an @ character into a
key.
One use for filling a class with a database-map lookup might involve looking up the name for root on the local machine:
LOCAL_CONFIG
F{RootName}0@text:-k2 -v0 -z: /etc/passwdHere, we need to know the name of
root because it is not the
same on all machines (some might call it
toor, and others
rot). The name found will be
placed into the class $={RootName}. The text-type database map
is used because it can look up keys in a plain file.
The /etc/passwd file might
look, in part, like this:
0th ↓ boss:Kmz4md67r66n2:0:1:Operator:/:/bin/csh daemon:*:1:1::/: ↑ 2nd
We wish to look up the first entry in that file that
has a user-id of zero. Note
that text type
database maps are arranged in columns that are
numbered, starting with column zero. In this case,
the second column holds the
user-id and the “zeroth”
column holds the name we seek.
The F configuration
command looks up the key 0 in a text type database map found in the
file /etc/passwd. The
database-map switches that prefix the file name tell
sendmail to do the following: look up the key in the
second column (the -k2); return the value from the zeroth
column (the -v0);
and use a colon as the column separator (the
-z:). The
text type
database map and its switches are described in text on page 941.
Several mc macros are
used to fill class macros with values. They are
listed in Table 22-1,
along with the class macros they fill. Note that
the classes shown should not be used directly
because there is no guarantee that they will
continue to be available in the future. To be
safe, always use the mc macro
instead. To reinforce this precaution in the
descriptions that follow, we use the
mc name for the class (as the
EXPOSED_USER class) instead of the class macro
name (as the $=E class).
|
mc macro |
§ |
Class macro |
|
|
FEATURE(nocanonify) on page 634 |
|
|
|
FEATURE(use_ct_file) on page 643 |
|
|
|
EXPOSED_USER mc Macro on page 599 |
|
|
|
FEATURE(generics_entire_domain) on page 622 |
|
|
|
LDAPROUTE_DOMAIN and LDAPROUTE_DOMAIN_FILE on page 924 |
|
|
|
LDAPROUTE_DOMAIN and LDAPROUTE_DOMAIN_FILE on page 924 |
|
|
|
$=w on page 876 |
|
|
|
LOCAL_USER mc Macro on page 605 |
|
|
|
MASQUERADE_DOMAIN mc Macro on page 600 |
|
|
|
MASQUERADE_EXCEPTION_FILE mc Macro on page 602 |
|
|
|
The RELAY_DOMAIN_FILE mc macro on page 269 |
|
|
|
FEATURE(virtuser_entire_domain) on page 645 |
|
It is possible to fill these class macros from database maps using these mc macros. Instead of the filename, just place the database lookup expression between the trailing parentheses of the mc macro. For example, consider this way of filling the RELAY_DOMAIN class with values from the access database, assuming the following entry exists in your access database:
DomainList: our.domain their.domain another.domain
Recall that the RELAY_DOMAIN class (The RELAY_DOMAIN mc macro on page 269) determines which domains you want to relay for. The idea here is that you want to fill it with the values our.domain, their.domain, and another.domain. You could perform that lookup with an mc configuration line such as this:
RELAY_DOMAIN_FILE(`DomainList:@hash:/etc/mail/access')
Here, DomainList: (colon included) is the key
looked up in the hash-type database-map located in the
database file
/etc/mail/access. The
presence of the literal @ tells sendmail
this is a database-map lookup, and not the name of
a file to read.
To use an example from the previous section, consider adding a user-id name to the EXPOSED_USER class (EXPOSED_USER mc Macro on page 599) like this:
EXPOSED_USER_FILE(`0@text:-k2 -v0 -z: /etc/passwd')
This lookup would result in the addition of the name boss (from the previous section) to the EXPOSED_USER class.
Adding values to class macros with ldap-type map databases
is very easy. In its simplest form, just use a
literal @LDAP as the
type and nothing
else:
RELAY_DOMAIN_FILE(`@LDAP') FR@LDAP
The first form uses the
mc macro RELAY_DOMAIN_FILE to
add values to the RELAY_DOMAIN class (The RELAY_DOMAIN mc macro
on page 269). The second line adds to the same
class, but uses the F configuration command. For both
lines, the database used for the lookup is the
ldap-type
database because of the literal @LDAP in both.
That literal expression causes the following
default ldap
schema to be used:
-k (&(objectClass=sendmailMTAClass)(sendmailMTAClassName=R)
(|(sendmailMTACluster=${sendmailMTACluster})(sendmailMTAHost=$j)))
-v sendmailMTAClassValueWhen using the F configuration command form, you must
specify the class to be filled. For
example:
F{OurStuff}@LDAPWhichever class you specify (the {OurStuff} here) will
become the class listed with the sendmailMTAClassName= in
the default schema:
-k (&(objectClass=sendmailMTAClass)(sendmailMTAClassName={OurStuff}
)
(|(sendmailMTACluster=${sendmailMTACluster})(sendmailMTAHost=$j)))
-v sendmailMTAClassValueNaturally you can bypass the default ldap definition
altogether by placing your own into the
declaration. Consider the following two lines,
which do just that:
VIRTUSER_DOMAIN_FILE(`@ldap:-k (&(objectClass=virtHosts)(host=*)) -v host')
F{VirtHosts}@ldap:-k (&(objectClass=virtHosts)(host=*)) -v hostNote that by replacing the literal @LDAP with a
type declaration of
@ldap, you
eliminate the automatic generation of a default
definition.
One possible pitfall is the temptation to define an identical class macro’s values in both your domain record and individual host records. If you do, the lookup will be additive, adding record values from both the domain and the host records.
Class macros are useful only in the LHS of rules. The sendmail program offers two ways to use them:
$=XThe $=
prefix causes sendmail to
seek a match between the workspace and one of the
words in a class list.[334]
$˜XThe $˜
prefix causes sendmail to
accept only a single token in the workspace that
does not match any of the words in a class
list.
The list of words that form a class are searched by
prefixing the class name with the characters
$=:
R$=X $@<$1>
In this rule, the expression $=X causes
sendmail to search a class
for the word that is in the current workspace. If
sendmail finds that the word
has been defined, and if it finds that the word is
associated with the class $=X, only then is a match made.
The matching word is made available for use in the RHS
rewriting. Because the value of $=X is not known ahead
of time, the matched word can be referenced in the
RHS with the $digit
positional operator.
Consider the following example. Two classes have been
declared elsewhere in the configuration file. The
first, $=w,
contains all the possible names for the local
host:
Cw localhost mailhost server1 server2
The second, $=D,
contains the domain names of the two different
networks on which this host sits:
CD internal.domain external.domain
If the object of a rule is to match any variation on the local hostname at either of the domains and to rewrite the result as the official hostname at the appropriate domain, the following rule can be used:
R $=w . $=D $@ $w . $2 make any variations "official"
If the workspace contains the tokenized address
server1.external.domain,
sendmail first checks to see
whether the word server1 has
been defined as part of the class w. If it has, the dots
in the rule and workspace match each other, and then
sendmail looks up
external.domain.
If both the host part and the domain part are found to
be members of their respective classes, the RHS of
the rule is called to rewrite the workspace. The
$2 in the
workspace corresponds to the $=D in the LHS. The
$=D matches the
external.domain from the
workspace, so that text is used to rewrite the new
workspace.
Note that prior to V8, when sendmail looked up the workspace to check for a match to a class, it looked up only a single token. V8 sendmail allows multitoken class matching.
The $˜ prefix is
used to match any single token in the workspace that
is not in a class. It is used fewer than a dozen
times in a typical production configuration file,
but when the need for its properties arises, it can
be very useful.
To illustrate, consider a network with three PC
machines on it. The PC machines cannot receive mail,
whereas all the other machines on the network can.
If the list of PC hostnames is defined in the class
{PChosts}:
C{PChosts} pc1 pc2 pc3a rule can be designed that will match any but a PC hostname:
R $* < @ $˜{PChosts} > $@ $1 < @ $2 > filter out the PC hostsHere the LHS looks for an address of the form:
"user" "<" "@" "not-a-PC" "">This matches only if the @ token is not
followed by one of the PC hosts listed in class
$={PChosts}. If
the part of the workspace that is tested against the
list provided by $˜ is found in that list, the match
fails.
Note that the $digit
positional operator in the RHS (the $2 in the preceding
example) references the part that matches $˜{PChosts}. That is,
$2 references
the token in the workspace that is not in the class
{PChosts}. If
the workspace contains
ben<@philly>, the
$2 references
the philly.
Also note that multitoken expressions in the workspace
will not match. That is, for multitoken expressions
in the workspace, $˜ is not the
opposite of $=.
To illustrate, consider this mini configuration
file:
V10 CX hostA.com Stest R $˜X $@ no $1 is not in X R $=X $@ yes $1 is in X R $* $@ neither
Now feed a multitokened address through these rules in rule-testing mode:
%/usr/sbin/sendmail -Cx.cf -btADDRESS TEST MODE (ruleset 3 NOT automatically invoked) Enter <ruleset> <address> >test hostC.comtest input: hostC . com test returns: neither
Here, the rule set returned neither because a multitoken expression
in the workspace should never be used with $˜. That is, $˜ looks for a workspace
that is not a member of the class and, indeed,
hostC.com is not. But because
hostC.com is multi-tokened,
$˜ acts as
though it is a member of the class, and so does not
call the RHS of the rule:
R $˜X ← a multitokened workspace will never call the RHSIf you consider multitokens and $˜ as illegal to use
together, this failure, although convoluted, makes
sense.
Another way to think of this failure is by comparing
the $˜ operator
to the $-
operator. Neither will match more than a single
token in the workspace. If the $˜ does not match a
single token, the LHS does not match, and the RHS is
not called.
There are two ways to circumvent this problem. One
alternative is to make the $˜ always look up only a single
token:
R $~X $* $@ no $1 is not in X
Here, the $* will
match the .com.
Then $~X will
correctly look up only the single token hostC, and correctly not
find it.
A second alternative is to invert the logic of the
test, and use the $= prefix only when multiple tokens are
in the workspace:
R $=X $@ yes $1 is in X R $* $@ no $1 is not in X
Here, we first check to see whether the multitokened
workspace is in the class $=X, and return yes if it is. Otherwise,
we know it is not in the class.
Multitoken matching operators, such as $+, always try to match
the least that they can (Backup and Retry on page 660). Such a
simple-minded approach could lead to problems in
matching (or not matching) classes in the LHS.
However, the ability of
sendmail to back up and retry
alleviates this problem. For example, consider the
following five tokens in the workspace:
"A" "." "B" "." "C"
and consider the following LHS rule:
R $+ . $=X $*
Because the $+
tries to match the minimum, it first matches only
the A in the
workspace. The $=X then tries to match the B. and then B.C to the class
$=X. If this
match fails, sendmail backs up
to the $+ and
tries again.
The next time through, the $+ matches A. in the workspace, but that fails to
match the dot in the rule, so it backs up again and
matches A.B. The
$=X tries to
match the C in
the workspace. If C is not in the class $=X, the entire LHS
fails.
The ability of the sendmail program to back up and retry LHS matches eliminates much of the ambiguity from rule design. The multitoken matching operators try to match the minimum but match more if necessary for the whole LHS to match.
When comparing a token in the workspace to a list of words in a class array, sendmail tries to be as efficient as possible. Instead of comparing the token to each word in the list, one by one, it simply looks up the token in its internal string pool. If the token is in the pool and if the pool listing is marked as belonging to the class being sought, a match is found.
The comparison of tokens to entries in the string pool is case-insensitive. Each token is converted to lowercase before the comparison, and all strings in the string pool are stored in lowercase.
Because strings are stored in the pool as text with a type, the same string value can be used for different types with no conflict. For example, the symbolic name of a delivery agent and a word as a class macro’s value can be identical, yet they will still be separate entries in the string pool.
The sendmail program uses a simple hashing algorithm to ensure that the token is compared to the fewest possible strings in the string pool. In normal circumstances, that algorithm performs its job well. At sites with unusually large classes (perhaps a few thousand hosts in a class of host aliases), it might be necessary to tune the hashing algorithm. The code is in the file stab.c with the sendmail source. The number of hash buckets is set by the constant STABSIZE.
As an alternative to very full classes, sendmail offers database maps (Enable at Compile Time on page 879). No information is currently available contrasting the efficiency of the various approaches.
In configuring with the mc technique, many classes are defined for your convenience. You need to be aware of these, not only to take advantage of them, but also to avoid reusing their names by mistake. Table 22-2 lists all the macros that the mc technique uses as of version 8.12. Most are described in other sections, but a few are described here. See a description of LOCAL_CONFIG (LOCAL_CONFIG mc macro on page 595) for the general method used for adding members and new class names using the mc configuration technique.
|
Class |
§ |
Description |
|
|
Enabling the access Database Generally on page 277 |
With |
|
|
FEATURE(bestmx_is_local) on page 617 |
With |
|
|
FEATURE(nocanonify) on page 634 |
With |
|
|
EXPOSED_USER mc Macro on page 599 |
With |
|
|
GENERICS_DOMAIN mc macro on page 624 |
With |
|
|
LOCAL_USER mc Macro on page 605 |
With |
|
|
LDAPROUTE_DOMAIN and LDAPROUTE_DOMAIN_FILE on page 924 |
With |
|
|
LDAPROUTE_EQUIVALENT and LDAPROUTE_EQUIVALENT_FILE on page 924 |
With |
|
|
MASQUERADE_DOMAIN mc Macro on page 600 |
With |
|
|
MASQUERADE_EXCEPTION mc Macro on page 601 |
With |
|
|
Follows table |
The list of nonusername characters that can
cause forwarding ( |
|
|
Follows table |
The list of pseudo top-level domains (e.g.,
|
|
|
$={ResOk} on page 874 |
Mark a successful DNS lookup. |
|
|
The RELAY_DOMAIN mc macro on page 269 |
With |
|
|
Accept and Reject per Recipient on page 284 |
With |
|
|
Follows table |
List of rule sets to call for searching the access database map (prior to V8.13 called this) |
|
|
Follows table |
List of rule sets to call for searching the access database map (V8.13 and later called this) |
|
|
$={tls} and $={Tls} on page 875 |
Possible values for TLS policy in the access database map (prior to V8.13 called this) |
|
|
$={tls} and $={Tls} on page 875 |
Possible values for TLS policy in the access database map (V8.13 and later called this) |
|
|
SASL and Your mc File on page 191 |
With |
|
|
UUCP Support on page 606 |
With |
|
|
UUCP Support on page 606 |
With |
|
|
FEATURE(virtuser_entire_domain) on page 645 |
With |
|
|
UUCP Support on page 606 |
With |
|
|
UUCP Support on page 606 |
With |
|
|
UUCP Support on page 606 |
With |
|
|
UUCP Support on page 606 |
With |
The class $=O is used by
the m4 technique to hold a list of
characters that cannot be used in local usernames. This list
is used to detect certain kinds of routing addresses that
might otherwise be difficult to detect. This list initially
contains:
@ %
but can also contain an !
if UUCP support is included.
The class $=P holds a list
of pseudodomains that will not be looked up using DNS.
Unless you use a FEATURE(), this class will contain a dot
only. Various FEATURE()s
will add appropriate pseudodomains to it, such as .UUCP and
.REDIRECT.
The class $={src} (prior to
V8.13) or $=Src (V8.13
and later) holds a list of rule set names that can be called
to look up items in the access
database. It is a clever trick that you might wish to copy
for use in your own rule sets. To see how this trick is
performed, look for that expression in your configuration
file.
Prior to V8 sendmail, only the class
$=w was used
internally, and only a small handful of classes were used in
the configuration file. Recently, more and more classes have
been added to that list. Table 22-3
lists all the class macros defined internally by
sendmail as of V8.14.
|
Class |
§ |
Description |
|
|
$=b on page 870 |
|
|
|
$={checkMIMEFieldHeaders} on page 870 |
|
|
|
$={checkMIMEHeaders} on page 871 |
|
|
|
$={checkMIMETextHeaders} on page 871 |
|
|
|
$=e on page 872 |
Encode this Content-Transfer-Encoding: |
|
|
$=k on page 872 |
The local UUCP name |
|
|
$=m on page 872 |
List of local domains |
|
|
$=n on page 873 |
Don’t encode these Content-Types |
|
|
$={persistentMacros} on page 873 |
Macros preserved in the |
|
|
$=q on page 874 |
Always quoted-printable encode Content-Type: |
|
|
$=s on page 875 |
Presume an RFC2822 7-bit body |
|
|
$=t on page 875 |
List of trusted users |
|
|
$=w on page 876 |
List of our other names |
Note that these classes really are used internally by sendmail, so don’t try to redefine their use in the configuration file. Such an attempt will be doomed to failure.
Although a class macro name can be any ASCII character[335] (any character in the range 0x0 to 0x7f), avoid using any of the nonletter characters. At the very least, they create confusing reading, and at worst they can cause sendmail to completely misinterpret your intentions.
Although values can traditionally be made to
contain whitespace by quoting them, class macros
will misinterpret those quotes. For example,
"vax ds1"
wrongly parses into two class entries: "vax and ds1", with the quotes a
part of each.
Duplicate values are silently ignored. Therefore, typos in a list of values can cause an accidentally duplicated entry to be silently excluded.
Avoid creating a new class macro name without
first checking to see whether it has already been
used. That is, don’t create a list of UUCP hosts
within class $=U without first checking
both for preexisting CU and FU definitions and for
rule-set uses of $=U and $˜U. It is perfectly legal for the
$=U and
$˜U expressions
to exist in rule sets without a corresponding
CU or FU definition. However,
such empty references will still cause
sendmail to search the string
pool.
Under V8 sendmail, you
can watch your class macro definitions being
formed by using the -d37.8 debugging switch (-d37.8 on page 564). Under other
versions of sendmail, you can
only approximate this information by using the
-d36.9
debugging switch.
The file form’s scanf(3) pattern can produce unexpected results. Remember that the pattern is applied to a line, not to a stream.
No error checking is performed during reads
for the F form
of the class configuration command. An I/O error
reading from a file silently causes the rest of
that file’s contents to be ignored. An unreported
error from a program (one that silently returns 0
on both success and failure) is also silently
ignored by sendmail.
We document most of the class macros employed by sendmail in chapters appropriate to the use of each. Here we collect, and document, those few class macros that have no other natural home.
MIME types for no NL-to-CRLF translation V8.8 and later
Ordinarily, MIME mail is translated into SMTP format before it is encoded with Base64. Specifically, the newline character that ends each line is converted into the SMTP carriage-return/linefeed form before being encoded. This adds time to the process, and extra size to the result, and for some forms of MIME mail this translation makes little sense. Video, for example, is not text-oriented, and so should not be treated like text (even though it will be encoded as text for transmission).
Beginning with V8.8, sendmail
will skip converting newlines under certain
conditions. Before deciding to convert,
sendmail extracts the
type and
subtype from the
Content-Type:
header (Content-Type: on page
1154):
Content-Type: type/subtype; ...If the type is in the class
$=b, newline
conversion will be skipped. If a concatenation of
type, a slash (/), and
subtype are in class
$=b, newline
conversion will also be skipped.
Note that this class is not automatically available. To use it in this way, you need to define USE_B_CLASS when you compile sendmail.
If you define USE_B_CLASS,
sendmail will automatically
assign to class $=b the values application/octet-stream, image, audio, and video.
MIME headers for maximum parameter length checking V8.10 and later
Beginning with V8.10 sendmail,
the MaxMimeHeaderLength option (MaxMimeHeaderLength on page 1047) can
be used to define the maximum length for the
parameters that some MIME headers take. A parameter
is separated from the main header name and value by
a semicolon:
name: value ; parameter ; parameter ...
Before checking that parameter’s length,
sendmail looks to see whether
the header name is in the
class $={checkMIMEFieldHeaders}. If it isn’t,
sendmail skips the parameter
length check.
When V8.10 sendmail starts up, it
predefines the $={checkMIMEFieldHeaders} class to
contain two MIME headers: the Content-Disposition:
header (Content-Disposition:
on page 1153); and the Content-Type: header (Content-Type: on page 1154). You
can add more headers with the C or F configuration file
command.
If any of these parameters are found to be too long,
they are truncated to the limit imposed by the
MaxMimeHeaderLength option (MaxMimeHeaderLength on page
1047).
MIME headers for maximum legal length checking V8.10 and later
Beginning with V8.10 sendmail,
the MaxMimeHeaderLength option (MaxMimeHeaderLength on page 1047) can
be used to define the maximum length for selected
MIME headers. Before making that check,
sendmail looks to see whether
a particular header is in the class $={checkMIMEHeaders}. If
it isn’t, sendmail skips this
length check.
When V8.10 sendmail starts up, it
predefines the $={checkMIMEHeaders} class to contain
five MIME headers: the Content-Disposition: header (Content-Disposition: on page
1153); the Content-Id: header (Content-Id: on page 1153); the
Content-Transfer-Encoding: header
(Content-Transfer-Encoding:
on page 1154); the Content-Type: header (Content-Type: on page 1154); and
the MIME-Version:
header (MIME-Version: on page
1160). You can add more headers with the C or F configuration file
command.
If any of these headers are found to be too long, they
are truncated to the length specified by the
MaxMimeHeaderLength option (MaxMimeHeaderLength on page 1047).
Note that this truncation is done carefully so as to
maintain the appearance of an RFC2822-legal
header.
MIME headers for maximum arbitrary length checking V8.10 and later
Beginning with V8.10 sendmail,
the MaxMimeHeaderLength option (MaxMimeHeaderLength on page 1047) can
be used to define the maximum length for selected
MIME headers that present text descriptions. Before
making that check, sendmail
looks to see whether a particular header is in the
class $={checkMIMETextHeaders}. If it isn’t,
sendmail skips this length
check.
When V8.10 sendmail starts up, it
predefines the $={checkMIMETextHeaders} class to
contain the single MIME header Content-Description:
header (Content-Description:
on page 1153). You can add more headers with the
C or F configuration file
command.
If this header’s value is found to be too long, it is
truncated to the length specified by the MaxMimeHeaderLength
option. Note that this is a blatant truncation, and
no effort is made to keep the header legal because
it contains only random text.
Note also that you should use $={checkMIMEHeaders} ($={checkMIMEHeaders} on page 871) for RFC-format-specific
headers.
Encode this Content-Transfer-Encoding: V8.7 and later
The F=7 delivery
agent flag (F=7 on page
764) determines whether MIME-encoded data should be
converted from 8 to 7 bits. If the message is in
8-bit format and if it is going to a MIME-capable
destination that requires 7-bit data, the message
body will be converted to 7 bits by using either
quoted-printable or Base64 (EightBitMode on page 1025).
Not all datatypes should be converted to 7 bits,
however. The types that might possibly be converted
are listed with the Content-Transfer-Encoding: header
(Content-Transfer-Encoding:
on page 1154). One type that should not be
converted, for example, is the quoted-printable type
because it is already converted. Types that can be
converted are 7bit, 8bit, and binary.
Beginning with V8.7 sendmail, the
class $=e is used
to determine whether a type will be encoded. Only
those values listed in this class will be encoded.
When sendmail first starts, it
initializes the list of values in class $=e to be:
7bit 8bit binary
You can add types to this class, but you can never remove them.
Note that a type in class $=e can still be prevented from being
encoded on the basis of the considerations imposed
by class $=n.
Also note that the actual encoding can be restricted
to quoted-printable by use of the class $=q.
The local UUCP name V8.6.5 and later
When sendmail first begins to
run, it figures out what your local UUCP node name
is and assigns the result to the $k macro ($k on page 831). At the same
time, it assigns the same name to this class
$=k.
List of local domains V8.7 and later
When sendmail first begins to
run, it figures out what your DNS domain is and
assigns the result to the $m macro ($m on
page 833). The sendmail program
then processes the configuration file. This gives
you the opportunity to redefine $m. After that,
sendmail assigns the final
value in $m to
the class $=m.
Unfortunately, prior to V8.10
sendmail, the class macro
$=m was not
used by sendmail, or by any of
the configuration files produced by the
m4 technique. Beginning with
V8.10, $=m is
used as part of screening to allow relaying. Note
that $=m should
not be used to have mail accepted as local under a
variety of domains. Instead, use FEATURE(domaintable)
(FEATURE(domaintable) on page 621).
Don’t encode these Content-Types V8.7 and later
Although some MIME content types can be converted to 7
bits, not all types should be. Content types are
defined by the Content-Type: header (Content-Type: on page 1154). For
example, the type multipart/ should not be converted,
whereas its component boundary-separated parts
probably should be. Conversion is done by encoding
with either quoted-printable or Base64 (EightBitMode on page 1025).
Beginning with V8.7 sendmail,
types that should not be encoded are those defined
as members of the class $=n. When sendmail
first starts to run, it defines the following list
of values for class $=n:
multipart/signed
As of V8.10, no other useful values exist for this class.
Note that a type in class $=n can still be prevented from being
encoded based on the considerations imposed by class
$=e. Also note
that the actual encoding can be restricted to
quoted-printable by use of the class $=q.
Macros preserved in the qf file V8.10 and later
When a message is first accepted,
sendmail usually queues it
first,[336] then tries to deliver it. The qf file contains all the
envelope information about a message, including
information specific to the
sendmail delivery process,
and several macros whose values are important to
preserve between queue runs. This {persistentMacros} class
holds the names of those important macros.
When V8.10 sendmail and later
starts to run, it adds to the {persistentMacros} class
a list of five macro names:
The $r
macro ($r on page 842)
holds the protocol used to receive a message when
it was first accepted.
The $s
macro ($s on page 844)
holds the hostname of the sender’s machine.
The $_
macro ($_ on page
801) holds the validated hostname and address,
RFC1413-validation (if available), and IP source
route information associated with the incoming
SMTP connection.
The ${if_addr} macro (${if_addr}
on page 827) holds the IP address of the interface
on which the message was received.
The ${daemon_flags} macro (${daemon_flags} on page 818) holds the flags specified by the
DaemonPortOptions option (DaemonPortOptions on page 993).
To add macro names to this class, omit the leading
dollar symbol. For example, you might add the macro
${MyMacro} like
this:
LOCAL_CONFIG
C{persistentMacros} {MyMacro}However, you are strongly advised not to add any macros to this class. Should you feel the need to do so, take enough time to fully examine how that macro is used in rule sets, and how it can be used internally by sendmail. Then cautiously test and observe to be certain nothing broke when you added it.
Always quoted-printable encode Content-Type: V8.8 and later
The EightBitMode
(8) option
(EightBitMode on page 1025)
determines when and how 8-bit data will be encoded
into a 7-bit format. Ordinarily, the decision to use
quoted-printable as opposed to Base64 is made by
examining the input stream and choosing
quoted-printable if less than 1/8 of the first 4
kilobytes of data has the high bit set. Otherwise,
encoding is with Base64.
Beginning with V8.8, sendmail
offers the class $=q as the means to force the selection
of quoted-printable. Just before scanning the input
data, sendmail extracts the
type and
subtype from the
Content-Type:
header (Content-Type: on page
1154):
Content-Type: type/subtype; ...If the type is in the class
$=q, the body
will definitely be encoded with quoted-printable if
encoding occurs. Also, if a concatenation of
type, a slash (/), and
subtype is in class
$=q, the body
will definitely be encoded with
quoted-printable.
When sendmail first begins to
run, class $=q is
empty. A reasonable value in most countries might be
text/plain
(although probably not in countries that use 16-bit
characters, such as China). Other values for this
class might be text or text/html.
Mark a successful DNS lookup V8.12 and later
FEATURE(accept_unresolvable_domains)
(FEATURE(accept_unresolvable_domains) on page 614) allows all mail to be received, even
when the domain part of the envelope-sender address
cannot be looked up. This feature is implemented in
rules, in part, by using the $={ResOk} class macro to
hold a value that indicates that an unresolved,
envelope-sender address is acceptable.
The $={ResOk} class
macro is strictly intended for use by this feature
and should not be used for anything else, or be
modified in any way.
Hosts for whom to relay V8.9 and later
The class $=R holds
as its list of values the host and domain names that
sendmail should allow mail to
be relayed to. This $=R class should not be used directly
because it could change without notice in future
versions of sendmail. See
RELAY_DOMAIN (The RELAY_DOMAIN mc macro
on page 269) and RELAY_DOMAIN_FILE (The RELAY_DOMAIN_FILE mc macro
on page 269).
Possible values for TLS policy in access map V8.12 and later
The tls_server rule
set is called at the start of any connection in
which the local sendmail would
normally issue the STARTTLS SMTP command. The
tls_client rule
set is called at the start of any inbound connection
in which the STARTTLS SMTP command was offered. Both
rule sets look up information in the
access database. (See The access database with tls_server and
tls_client
on page 214 for a full description of this
process.)
The tls_server rule
set prefixes its lookups with a literal TLS_Srv: expression, and
the tls_client
rule set prefixes its lookups with a literal
TLS_Clt:
expression. Among the possible returned values from
the lookup can be two special keywords:
TLS_Srv:hostA.domain VERIFY
TLS_Clt:hostB.domain ENCR:bitsThese two special keywords (VERIFY and ENCR) are not
defined inside sendmail.
Instead, they are defined as values given to the
class $={tls}
(prior to V8.13) or $={Tls} (V8.13 and later).
This class macro is properly defined in your default configuration file and should never need adjustment.
Presume an RFC2822 7-bit body V8.7 and later
An email message as defined by RFC822 cannot contain
8-bit data. Consequently, when the MIME Content-Type: header
declares a message subtype that is rfc822, we immediately
know that it will contain nothing that needs 8- to
7-bit encoding:
Content-Type: message/rfc822
As other message subtypes evolve, this assumption can
safely be made about them too. So, to make
sendmail more adaptable, the
$=s class was
added beginning with V8.7. This class contains a
list of subtypes that should be treated the same as
rfc822. When
sendmail first begins to run,
it initializes that list to contain:
rfc822
Other subtypes that can legitimately appear here might
be partial or
delivery-status.
Note that this provides only an initial hint to
sendmail. The rfc822 subtype can
itself contain MIME information that might require
8- to 7-bit encoding.
List trusted users V8.7 and later
Trusted users are those who can run
sendmail with the -f command-line switch
to specify who sent the message, without generating
a warning. Prior to V8.6
sendmail, such users had to
be listed with the T command (Declare trusted users (ignored V8.1 through
V8.6)
on page 174). That command was ignored in V8.1
through V8.6, and with those versions anyone could
use the -f
switch. Beginning with V8.7
sendmail, the T command was
reintroduced, but it now causes the list of trusted
users to be added to the class $=t. Now, any user who
uses the -f
switch and who is not listed in class $=t will cause the
following error message (X-Authentication-Warning: on page
1167) to be included in the outgoing mail message
(if the PrivacyOptions option, PrivacyOptions on page 1065, has
authwarnings
set):
X-Authentication-Warning: user set sender to other using -f
See FEATURE(use_ct_file) (FEATURE(use_ct_file) on page 643) for an easy way to add users to this
class using the m4
technique.
List of our other names All versions
Before the sendmail program reads
its configuration file, it calls
gethostbyname(3) or
getipnodebyname(3) to find
all the known aliases for the local machine. The
argument given to
gethostbyname(3) or
getipnodebyname(3) is the
value of the $w
macro that was derived from a call to
gethostname(3) ($w on page 850).
Depending on the version of
sendmail you are running, the
aliases that are found will be either those from
your /etc/hosts file or those
found as additional A or AAAA records in a DNS lookup. Then,
depending on the DontProbeInterfaces option (DontProbeInterfaces on page 1023),
sendmail will round out that
picture by examining (probing) each network
interface and extracting from it the associated IP
address or hostname.
To see the aliases that sendmail
found, or to see what it missed and should have
found, use the -d0.4 debugging switch (-d0.4 on page 542). Any aliases that
are found are printed as:
aka: aliasDepending on your version of
sendmail, each alias is either a
hostname (such as rog.stan.edu)
or an IPv4 address (such as
[123.45.67.8]), or an IPv6
address (such as
[IPv6:2002:c0a8:51d2::23f4]).
Prior to V8.13, sendmail would also add leading name
components to the list of host names in $=w (for example, for
the hostname a.b.c.d, it would
add a and
a.b). Also prior to V8.13,
each such name found (if not duplicated) would be
reverse-looked-up to find its IP number and that IP
number would be added to the list. Beginning with
V8.13, these two steps are skipped. If you are
running pre-V8.13 sendmail and
you desire those hostname variations to be added to
the list of hostnames, you will henceforth have to
add them to class $=w yourself.
Many sendmail.cf files use the
$=w class macro
to define all the ways users might reference the
local machine. This list must
contain all names for the local machine as given in
the /etc/hosts file, all names
for the local host as listed in DNS (including CNAME
and MX records), and the names associated with your
network interfaces. For example:
# All our routing identities Cw server1 server2 # All our local aliases Cw localhost mailhost tops-link print-router loghost # DNS records Cw serv-link # We are a bitnet registered node Cw bitserver
The correct way to add these domains to $=w in your
mc file is with LOCAL_DOMAIN,
like this:
LOCAL_DOMAIN(`server1 server2') LOCAL_DOMAIN(`localhost mailhost tops-link print-router loghost') LOCAL_DOMAIN(`serv-link') LOCAL_DOMAIN(`bitserver')
Another correct way to add hostnames to class $=w is with FEATURE(use_ct_file)
(FEATURE(use_cw_file) on page 643).
In addition to hostnames, you can also add addresses
to the $=w class.
To do so, just surround each address with square
braces:
LOCAL_DOMAIN(`[123.45.67.8]') ← IPv4 address LOCAL_DOMAIN(`[IPv6:2002:c0a8:51d2::23f4]') ← IPv6 address
Note in the second example that you must prefix any
IPv6 addresses with a literal IPv6: expression. That
prefix signals to sendmail that
it is dealing with an IPv6 address.
[331] * Note that when
a class name is a single character, it can be
referenced with or without enclosing curly braces,
with no change in meaning. That is, CX and C{X} are
equivalent.
[332] * This was removed from V8.1 sendmail because it presented a security risk. It was restored to V8.7 and later because sendmail now checks permissions more carefully and exec(2) is the program itself, instead of using the old, buggy popen(3) approach of yore.
[333] * The version of sendmail that you are using must have been compiled with SCANF defined (SCANF on page 137) for scanf(3) to be usable from within the configuration file.
[334] * With V8 and later, words in a class can be multitokened.
[335] * Other than the
{
character.
[336] * If the SuperSafe option (SuperSafe on page 1096) is false, or
interactive with the DeliveryMode option (DeliveryMode on page 1004) also set to
interactive, and if the DataFileBufferSize (DataFileBufferSize on page 998) and
XscriptFileBufferSize (XscriptFileBufferSize on page 1117)
options are large enough, it is possible that no
mail will ever hit the disk.