Database maps can be used to look up information in databases, to perform transformations (such as dequoting), to perform computations, and to store values into macros. In their database role, they offer these advantages:
Information can be easily changed without having to restart sendmail because database information is external to the configuration file.
The sendmail program starts up faster because only the location of the information is stored at startup, not the information itself.
Rules are made more versatile because database information can be used in the RHS of rules. Class macros are still of use in the LHS.
To fully appreciate sendmail databases, consider
the only alternative, the F
configuration command. For example, mail that is sent via UUCP is a
typical application that requires lists of information:
FU /etc/mail/uuhosts
Here, the external file /etc/mail/uuhosts
contains a list of UUCP hosts connected to the local machine. If the
list rarely changes, the F
command is appropriate. On the other hand, if the list is volatile
and changes often, the F command
has drawbacks. The file /etc/mail/uuhosts is
read only when the configuration file is processed. Any change to
that file is ignored by a running sendmail
(such as the daemon). To make the change effective, the daemon needs
to be restarted.
In such volatile situations, storing UUCP information in a database is preferred. A change to a database is immediately available to the running daemon, eliminating the need to restart.
V8 sendmail is designed to rewrite addresses on
the basis of information looked up in external databases or in its
internal symbol table. It can use a wide variety of database forms,
ranging from ndbm(3) files (dbm on page 903) to Hesiod network database maps (hesiod on page 909). The K configuration command (The K Configuration Command on page 882) is used
to declare the name, location, and other parameters of databases or
to modify use of its symbol table.
In their nondatabase role, database maps can also be used to perform a wide range of services that make the use of rules and rule sets easier and more versatile. For example, database maps can be used to:
Assign a value to a macro
Log information using the syslog facility
Perform mathematical computations and comparisons
Remove quotation marks from quoted strings
The $( and $) database-map operators (Use $( and $) in Rules on page
892) are used in the RHS of rules to access and utilize the
information produced by all the database-map roles.
Vendors that provide V8 sendmail in
precompiled form might or might not provide access to all
the types of databases that V8 sendmail
supports. If your online documentation lacks this
information, you can run sendmail with
the -d0.4 debugging
switch to discover what it supports:
% /usr/sbin/sendmail -d0.4 -bt
Version 8.14.1
Compiled with: MAP_REGEX LOG MIME7TO8 MIME8TO7 NAMED_BIND NETINET
NETUNIX NIS NEWDB QUEUE SCANF SMTP TCPWRAPPERS USERDB
XDEBUG
...In this implementation of sendmail the
following databases are available: regular-expression (the
MAP_REGEX), Sun nis (the NIS), the
bestmx
database-map type (the NAMED_BIND), and the Sleepycat DB’s
hash and btree types (the NEWDB).
Many internal database maps needed by
sendmail are also automatically
included without being enabled. They are text, stab, implicit, user, host, program, sequence, null, syslog, arith, macro, and switch. Note that hesiod and nisplus database maps are
not supported by this particular
sendmail binary (neither HESIOD
nor NISPLUS was printed in the preceding output).
If you download and compile sendmail
yourself, you can include any supported databases. Support
is declared in your m4 Build file. For
example, the following includes support for the dns database-map
type:
APPENDDEF(`confMAPDEF', `-DDNSMAP')
Here, APPENDDEF is used to append the compile-time switch to any previous definitions. The -DDNSMAP is the compile-time switch that, when given a positive, nonzero value, enables inclusion of that support.
Possible compile-time switches are shown in Table 23-1.
|
Switch |
§ |
Database support included |
|
-DDNSMAP |
dns on page 905 |
dns lookups (V8.12 and later) |
|
-DHESIOD |
hesiod on page 909 |
hesiod(3) aliases, and userdb |
|
-DLDAPMAP |
ldap (was ldapx) on page 912 |
ldap(3) |
|
-DMAP_NSD |
nsd on page 929 |
IRIX |
|
-DMAP_REGEX |
regex on page 932 |
Regular expression support |
|
-DNDBM |
dbm on page 903 |
ndbm(3) database files (dbm) |
|
-DNAMED_BIND |
bestmx on page 902 |
bestmx(3) DNS lookups |
|
-DNETINFO |
netinfo on page 926 |
NeXT netinfo(3) aliases only |
|
-DNEWDB |
btree on page 901 |
db(3) hash and btree databases, and userdb |
|
-DNIS |
nis on page 927 |
Sun NIS network database maps |
|
-DNISPLUS |
nisplus on page 928 |
Sun NIS+ network database maps |
|
-DPH_MAP |
ph on page 930 |
PH database maps |
|
-DSOCKETMAP |
socket on page 936 |
Socket database maps (V8.13 and later) |
For example, the default Build m4 file for Ultrix (in devtools/OS/ULTRIX) might include this line:
define(`confMAPDEF', `-DNDBM=1 -DNIS=1')
which includes support for ndbm(3) and nis(3) database maps, whereas the m4 file for SunOS 5.5 might include the following:
define(`confMAPDEF', `-DNDBM=1 -DNIS=1 -DNISPLUS=1 -DMAP_REGEX=1')
which also includes support for the nisplus database map and regular expressions.
Beginning with V8.9, sendmail automatically determines whether NEWDB should be included by default. Only nonstandard locations of the db libraries will prevent this. So, in addition to the database support shown earlier, standard installations will also have db(3) support.
If you omit all database support with a declaration such as this in your m4 Build file:
define(`confMAPDEF', `')
and if your db libraries are in a
nonstandard location, a sendmail binary
will be created that will be unable to maintain its aliases
in database format. Also, any attempt to rebuild the
aliases database (with
newaliases or with -bi) will fail with the
following error message:
Cannot rebuild aliases: no database format defined Cannot create database for alias file /etc/mail/aliases: No such device
Note that if you add new database-map types, you might also
have to add to your m4 Build
configuration file libraries with the confLIBS compile-time
macro (confLIBDIRS on page 82) and
#include-file
directories with the confINCDIRS compile-time macro (confINCDIRS on page 78). For
example:
APPENDDEF(`confINCDIRS', `-I/packages/include/db') APPENDDEF(`confLIBDIRS', `-L/packages/lib') APPENDDEF(`confMAPDEF', `-DNEWDB')
Here, support for db(3) is included where it otherwise would not have been because of its nonstandard location in /packages.
The makemap program, supplied in source form with V8 sendmail, is fully described in The makemap Program on page 370. It is used to create database files and is run, in brief, from the command line like this:
% makemap type file < textfileThe type can be either
dbm (which uses the
ndbm(3) library routines),
hash, or
btree (both of which use the
db(3) library routines). The
file is the location
and name (full path or relative name) for the
database file to create. For
dbm files, the
.pag and
.dir suffixes are added
automatically. For db files,
the .db suffix will be added
automatically if it is not already included in the
name.
The makemap program reads from
its standard input. That input is line-oriented and
contains the text from which the database files will
be created. Lines that begin with a # are interpreted as
comments and ignored. Lines that contain no
characters (empty lines) are also ignored.
Whitespace (spaces or tabs) separates the
key on the left from the
data on the right. An example
of such an input file is the following:
lady relaysite!lady my.host relaysite!lady bug bug.localuucp
The second line in this example shows that
keys can be multitokened
(my.host is
three tokens). In reading from existing files, some
conversion might be required to massage the input
into a usable form. To make a database of the
/etc/hosts file (for
converting hostnames into IP addresses), for
example, a command line such as the following might
be required:[337]
% awk '/^[^#]/ {print $2, $1}' /etc/hosts | makemap ...Here, awk(1) needs to eliminate
comment lines (the /^[^#]/). Otherwise, it will wrongly
move them to the second column, where
makemap will not recognize
them as comments.
The K configuration command
is used to associate a symbolic name with a database-map
type. The symbolic name will later be used in the RHS of
rules. The form of the K
command looks like this:
Kname type argsThe name is the symbolic name, the
type is the kind of
database map to use, and the args
specifies its location and properties. We describe each in
turn.
The name portion of the
K configuration
command immediately follows the K. Whitespace between
the K and the
name is
optional:
K name type args ↑ optional whitespace
The name must begin with a letter or digit and can contain only letters, digits, and the underscore character:
K local_hosts ← good K $andcents ← bad
The case of the letters in
name does not matter.
All names are converted to lowercase before they are
stored:
K LOCAL_Hosts
K local_hosts ← the sameIf you begin a name with a
bad character, the following error will be printed
and that K line
will be ignored:
configfile: line num: readcf: config K line: no map name
If a bad character appears in the middle of a name,
the part preceding the bad character will be taken
as the name, and the part
following the bad character will be taken as the
type. For example, the
name
me@home will produce this
error:
configfile: line num: readcf: map me: class home not available
Recall that the type[338] portion of the K configuration command follows the
name:
Kname type argsNote that whitespace between the
name and the
type can be a joined
indented line, which allows commenting and improves
readability:
Kname # Why this name type # Why this type args # and so on
The type declares which
sort of database map to use. It must be one of the
types listed in Table 23-2.
|
Type |
§ |
Versions |
Description |
|
|
arith on page 898 |
V8.10 and later |
Perform arithmetic computations. |
|
|
btree on page 901 |
V8.1 and later |
A db(3) form of database. |
|
|
bestmx on page 902 |
V8.7 and later |
Look up the best MX record for a host. |
|
|
dbm on page 903 |
V8.1 and later |
Really ndbm supplied with most versions of Unix. |
|
|
dequote on page 904 |
V8.6 and later |
Remove quotation marks. |
|
|
dns on page 905 |
V8.12 and later |
Look up information using DNS. |
|
|
hash on page 908 |
V8.1 and later |
A db(3) form of database. |
|
|
hesiod on page 909 |
V8.7 and later |
MIT network user authentication services. |
|
|
host on page 910 |
V8.1 and later |
Internal table to store and look up hostnames. |
|
|
implicit on page 911 |
V8.1 and later |
Search for an aliases database entry. |
|
|
ldap (was ldapx) on page 912 |
V8.8 and later |
The Lightweight Directory Access Protocol (LDAP). |
|
|
ldap (was ldapx) on page 912 |
V8.9 and earlier |
Replaced by |
|
|
macro on page 925 |
V8.10 and later |
Store a value into a macro via a rule. |
|
|
netinfo on page 926 |
V8.7 and later |
NeXT, Darwin, and Mac OS X network information services. |
|
|
nis on page 927 |
V8.1 and later |
Sun’s Network Information Services (NIS). |
|
|
nisplus on page 928 |
V8.7 and later |
Sun’s newer version of NIS (NIS+). |
|
|
nsd on page 929 |
V8.10 and later |
IRIX |
|
|
null on page 929 |
V8.7 and later |
Provide a never-found service. |
|
|
ph on page 930 |
V8.10 and later |
CCSO Nameserver (ph) lookups. |
|
|
program on page 931 |
V8.7 and later |
Run an external program to look up the key. |
|
|
regex on page 932 |
V8.9 and later |
Use regular expressions. |
|
|
sequence on page 935 |
V8.7 and later |
Search a series of database maps. |
|
|
socket on page 936 |
V8.13 and later |
Connect to a socket for a database. |
|
|
stab on page 938 |
V8.10 and later |
Internally load aliases into the symbol table. |
|
|
switch on page 938 |
V8.7 and later |
Build sequences based on service switch. |
|
|
syslog on page 939 |
V8.10 and later |
Log information using syslog(3) via rule sets. |
|
|
text on page 941 |
V8.7 and later |
Look up in flat text files. |
|
|
userdb on page 942 |
V8.7 and later |
Look up in the User Database. |
|
|
user on page 945 |
V8.7 and later |
Look up local passwd information. |
All of these database-map types are described in Alphabetized Database-Map Types on
page 898 at the end of this chapter. If the
type is not one of
those listed, or if support for the
type was not compiled
in, the following error is printed and the K command is
ignored:
configfile: line num: readcf: map name: class type not available
The args of the K configuration command
follow the symbolic name
and type:
Kname type argsThe args specify (among
other things) the location of the database file or
the name of a network database map. The args is like a miniature
command line, and its general form looks like
this:
switches file_or_mapThe switches are letters
prefixed with a -
character that modify the use of the database.
(We’ll discuss them in the next section.) The
file_or_map is the
location of the database file or the name of a
network database map. The
file_or_map should
exclude the .pag and
.dir suffixes for
dbm-type files and exclude
the .db suffix for
hash, or
btree-type files.
A database map is opened for reading when the
configuration file is processed. If the
file cannot be opened
(and the -o is
omitted, -o on page 889), an
appropriate error is printed. The
file_or_map should be
an absolute pathname of a file (such as
/etc/mail/uuhosts) or a
literal network database-map name (such as
hosts.byname). An nis database-map
specification can include a domain:
map@domain
Relative filenames (names that omit a leading /) are interpreted as
relative to the queue directory and should never be
used.
The database files must live in a safe directory (one
whose every component is writable only by
root or the user defined by
the TrustedUser
option, TrustedUser on page 1112).
If the file itself is unsafe or its directory is
unsafe, one of several errors will be printed or
logged, depending on how you run
sendmail. (See the
description of the DontBlameSendmail option DontBlameSendmail on page 1009 for
more information about this safety check.)
The switches must follow the
type and precede the
file_or_map:
Kname type switches file_or_mapIf any switches follow
file_or_map, they will be
silently ignored.[339] All switches begin
with a - character and
are listed in Table 23-3. Note
that some database-map types utilize only a small subset of
all switches (e.g., dequote uses only -a, -D, -s, and -S, and sequence doesn’t use
any).
|
Switch |
§ |
Description |
|
|
The −1 ldap database-map switch on page 915 |
Consider successful only if exactly one key
is matched ( |
|
|
-A on page 886 |
Append values for duplicate keys |
|
|
-a on page 887 |
Append tag on successful match |
|
|
DNS database-map -B switch on page 908 |
Append domain before the lookup ( |
|
|
The -b ldap database-map switch on page 915 |
Base from which to begin the search
( |
|
|
The -b regex database-map switch on page 933 |
Use basic, not extended, regular expression
matching ( |
|
|
-D on page 887 |
Don’t use this database map if |
|
|
The -d ldap database-map switch on page 915 |
DN to bind to server as ( |
|
|
The -d regex database-map switch on page 934 |
The delimiting string ( |
|
|
Timeout.resolver (V8.10 and later) on page 1108 |
The res_search( )
|
|
|
-f on page 887 |
Preserve case |
|
|
The -h ldap database-map switch on page 916 |
Hosts that serve this network database
( |
|
|
The -h ph database-map switch on page 931 |
Hosts that serve this network database
( |
|
|
-k on page 888 |
Specify column for key |
|
|
The -k ldap database-map switch on page 917 |
The search query ( |
|
|
netinfo on page 926 |
The property that is searched ( |
|
|
The -k ph database-map switch on page 931 |
Specify a list of fields to query ( |
|
|
syslog on page 939 |
The logging level at which to log ( |
|
|
-l (lowercase L) on page 888 |
Time limit to timeout connection ( |
|
|
The -M ldap database-map switch on page 917 |
The method to use for binding ( |
|
|
-m on page 888 |
Suppress replacement on match |
|
|
-N on page 889 |
Append a null byte to all keys |
|
|
The -n ldap database-map switch on page 917 |
Retrieve attribute names only, not values
( |
|
|
The -n regex database-map switch on page 934 |
NOT, that is, invert the test ( |
|
|
-O on page 889 |
Never add a null byte |
|
|
-o on page 889 |
The database map is optional |
|
|
The -P ldap database-map switch on page 917 |
The secret password to use for binding
( |
|
|
The -p ldap database-map switch on page 917 |
Port to use when connecting to host
( |
|
|
-q on page 889 |
Don’t strip quotes from key |
|
|
The -R ldap database-map switch on page 917 |
Don’t auto-chase referrals ( |
|
|
dns on page 905 |
Record type to look up ( |
|
|
The -r ldap database-map switch on page 918 |
Allow dereferencing of aliases ( |
|
|
Timeout.resolver (V8.10 and later) on page 1108 |
The res_search( )
|
|
|
-S on page 890 |
Space replacement character for database map |
|
|
The -s ldap database-map switch on page 918 |
Search scope of “base,” “one,” or “sub”
( |
|
|
The -s regex database-map switch on page 934 |
Substring to match and return ( |
|
|
-T on page 890 |
Suffix to append on temporary failure |
|
|
-t on page 891 |
Ignore temporary errors |
|
|
The -V ldap database-map switch on page 918 |
Specify return attribute list separator
( |
|
|
-v on page 891 |
Specify the value’s column |
|
|
netinfo on page 926 |
The property to return ( |
|
|
ph on page 930 |
Specify a list of fields to return ( |
|
|
The -v ldap database-map switch on page 919 |
Specify the list of attributes to return
( |
|
|
DNS database-map -Z switch on page 908 |
Limit the number of items to return
( |
|
|
The -Z ldap database-map switch on page 921 |
Limit the number of matches to return
( |
|
|
DNS database-map -z switch on page 908 |
Allow multiple returns and the delimiting
character ( |
|
|
-z on page 891 |
Specify the column delimiter |
If a switch other than those listed is specified, that switch
either is silently ignored or an error reports, depending on
the version of sendmail and the
particular type.
In the sections that follow, we document the switches that are common to a number of database-map types. Those that are unique, or unique in meaning, to a particular database-map type are listed with the type.
Append values for duplicate keys V8.7 and later
Ordinarily, when sendmail builds (rebuilds) an aliases database, it objects to duplicate keys on the left of the colon:
staff: bill
staff: leopold ← this is an errorBut sometimes—for example, in automating—such
duplicates are necessary. In such instances, the
-A switch can
be used with the AliasFile (A) option (see AliasFile on page 970) to cause
duplicates to be silently appended:
staff: bill
staff: leopold
... silently modified by sendmail to internally become
staff: bill, leopoldNote that this process is further illustrated in Duplicate Entries and Automation on page 477.
The -A database
switch is useful only with alias files because those
are the only files that
sendmail rebuilds on its own.
Beginning with V8.10, this switch is also useful
with the ph type
(ph on page 930).
Append tag on successful match V8.1 and later
When a key is looked up in a database (from inside the
$( and $) operators of the RHS
of rules) a successfully found key is replaced by
its data. If the -a switch is given, the text following
that switch, up to the first delimiting whitespace
character, is appended to the replacement data. For
example:
-a appends nothing -a. appends . -a,MAGICTOKEN appends ,MAGICTOKEN
The text to be appended is taken literally. Quotation
marks and backslashed characters are included
without interpretation, so whitespace cannot be
included in that text. Because the rewritten RHS is
normalized as an address, special address
expressions (such as parentheses) should be avoided.
The use of appended text is one of two methods used
for recognizing a successful lookup in rules. We’ll
discuss the other, $:, in Specify a Default with $: on
page 893.
Don’t use if DeliveryMode=defer V8.10 and later
The defer setting
of the DeliveryMode option (DeliveryMode on page 1004) is intended
for sites that do not have a continuous connection
to the Internet (specifically, dial-on-demand
sites). For such sites, mail should be placed in the
queue without interacting with the Internet (which
is likely unavailable). Then, when the Internet
connection is made, a normal queue run will deliver
the mail.
Some database maps (such as those that look up hosts
and possibly those that log messages with
syslog) should probably not
be used when sendmail is
running in defer
mode. This -D
database switch can also be used with a few
database-map types. When it is, it advises those
types to not operate when
sendmail is in defer mode.
Preserve case V8.1 and later
Ordinarily, sendmail will
normalize a key to lowercase before looking it up in
a database. If the keys in the database are
case-sensitive (“TEX” is considered different from
“tex,” for example), the -f database switch should be used to
prevent this normalization. Note that if the
-f switch is
omitted (the default), the database must have been
created with all lowercase keys (also the
default).
Also note that when the -f switch is used with the regex database-map type,
it causes the regular expression match to be made in
a case-insensitive manner.
Specify column for key or key name V8.7 and later
Beginning with V8.7, sendmail began to support a flat text-file form of database. The /etc/hosts file is an example of such a flat file, in that it is organized in a line-by-line manner:
123.45.67.89 here.our.domain
When such files are read as databases (with the
text type,
text on page 941) you need to
specify which column contains the key and which
contains the value.
For nisplus,
netinfo, and
ph database
maps, the -k
switch specifies the name (text) of the desired
column.
When the -k switch
specifies which column contains the key, its absence
defaults to 0 for the text type (which is indexed beginning
with 0) and defaults to the name of the first column
for the nisplus
type. See also -v
(-v on page 891) for the
returned value’s column, and -z (-z on page 891) for the column
delimiter.
Finally, note that for ldap database maps, the -k switch has a
different meaning, one that is particular to that
type.
Set a timeout for the lookup V8.12 and later
When doing a lookup, the -l switch sets a time limit for how
long to wait for a reply:
-l5
Note that the limit is not a general time expression
(that is, 15m
still evaluates to 15 seconds).
Also note that this -l switch is not available for all
database-map types. As of this writing, it is
available only with the ldap and ph database-map types.
Suppress replacement on match V8.1 and later
Ordinarily, a successful lookup in a database map
causes the key to be replaced by its value. When the
intention is to merely verify that the key exists
(not to replace it) the -m switch can be used to suppress
replacement.
For example, the values that are returned from the
hosts.byname NIS database map
are not generally useful (they contain multiple
hostnames). In looking up a key in this database map
(with $( and
$); see Use $( and $) in Rules
on page 892), the -m switch prevents those multiple names
from wrongly replacing the single hostname in the
key. Note that the -a switch (-a on
page 887) can still be used to append a suffix to a
successful lookup. Also, the $:default
(Specify a Default with $: on
page 893) is still used if the lookup fails.
Append a null byte to all keys V8.1 and later
If a database was created with
makemap’s -N switch (-N on page 374) to include the
terminating zero byte with each key, this -N switch should be
specified with the corresponding K configuration command
to force all lookups to also include a zero byte.
Note that -N is
not needed for the nis type and, if included, is ignored.
See also -O in
-O on page 889.
Never add a null byte V8.2 and later
If neither -N nor
-O is
specified, sendmail uses an
adaptive algorithm to decide whether to look for the
terminating zero byte. The algorithm starts by
accepting either possibility. If the first key
looked up is found to end with a terminating zero
byte, the algorithm will thereafter look only for
keys with a terminating zero byte. If the first key
that is looked up is found to not end with a
terminating zero byte, the algorithm will thereafter
look only for keys without a terminating zero
byte.
If this -O switch
is specified, sendmail never
tries a zero byte, which can speed matches. Note
that if both -N
and -O are
specified, sendmail will not
produce an error message, and will never try to
match at all, thus causing all lookups to appear to
fail.
The database map is optional V8.1 and later
Ordinarily, in the case of types that employ disk
files, sendmail will complain
if a specified file cannot be opened for reading. If
the presence of a database file is optional (as it
can be on certain machines), the -o switch should be used
to tell sendmail that the
database is optional. Note that if a database is
optional and cannot be opened, all lookups will
silently fail for rules that use that
database.
Also note that for network-based types of database
maps, this -o
switch can be used to cause failed initializations
to be ignored. If a database map is used during the
processing of a message, and if a lookup fails in
the absence of a -o switch, the message (or SMTP
request) will be rejected with a temporary
failure.
Don’t strip quotes from key V8.7 and later
Ordinarily, sendmail strips all the nonescaped quotation marks (those not prefixed with a backslash) from a key before looking it up. For example, the following key:
"Bob "bigboy" Roberts \(esq\)"@bob.com
will have its nonescaped quotation marks removed and end up looking like this:
Bob "bigboy" Roberts (esq)@bob.com
Note that all escaped characters are de-escaped (have the backslash removed) during this process.
When quotation marks and escaped characters need to be
preserved in a key before it is looked up, you can
use the -q switch
with the K
configuration command. The -q switch suppresses dequoting and
de-escaping.
Space replacement character V8.8 and later
The dequote type
(dequote on page 904) refuses to
remove quotation marks if doing so will result in an
illegal address. For example, internal space
characters are illegal in addresses:
"a b" becomes → "a b"The -S switch
causes all the quoted space characters to be changed
into a character that you specify just before the
dequoting process:
Kdequote dequote -S+
Here, we specify that quoted strings will have quoted spaces converted into a plus sign before dequoting. Therefore, the preceding conversion becomes the following:
"a b" becomes → a+bAs you will see in the reference sections at the end
of this chapter, this -S database switch can be used with a
few other types as well.
Suffix to append on temporary failure V8.10 and later
When a resource is temporarily unavailable, it would be handy if sendmail indicated that unavailability when the database lookup fails. Consider NIS, for example. It can time out when a server is down briefly, but a failed lookup of a user’s login name need not cause a permanent failure under such a circumstance. Instead, something should be returned to show that it is only a temporary failure.
The -T database
switch was added with V8.10
sendmail to solve this
problem. You use it to define a suffix to add to the
key for the returned failure value when the problem
is temporary. You might use it like this:
Kmailservers nis -T.Defer -o mailservers ... R $* <@ $+ > $* $: $1<@$2>$3 <$(mailservers $2 $: Fail $)> R $* <@ $+ > $* <$* . Defer> $# error $@ 4.2.2 $: "450 defer" ← handle failure here R $* <@ $+ > $* <Fail> $# error $@ 5.7.1 $: "550 reject" ← handle failure here R $* <@ $+ > $* <$+> $# smtp $@ $4 $: $1 < @ $2 > $3 ← OK, so send it ...
Note that a permanent failure returns the failure
alternative indicated by the $: operator (the
Fail). But a
temporary failure returns the suffix defined by the
-T, appended to
the original key (the $2) to form $2.Defer.
Note that this definition of temporary failure is
different from that defined by the -D database switch. With
-D, database
lookups are not done at all if the DeliveryMode option
(DeliveryMode on page 1004) is
set to defer.
Also note that this -T database switch affects only the
return value. It does not affect the outcome of mail
delivery. To affect the outcome on temporary
failures, use the -t switch (-t on
page 891).
Ignore temporary errors V8.10 and later
Usually it is acceptable for a lookup to fail because
of a temporary failure of a system resource. When
reading from a network database map (such as the DNS
name server) temporary failures (such as server
down) generally cause email to be requeued for a
later try. However, you might sometimes find it
desirable for a database map’s temporary failures to
be ignored. In such cases, you can enable this
-t database
switch. With it set, a temporary error will cause
the mail to be delivered.
Note that failure of a key to be found in a database
map is not a temporary error. Also note that this
switch just determines the outcome of a message. It
does not affect the nature of the returned value. To
affect the return value on temporary failures, use
the -T database
switch (-T on page 890).
Specify the value’s column V8.7 and later
The manner in which the key and its value are visually
displayed in flat, sequential text files and certain
network services, might not be directly suitable for
use with database maps. A text-type file—for example,
/etc/hosts—might display the
key on the right and the value on the left:
123.45.67.89 here.our.domain
For such circumstances, the -v switch can be used with the K command to specify the
column or item that will be returned as the value
when a key is matched. For example:
Kaddr text -k1 -v0 /etc/hosts
For nisplus,
netinfo,
user, and other
such database maps, the -v switch specifies the name (text) of
the value’s column.
This -v switch
specifies which column is the value to return. If it
is omitted, it defaults to 0 for the text type (which is
indexed beginning with 0) to the last named column
for the nisplus
type, and to the string "members" for the netinfo type. Note that
the -v switch has
a different meaning for the ph database-map type. See also -k (-k
on page 888) for the value’s column and -z (-z on page 891) for the column
delimiter.
Specify the column delimiter V8.7 and later
Flat, sequential text files have columns of information delimited from each other with a variety of characters:
123.45.67.89 here.our.domain ← /etc/hosts uses a whitespace nobody:*:65534:65534::/: ← /etc/passwd uses a colon
The -z switch can
be used to specify a delimiter whenever the default
delimiter of whitespace is not appropriate. In the
case of the /etc/passwd file, a
database declaration might look like this:
Kuid text -z: -k2 -v0 /etc/passwd # map to convert user-id to login name
The default is whitespace for the text type. It is a comma
for the netinfo
type.
For the ldap type,
a -z switch
specifies the character to use to separate values
when building the resulting string when multiple
attribute values are returned.
The information in database maps is accessed in the RHS of rules. This is the basic syntax:
$(name key $)The key is looked up in the
database map whose symbolic name (declared with the K configuration command,
The K Configuration Command on
page 882) is name. If the
key is found, the entire
expression, including the $( and $), is normally replaced with the value
returned for that key.[340] Any suffix, as
specified with the -a
switch (-a on page 887) in the K configuration
declaration for name, is appended
to the data. If the key is not
found, the entire expression is replaced with
key. If the $) is omitted, all tokens
up to but excluding the tab and comment, or end-of-line if
there is no comment, are taken as the key. To illustrate one
use for $( and $), see the following
rule:
R$- . uucp $: $(uucp $1.uucp $)
and the following K
command:
Kuucp hash /etc/mail/uucp
This associates the symbolic name uucp with a hash-type file called /etc/mail/uucp. If the
uucp database contained entries
such as these:
lady.uucp lady.localuucp sonya.uucp sonya.localuucp
a workspace of lady.uucp
would match the LHS, so the RHS would look up $1.uucp (thus, lady.uucp) in the
uucp.db database. Because
lady.uucp is
found, the entire $( to
$) RHS expression
is replaced with lady.localuucp from the database. Any
UUCP hosts other than lady or sonya would not be found in the database,
so the RHS expression would become the original workspace,
unchanged.
Note that the entire RHS is prefixed with a $:. This prevents
sendmail from retesting with
the LHS after the RHS rewrite. If this prefix were omitted,
endless looping could occur.
Also note that the -a
switch of the K command
can be used to simplify the writing of this rule. For
example:
Kuucp hash -a.localuucp /etc/mail/uucpThe -a switch tells
sendmail to append the text
.localuucp to all
successful lookups. Thus, the preceding database can be
simplified to look like this:
lady.uucp lady sonya.uucp sonya
But the preceding rule remains the same:
R$- . uucp $: $(uucp $1.uucp $)
Beyond the simple macros and positional operators we have
shown, the key part can use other
operators and forms of macros. For example, delayed
expansion macros can be useful:
R$&s $: $( uucp $&s $)
Here, the sender’s host is looked up to see whether it is a
UUCP host. The $&
prefix (Use Value As Is with $& on
page 793) prevents the s
macro from being expanded as the configuration file is read.
Instead, its value will change with each piece of mail that
is processed.
Additional examples of database lookups are given with the individual type descriptions at the end of this chapter.
The $: operator can
be used as an alternative to the -a switch (or in
conjunction with it). The $: operator, when it stands between the
$( and $), specifies a default
to use instead of the
key, should a lookup
fail:
R$- . uucp $: $(uucp $1 $: $1.uucp $)
Here, the $- part
of the LHS is looked up in the uucp database. If it is
found, the $( to
the $) in the RHS
expression is replaced by the data from that
database. If it is not found, the $: causes the expression
to be replaced with the $- LHS part and a .uucp suffix ($1.uucp).
This version of our rule further simplifies the contents of the database file. With this rule, the database file would contain information such as the following:
lady lady sonya sonya
The -a is still
used as before to append a .localuucp to each successful
match:
Kuucp hash -a.localuucp /etc/mail/uucp
In the RHS expression, the $: must follow the
key or it loses its
special meaning:
$(name key $: default $)
If the $:default
wrongly precedes the key,
it is used as the key, lookups fail, and
replacements are not as expected. If the $: is present but the
default is missing, a
failed lookup returns an empty workspace.
For more complex substitutions, V8
sendmail offers use of the
$@ operator in
the RHS in conjunction with the $( and $) expressions in
database maps.[341] There can be multiple $@-prefixed texts between the
key and the $: (if present) or the
$), where each
of the texts may
itself be multiple rule-set expressions:
$(name key $@ text1 $@ text2 and text3 $: default $)Each $@text
expression is numbered by position (from left to
right):
$(name key $@ text1 $@ text2 $: default $) ↑ ↑ 1 2
In this numbering scheme the
key is always number 0,
even if no $@s
are listed.
These numbers correspond to literal %
digit expressions in the
data portion of a database map. For example:
lady %0!%1@%2
When a lookup of the key in
the RHS of the rule is successful, the returned
value is examined for %digit
expressions. Each such expression is replaced by its
corresponding $@text from
the rule. In the case of the preceding database map,
%0 would be
replaced with lady (the
key), %1 with text1, and %2 with text2.
To illustrate, consider the earlier database entry and the following rule:
R$- @ $-.uucp $: $(uucp $2 $@ $1 $@ mailhost $: $1@$2.uucp $)
If the workspace contains the address
joe@lady.uucp, the LHS
matches. The RHS rewrites only once because it is
prefixed with the $: operator. The expression between the
$( and $) causes the second
$- from the LHS
(the $2, the
key) to be looked up in
the database whose symbolic name is uucp. Because $2 references lady from the workspace,
lady is found
and the data (%0!%1@%2) is used to rewrite. The
%0 is replaced
by lady (the
key via $2). The
text for the first
$@ ($1 or joe) then replaces the
%1. Then the
second text for the
second $@
(mailhost)
replaces the %2.
Thus, the address joe@lady.uucp
is rewritten to become
lady!joe@mailhost.
If a host other than lady appeared in the workspace, this
RHS would use the $:default
part. Thus, the address
joe@foo.uucp would become
(via the $:$1@$2.uucp)
joe@foo.uucp. That is, any
address that is not found in the database would
remain unchanged.
If there are more $@text
expressions in the RHS than there are numbers in the
value, the excess $@text parts
are ignored. If a %digit in
the data references a nonexistent $@text, it
is simply removed during the rewrite.
All $@text
expressions must lie between the
key and the $:default
(if present). If any follow the $:, they become part of
the default and cease to reference any %digit.
But be aware of a common mistake, which is to confuse
a $number rule
righthand-side expression with %digit
results. For example, you might expect $1 assigned to %1 and $2 assigned to %2 with the following
expression, but you would be wrong:
$(lookup $&{client_addr} $@ $1 $2 $)Here, $1 and
$2 are both
assigned to %1.
Remember, each $@
corresponds to a single %digit, no
matter how many expressions follow the $@. The correct way to
code the preceding expression would look like
this:
$(lookup $&{client_addr} $@ $1 $@ $2 $)Here, the intended association is achieved, where
$1 is correctly
assigned to %1
and $2 is
correctly assigned to %2.
The special database-map type called
host can be declared to
modify name-server lookups with $[ and $]. The special symbolic
name and type pair, host and host, is declared with the $( and $) operators like
this:
Khost host -a.The -a switch was discussed
earlier in this chapter. Here, it is sufficient to
note how it is used in resolving fully qualified
domain names with the $[ and $] operators in the RHS of rules. Under
V8 sendmail, $[ and $] are a special case of
the following database lookup:
$(host lookuphost $)A successful match will ordinarily append a dot to a successfully resolved hostname.
When a host type is declared with
the K command,
any suffix of the -a replaces the dot as the character or
characters added.[342] For example:
$[ lookuphost $] ← found, so rewritten as lookuphost.domain. Khost host -a $[ lookuphost $] ← found, so rewritten as lookuphost.domain Khost host -a.yes $[ lookuphost $] ← found, so rewritten as lookuphost.domain.yes
The first line shows the default action of the
$[ and $] operators in the RHS
of the rules. If lookuphost can be fully qualified, its
fully qualified name becomes the rewritten value of
the RHS and has a dot appended. The next two lines
show the -a with
no suffix (note that with no suffix the -a is optional). In this
configuration file, the fully qualified name has
nothing (not even a dot) appended. The last two
lines show a configuration file with a .yes as the suffix. This
time, the fully qualified name has a .yes appended instead of
the dot.
All available mc database maps are
implemented as FEATUREs. Table 23-4 lists those that
are available. The second column shows you where to find
information about each.
|
FEATURE() |
§ |
Versions |
Description |
|
|
The access Database on page 277 |
V8.9 and later |
A database for mail policy |
|
|
FEATURE(authinfo) on page 616 |
V8.12 and later |
Use a separate database for authentication information |
|
|
FEATURE(bestmx_is_local) on page 617 |
V8.6 and later |
Accept best MX record as local if in
|
|
|
FEATURE(bitdomain) on page 617 |
Deprecated |
Convert BITNET addresses into Internet addresses |
|
|
FEATURE(dnsbl) on page 261 |
V8.10 and later |
Reject based on various DNS blacklists |
|
|
FEATURE(domaintable) on page 621 |
V8.1 and later |
Accept other domains as equivalent to the local domain |
|
|
FEATURE(enhdnsbl) on page 263 |
V8.12 and later |
Enhanced |
|
|
FEATURE(genericstable) on page 622 |
V8.8 and later |
Transform sender addresses |
|
|
FEATURE(ldap_routing) on page 922 |
V8.10 and later |
Reroute recipients based on LDAP lookups |
|
|
FEATURE(mailertable) on page 629 |
V8.1 and later |
Select new delivery agents based on an external database |
|
|
FEATURE(uucpdomain) on page 644 |
Deprecated |
Convert UUCP hosts via a database |
|
|
FEATURE(virtusertable) on page 645 |
V8.8 and later |
Support for virtual domains |
Note that these FEATUREs do
not necessarily need to be used with database files. To
illustrate, consider FEATURE(domaintable) (FEATURE(domaintable)
on page 621). It is included in your mc
file like this:
FEATURE(`domaintable',`nis domaintable')
Here, we specify that the database map is to be the nis type. This causes the
key to be looked
up via NIS and any match to be returned the same way.
FEATUREs that
employ on-disk database files all share the common
default database-map type hash. But if you wish to change that
default to another type, you can do so with the
following mc configuration
command:
define(`DATABASE_MAP_TYPE', `dbm')
Here, we declare the default to be dbm, thereby causing all
such FEATUREs to
use ndbm(3) database files.
Note that if you declare a default, you must do so
before declaring any database FEATUREs.
Many FEATUREs that
take arguments require you to declare the database
type. For example:
FEATURE(`authinfo', `dbm /etc/security/authinfo')
That is, this DATABASE_MAP_TYPE’s default is used only if no argument is given for the feature.
The result of a subroutine call cannot be looked up directly in a database map. Consider this RHS of a rule:
$(uucp $>96 $1 $)
Here, the intention is to pass $1 to rule set 96 and
then to look up the result in the uucp database map.
Instead, the literal value 96 and the value in
$1 are looked
up together and fail first. Then $1 is passed to rule set
96, and the result of that subroutine call becomes
the result of the RHS.
If you are running a Solaris 2.4 or earlier
release of Sun’s operating system, your database
files should not live on tmpfs-mounted filesystems. File locking
was not implemented for tmpfs until Solaris 2.5.
Avoid assuming that all K command switches mean
the same thing for all types. The ad hoc nature of
database-type submissions by outsiders makes that
assumption perilous.
Not all initialization errors or lookup errors
are reported. For some of them you will see an
indication of an error only if you use the
-d38.2
debugging switch (-d38.2 on page
564).
The sendmail program
automatically creates certain database maps as it
needs them. This is done without the need to
declare them with a K configuration command. For example,
consider the following mc
configuration line:
define(`ALIAS_FILE', `/etc/mail/aliases')
When sendmail encounters
this AliasFile
option (AliasFile on page 970)
it automatically creates the
aliases.files database map so
that it can easily look up aliases.
sendmail automatically
creates the following database maps:
aliases.files,
aliases.nis,
aliases.nisplus,
aliases.netinfo,
aliases.hesiod,
passwd.files,
passwd.nis,
passwd.nisplus,
passwd.hesiod, and
users. You should avoid using
these database maps in rule sets because they are
essentially internal to
sendmail and can change
without notice.
Recall that the K
configuration command (The K Configuration Command on page 882)
is used like this:
Kname type argsThe type determines the type of
database map that will be used. For example, the type
btree causes a
db(3)-format database file to
be used, whereas the type dequote causes an internal routine of
sendmail’s to be called.
In this section, we present all the types in alphabetical
order. They are summarized in Table 23-2 on page 883.
Most interaction with these types can be watched by using
the -d38.2 debugging
switch (-d38.2 on page 564). Some specialty
database maps use other debugging switches, which we
indicate where appropriate.
Perform arithmetic computations V8.10 and later
Beginning with V8.10, sendmail
supports arithmetic computations in rule sets via a
database-map type called arith. This form of database map is
always present for your use, without the need for
special compile-time macros. To illustrate one use
for arith,
consider this mini configuration file:
V10 Kmath arith SCalculate R $+ $+ $+ $@ $(math $2 $@ $1 $@ $3 $: EXCEPTION $)
The K configuration
command declares that a database map named math will be of the
database-map type arith. To use this database map we
declare a rule set. We call that rule set Calculate so that
rule-set testing will be mnemonically clear.
The rule is the crux of how this math database map is
used:
R $+ $+ $+ $@ $(math $2 $@ $1 $@ $3 $: EXCEPTION $)
↑ ↑ ↑
operator lvalue rvalueThe arith
database-type database maps (such as math here) take three
arguments. The first, in the position of the
key that would otherwise be
used for lookups, is the arithmetic operator. The
legal operators, as of V8.12, are shown in Table 23-5.
|
Description | |
| [a] | |
|
|
Addition: add |
|
|
Subtraction: subtract |
|
|
Multiplication: multiply |
|
|
Division: divide |
|
|
Less-Than: if |
|
|
Equality: if lvalue is equal to rvalue return literal TRUE, otherwise literal FALSE |
|
|
The bitwise OR operation (V8.12[a] and later) |
|
|
The bitwise AND operation (V8.12[a] and later) |
|
|
The modulo operator: |
|
|
Provide a random value (V8.14 and later) |
[a] a To enable these operators for V8.10 and V8.11, define _FFR_BITOPS when compiling sendmail. | |
If the arithmetic operator used is not one of those
shown in the table (such as an illegal ! operator), the lookup
(calculation) fails and the value following the
$: operator is
returned (the EXCEPTION). If the arithmetic operator
is legal (is shown in the table), a calculation is
performed and the result returned.
The two values used in the computation are passed
following the first and second $@ operators. The
lvalue follows the first
$@ operator,
and the rvalue follows the
second. The arithmetic operation specified is
performed on the two values and the result is
returned.
Computations are always performed using integer calculations, and the values are always interpreted as integer values. A division by 0 always returns a failed lookup (the EXCEPTION). The less-than and equality arithmetic operators return the literal token TRUE or FALSE, indicating the truth of the comparison.
To demonstrate this arith database-map type, you can run
sendmail on the mini
configuration file listed earlier. If that file were
called demo.cf you might test
it like this:
%/usr/sbin/sendmail -Cdemo.cf -btADDRESS TEST MODE (ruleset 3 NOT automatically invoked) Enter <ruleset> <address> >Calculate 1 + 1Calculate input: 1 + 1 Calculate returns: 2 >Calculate 5 / 0Calculate input: 5 / 0 Calculate returns: EXCEPTION >Calculate 5 / 2Calculate input: 5 / 2 Calculate returns: 2 >Calculate −1 * 4Calculate input: −1 * 4 Calculate returns: −4 >Calculate 2 = 2Calculate input: 2 = 2 Calculate returns: TRUE >Calculate 0xff / 2Calculate input: 0xff / 2 Calculate returns: 0
The last three lines show that only decimal integer values can be used. Also note that negative values work properly.
One example of a real use for this type of database map might be a test to see whether the ETRN command should be run if the machine’s load average is too high:
D{OurMaxLoad}20
Scheck_etrn
R $* $: $(math l $@ $&{load_avg} $@ ${OurMaxLoad} $) $1
R FALSE $#error $@ 4.7.1 $: "450 The load average is currently too high."The check_etrn rule
set is called by V8.10 and later
sendmail each time the remote
site sends an ETRN command, and before any reply is
sent to the remote site.
The $& prevents
the {load_avg}
macro (${load_avg}
on page 832) from being interpreted too early (when
the configuration file was read). Consequently, its
current value is compared to
the value in the ${OurMaxLoad} macro. If the truncated
integer value of the load average is higher than our
limit, the request is denied. Note that if ${OurMaxLoad} is
undefined, the rule will return a failed lookup, but
not the literal token FALSE. Thus, by undefining
${OurMaxLoad}
you disable this test.
To fetch a random value using the new r operator (available as
of V8.14) you need to provide lower and upper bounds
for the random number as the first and second
arguments following the operator:
V10 Kmath arith SRandomize R $+ $+ $@ $(math r $@ $1 $@ $2 $)
Here, if the first argument ($1) is numerically less than the second
argument ($2),
the ASCII representation of a pseudorandom value
will be returned that is greater than or equal to
the first and less than or equal to the second. If
the two values are equal, that equal value is
returned. If the first is greater than the second, a
literal r is
returned to indicate an error. If either, or both,
values are non-numeric, the value 0 is
returned.
Only a few database switches are useful with the
arith
database-map type. They are listed in Table 23-6.
Although these switches are allowed, it will take some
inventiveness to devise a use for them with this
arith
database-map type. If you specify a switch that is
not listed in the table, it will be silently
ignored.
The db(3) form of database V8.1 and later
The term btree stands for
“balanced tree.” It is a grow-only form of database.
Lookups and insertions are fast, but deletions do
not shrink the size of the database file.[343] A good description of this form of
database can be found in The Art of
Computer Programming, Vol. 3: Sorting and
Searching, by D.E. Knuth. The btree type is available
only if sendmail was compiled
with NEWDB
defined and the Berkeley or Sleepycat
db library linked (The Sleepycat DB Library on page 104).
In most cases, the hash type (hash on
page 908) will perform slightly better.
Quite a few database switches are available with this database-map type. They are listed in Table 23-7.
|
§ |
Description | |
|
|
-A on page 886 |
Append values for duplicate keys. |
|
|
-a on page 887 |
Append tag on successful match. |
|
|
-D on page 887 |
Don’t use this database map if |
|
|
-f on page 887 |
Don’t fold keys to lowercase. |
|
|
-m on page 888 |
Suppress replacement on match. |
|
|
-N on page 889 |
Append a null byte to all keys. |
|
|
-O on page 889 |
Never add a null byte. |
|
|
-o on page 889 |
The database map is optional. |
|
|
-q on page 889 |
Don’t strip quotes from key. |
|
|
-S on page 890 |
Space replacement character. |
|
|
-T on page 890 |
Suffix to append on temporary failure. |
|
|
-t on page 891 |
Ignore temporary errors. |
One use for this btree type might be to look up users
for whom permission to send offsite email is denied.
The data source file might look like the following,
and might live in the file
/etc/mail/badusers.db (after
makemap was run to create
it):
bob bob ted ted alice alice
A simple configuration file to test this database can then be created like this:
V10 Kbaduser btree -a.BAD -t /etc/mail/badusers R $+ < @ $+ > $* $: $1< @ $2 > $3 < $(baduser $1 $) > R $+ < @ $+ > $* < $* . BAD > $#error $@ 5.1.3 $: "Offsite mailing denied"
Here, the database is declared with the K configuration command.
The -a database
switch causes .BAD to be appended to any key that is
found in the database. The -t switch causes temporary errors to be
ignored. A match causes the workspace to carry the
extra information that is matched by <$*.BAD >, and
which results in an error being reported back to the
sender.
The -d38.20
command-line switch (-d38.20 on
page 568) can be used to observe this type’s lookups
in more detail.
Look up the best MX record for a host V8.7 and later
The bestmx
database-map type looks up a hostname as the
key and returns the
current, single best MX record as the
value. Because bestmx is a type, not a
database map, you need to declare it with a K configuration command
before you can use it:
Kbestmx bestmxOne use for this database-map type might be to see whether a particular host has any usable MX records:[344]
Kbestmx bestmx ... R $*< @ $+ > $* $: $1<@$2>$3 < $(bestmx $2 $: NO $) > R $*< @ $+ > $* < NO > $#smtp $@ $2 $: $1 < @ $2 > $3 R $*< @ $+ > $* < $* > $: $1<@ $[ $2 $] > $3
In the first rule, we look up the host part of an
address (which has already been focused by the
canonify rule
set 3) with the bestmx database map. The result of the
lookup is surrounded with angle brackets and
appended to the original address. The second rule
looks for the NO
caused by an unsuccessful lookup (the $:). The original
address is then sent with the smtp delivery agent. If
the hostname inside the appended angle braces is not
NO, the host
part of the original address is canonicalized with
the $[ and
$]
operators.
bestmx is a special
internal type that can utilize only a few of the
K command
switches, as listed in Table 23-8.
|
§ |
Description | |
|
|
-a on page 887 |
Append tag on successful match. |
|
|
-D on page 887 |
Don’t use this database map if |
|
|
-m on page 888 |
Suppress replacement on match. |
|
|
-q on page 889 |
Don’t strip quotes from key. |
|
|
-T on page 890 |
Suffix to append on temporary failure. |
|
|
-t on page 891 |
Ignore temporary errors. |
|
|
-z on page 891 |
Specify the column delimiter. |
The -z switch
(special for this bestmx database-map type) allows
multiple MX records to be returned, and specifies a
column delimiter used to separate one record from
another. As long as the column delimiter is not a
character that appears in any domain name, it will
be used to separate all the MX records returned by
the MX lookup. These records will be returned in the
new workspace. For example, if the -z switch specified a
comma, and if abc.com were
looked up, the following might be returned:
mail11 . disney . com . , mail . disney . com .
If the -z switch
wrongly specifies a character that can exist in a
domain name (such as a dot), the following error
will be reported and only one MX record will be
returned:
bestmx_map_lookup: MX host mail11.disney.com. includes map delimiter character 0x2E
If too many MX records are returned, the list can be
truncated to avoid an overly long workspace. When
the list is truncated, some MX records can be lost.
This can become a serious problem when this -z switch is used with
this database-map type and when FEATURE(relay_based_on_MX) is also
declared (FEATURE(relay_based_on_MX) on page 271).
This type can be watched with the -d8 debugging switch
(-d8.1 on page 548).
Really ndbm supplied with most versions of Unix V8.1 and later
The dbm
database-map type, which is really the
ndbm form of database, is the
traditional form of Unix database file. Data is
stored in one file, keys in another. The data must
fit in blocks of fixed sizes, so there is usually a
limit on the maximum size (1 kilobyte or so) on any
given stored piece of data. The
dbm database-map type is
available only if sendmail was
compiled with NDBM declared (NDBM
on page 125).
Many database switches are available with this
dbm
database-map type. All are listed in Table 23-9.
|
§ |
Description | |
|
|
-A on page 886 |
Append values for duplicate keys. |
|
|
-a on page 887 |
Append tag on successful match. |
|
|
-D on page 887 |
Don’t use this database map if |
|
|
-f on page 887 |
Don’t fold keys to lowercase. |
|
|
-m on page 888 |
Suppress replacement on match. |
|
|
-N on page 889 |
Append a null byte to all keys. |
|
|
-O on page 889 |
Never add a null byte. |
|
|
-o on page 889 |
The database file is optional. |
|
|
-q on page 889 |
Don’t strip quotes from key. |
|
|
-S on page 890 |
Space replacement character. |
|
|
-T on page 890 |
Suffix to append on temporary failure. |
|
|
-t on page 891 |
Ignore temporary errors. |
This is the database-map type used with
aliases files, if the
hash type is
unavailable. This type is also needed on machines
that employ NIS because the underlying files for
those services are stored in dbm format. Note that
because of the implicit limit on the size of a piece
of data, you should consider using one of the
db(3) hash or btree types
instead.
Remove quotation marks V8.6 and later
V8 sendmail can remove quotation
marks from around tokens by using the special
dequote
database-map type. Because dequote is a type, not a database map,
you need to declare it with a K configuration command
before you can use it:
Kunquote dequoteThis declares a database map named
unquote of the type dequote. Once a
database-map name has been declared, the dequote type can be used
in the RHS of rules to remove quotation marks. It is
used with $( and
$) just like
all database-map lookups:
$(unquote tokens $)Here, arbitrary tokens are
looked up in the database map named unquote. That database
map is special because it is of the type
dequote. Instead of
being looked up in an external database file,
tokens will just have
any surrounding quotation marks removed:
"A.B.C" becomes A.B.C "A"."B"."C" becomes A.B.C "A B" becomes "A B" "A,B" becomes "A,B" "A>B" becomes "A>B"
The first example shows that surrounding quotation marks are removed. The second shows that multiple quoted tokens are all dequoted. The last three show that sendmail refuses to dequote any tokens that will form an illegal or ambiguous address when dequoted.
As an aid to understanding this dequoting process, run the following two-line configuration file in rule-testing mode:
V10 Kdequote dequote
You can then use the -bt
/map command to try various dequoting
possibilities:
>/map dequote "A.B.C"map_lookup: dequote ("A.B.C") returns A.B.C (0) >/map dequote "A"."B"."C"map_lookup: dequote ("A"."B"."C") returns A.B.C (0) >/map dequote "A B"map_lookup: dequote ("A B") no match (0)
A few database switches are available to modify the
behavior of this dequote database-map type. They are
listed in Table 23-10.
Note that beginning with V8.7, specifying the -s switch (and beginning
with V8.10, specifying the -S switch) causes the space character
to be replaced with another character before
dequoting (-S on page
890):
Kdequote dequote -s+ ← V8.7 through V8.9 Kdequote dequote -S+ ← V8.10 and later
When using the mc configuration
technique, dequote switches are declared like
this:
define(`confDEQUOTE_OPTS', `-S+')
In either case, the last example would have the space
converted to a plus sign before the conversion, thus
resulting in a legal address. The "A B" example (which
failed before) will become the following:
> /map dequote "A B"
map_lookup: dequote ("A B") returns A+B (0)Also note that beginning with V8.8, specifying the
-a switch
causes a suffix of your choice to be appended to a
successful match:
define(`confDEQUOTE_OPTS', `-a.yes')
In that case, the "A.B.C" example would become the
following:
> /map dequote "A.B.C"
map_lookup: dequote ("A.B.C") returns A.B.C.yes (0)In addition to removing quotes, the
dequote type also
tokenizes everything that is returned. It does this
because quotes are ordinarily used to mask the
separation characters that delimit tokens.
No debugging switch is available to watch the actions
of the dequote
type.
Look up addresses using DNS V8.12 and later
The dns type is an
internal database map available to perform DNS
lookups. It is declared like this:
Kdnslookup dns -Rlookup-type
The -R switch—which
specifies the DNS query to perform—must always be
included. Table 23-11 shows the DNS queries that are supported.
|
Means | |
|
|
Return IPv4 address records for the host (RFC1035). |
|
|
Return IPv6 address records for the host (RFC1886). |
|
|
Return an AFS server resource record (RFC1183). |
|
|
Return the canonical name for the host (RFC1035). |
|
|
Return a best MX record for the host (RFC1035). |
|
|
Return a name server record (RFC1035). |
|
|
Return the hostname that corresponds to an IP record (RFC1035). |
|
|
Return the port to use for a service (RFC2782). |
|
|
Return general (human-readable) information (RFC1035). |
If an -R value
other than those in Table 23-11 is specified, the following two errors are
printed and logged. If the -R switch is omitted, only the second
error is printed and logged:
configfile: line num: dns map lookup: wrong type bad -R value configfile: line num: dns map lookup: missing -R type
To make this dns
database-map type more useful, the switches shown in
Table 23-12 are also available for your use.
|
Switch |
§ |
Description |
|
|
-A on page 886 |
Append values for duplicate keys. |
|
|
-a on page 887 |
Append tag on successful match. |
|
|
DNS database-map -B switch on page 908 |
Specify domain to append to all queries (V8.14 and later). |
|
|
Timeout.resolver (V8.10 and later) on page 1108 |
The res_search()
|
|
|
-f on page 887 |
Don’t fold keys to lowercase. |
|
|
-m on page 888 |
Suppress replacement on match. |
|
|
-N on page 889 |
Append a null byte to all keys. |
|
|
-O on page 889 |
Never add a null byte. |
|
|
-o on page 889 |
This database map is optional. |
|
|
-q on page 889 |
Don’t strip quotes from key. |
|
|
Previous paragraphs |
Record type to look up. |
|
|
Timeout.resolver (V8.10 and later) on page 1108 |
The res_search()
|
|
|
-T on page 890 |
Suffix to append on temporary failure. |
|
|
-t on page 891 |
Ignore temporary errors. |
|
|
DNS database-map -Z switch on page 908 |
The maximum number of returned entries to form a lookup result (V8.14 and later). |
|
|
DNS database-map -z switch on page 908 |
The delimiter to use to delimit multiple returned entries (V8.14 and later). |
One possible use for this dns database map might be to do a
reverse lookup of a connecting host’s address and to
defer the message if that address does not
resolve.[345] Consider the following
mc configuration, for
example:
LOCAL_CONFIG
Krlookup dns -RPTR -a.FOUND -d5s -r2
LOCAL_RULESETS
Local_check_relay
R $* $: $&{client_addr}
R IPv6: $* $# OK
R $+.$+.$+.$+ $: $(rlookup $4.$3.$2.$1.in-addr.arpa. $)
R $* . FOUND $# OK
R $* $#error $@ 4.1.8 $: "450 cannot resolve " $&{client_addr}Here, under the LOCAL_CONFIG, we declare a dns-type database called
rlookup. The
-RPTR specifies
that we will be looking up PTR (address) records.
The -a.FOUND
instructs sendmail to append a
literal .FOUND to the value returned by a successful
lookup. Finally, the -d5s and -r2 switches prevent the lookup from
hanging for too long an interval.
The actual rules are under the LOCAL_RULESETS section
of your mc configuration file.
We place the rules under the Local_check_relay rule
set (Local_check_relay and check_relay on page 252), which is used to screen incoming
network connections and accept or reject them based
on the hostname, domain, or IP address. The first
rule matches everything and simply copies the value
of the ${client_addr} macro into the
workspace. That macro contains the connecting host’s
IP address.
The second rule checks to see whether the IP address
is an IPv6 address (the IPv6: prefix) and if so, accepts the
address (the $#OK). If the address is a normal
dotted-quad, IPv4-style address (such as
123.45.67.8), the third rule finds it in the
workspace. An IPv4 address is looked up in the RHS
of the third rule using the rlookup database. The key point here is
that an address has to look like a hostname, so we
reverse it and add a literal .in-addr.arpa. suffix to
it. For example:
123.45.67.8 would look up as → 8.67.45.123.in-addr.arpa.The fourth rule detects the result of the lookup. If
the workspace ends in a literal .FOUND, the lookup
was successful and the rule set returns a $#OK, which means that
the message is acceptable.
The last rule handles any lookup failure (including temporary failures). The envelope sender is rejected with a temporary error, thus causing the sending site to retain the message in its queue. If the IP address can be looked up in the future, no harm is done. Otherwise, the message will eventually bounce.
The value returned by the dns-type database map is always a
single item. If a host has multiple MX, A, or AAAA
records, a successful lookup will return only one
such record. In the case of MX records, the
lowest-cost record may not be returned.[346]
This dns-type
database map can be used only if
sendmail was built with the
NAMED_BIND and DNSMAP compile-time macros defined
(which they are by default).
This dns-type
database map is used primarily by FEATURE(dnsbl) (FEATURE(dnsbl) on page 261) and FEATURE(enhdnsbl) (FEATURE(enhdnsbl) on page 263). Both of these features use the
-RA and
-T<TMP>
switches. FEATURE(enhdnsbl) also uses the
-r5 and
-a. switches.
Beginning with V8.13, these switches can be
overridden for FEATURE(dnsbl) using the DNSBL_MAP_OPT
mc configuration macro (FEATURE(dnsbl) on page 261). For FEATURE(enhdnsbl), the timeout for
-r can be
changed using the EDNSBL_TO mc
configuration macro.
As of V8.14, the -B database-map switch may be used to
add a domain specification that will automatically
be appended to each lookup. For example:
LOCAL_CONFIG Ktxtlookup dns -RTXT -a.FOUND -Bexample.com
Here, if an unqualified host, such as
hostA, is looked up, it has
the domain example.com
appended to it to form
hostA.example.com and the
resulting hostname will be looked up. If you use
the -B switch
to look up a fully qualified name (such as
www.example.com), the domain
is also appended (to form
www.example.com.example.com)
and the lookup will fail or possibly return an
unexpected value. Thus, we recommend that you use
only -B to look
up unqualified hostname.
As of V8.14, the -Z database-map switch may be used to
limit the number of entries returned on a
successful lookup. For example:
LOCAL_CONFIG Klookup dns -RA -z, -Z2
Here, the lookup database map will query for
an A record.
Normally, if a host has several A records, this lookup
would return only one, but with the addition of
the V8.14 -z
switch, sendmail will return
all the entries it finds. Note that when using the
-Z dns
database-map switch, if you specify a limit of 2,
the successful result will be limited to just two
addresses even if there are more.
As of V8.14, the -z database-map switch may be used to
specify the delimiter that separates one returned
value from the next. For example:
LOCAL_CONFIG Klookup dns -RA -z,
Here, the lookup database-map will query for
an A record.
Normally, if a host has several A records, this lookup
would return only one. But with the addition of
the V8.14 -z
switch, sendmail will return
all the entries it finds, each separated by the
character specified, in this instance the
comma:
hostA . example . com , hostB . example . com
Note that if a query will likely return too
many entries, you may use the -Z dns database-map
switch detailed in DNS database-map -Z switch on page 908
to limit the number returned.
A db(3) form of database V8.1 and later
The hash database
map type uses a hashing algorithm for storing data.
This approach to a database is described in
A New Hash Package for UNIX,
by Margo Seltzer (Usenix Proceedings, Winter 1991).
The hash type is
available only if sendmail was
compiled with NEWDB defined and the Berkeley or
Sleepycat db(3) library
linked.
The hash type is
the default that is used with most of the features
offered by the mc configuration
technique (see Table 23-4 on page 896). For example, consider the
following:
Kuudomain hash -o /etc/mail/uudomain
Here, a database map named uudomain is declared to be of type
hash. The
-o says that
the database file
/etc/mail/uudomain is
optional.
Quite a few other database-map switches are available with this type. The complete list is shown in Table 23-13.
|
Switch |
§ |
Description |
|
|
-A on page 886 |
Append values for duplicate keys. |
|
|
-a on page 887 |
Append tag on successful match. |
|
|
-D on page 887 |
Don’t use this database map if |
|
|
-f on page 887 |
Don’t fold keys to lowercase. |
|
|
-m on page 888 |
Suppress replacement on match. |
|
|
-N on page 889 |
Append a null byte to all keys. |
|
|
-O on page 889 |
Never add a null byte. |
|
|
-o on page 889 |
This database map is optional. |
|
|
-q on page 889 |
Don’t strip quotes from key. |
|
|
-S on page 890 |
Space replacement character. |
|
|
-T on page 890 |
Suffix to append on temporary failure. |
|
|
-t on page 891 |
Ignore temporary errors. |
The -d38.20
command-line switch (-d38.20 on
page 568) can be used to observe this type’s lookups
in more detail. See also the btree type (btree on page 901).
MIT network user authentication services V8.7 and later
The hesiod type of
database map uses the Hesiod system, a network
information system developed as Project Athena.
Support of hesiod database maps
is available only if you declare HESIOD when
compiling sendmail. (See HESIOD on page 115 for a fuller
description of the Hesiod system.)
A hesiod database
map is declared like this:
Kname hesiod HesiodNameType
The HesiodNameType must be
one that is known at your site, such as passwd or service. An unknown
HesiodNameType will
yield this error when sendmail
begins to run:
cannot initialize Hesiod map (hesiod error number)One example of a lookup might look like this:
Kuid2name hesiod uid R$- $: $(uid2name $1 $)
Here, we declare the network database map uid2name using the
Hesiod type uid,
which converts user-id numbers
into login names. If the conversion was successful,
we use the login name returned; otherwise, we use
the original workspace.
Quite a few database-map switches are available with this type. They are all listed in Table 23-14.
|
Switch |
§ |
Description |
|
|
-A on page 886 |
Append values for duplicate keys. |
|
|
-a on page 887 |
Append tag on successful match. |
|
|
-D on page 887 |
Don’t use this database map if |
|
|
-f on page 887 |
Don’t fold keys to lowercase. |
|
|
-m on page 888 |
Suppress replacement on match. |
|
|
-N on page 889 |
Append a null byte to all keys. |
|
|
-O on page 889 |
Never add a null byte. |
|
|
-o on page 889 |
The network database map is optional. |
|
|
-q on page 889 |
Don’t strip quotes from key. |
|
|
-S on page 890 |
Space replacement character. |
|
|
-T on page 890 |
Suffix to append on temporary failure. |
|
|
-t on page 891 |
Ignore temporary errors. |
The -d38.20
command-line switch (-d38.20 on
page 568) can be used to observe this type’s lookups
in more detail.
Internal table to store lookup hostnames V8.1 and later
The host
database-map type is a special internal database
used by sendmail to help
resolve hostnames. It is fully described under the
$[ and $] operators in $[ and $]: A Special Case on page 895.
Only a few database-map switches are available with
the host type,
and they are listed in Table 23-15.
|
§ |
Description | |
|
|
-a on page 887 |
Append tag on successful match. |
|
|
The res_search()
| |
|
|
-D on page 887 |
Don’t use this database map if |
|
|
-m on page 888 |
Suppress replacement on match. |
|
|
Timeout.resolver (V8.10 and later) on page 1108 |
The res_search()
|
|
|
-S on page 890 |
Space replacement character. |
|
|
-T on page 890 |
Suffix to append on temporary failure. |
|
|
-t on page 891 |
Ignore temporary errors. |
The -D database
switch should probably always be used with this type
on sites that have dial-on-demand connections to the
Internet. It prevents host lookups when the DeliveryMode option
(DeliveryMode on page 1004) is
set to defer.
Search for an aliases database entry V8.1 and later
The implicit database-map
type refers specifically to
aliases(5) files only. It
causes sendmail to first try to
open a db(3) hash-style
alias file. If that fails or
if NEWDB support was not compiled in, it tries to
open an ndbm(3)-style database.
If that fails, sendmail reads
the aliases(5) source file into
its internal symbol table.
When sendmail rebuilds its
aliases database (as with
newaliases) it looks for the
special string literal /yp/ anywhere in the path specified for
the aliases source file. If
that string literal is found,
sendmail uses this
implicit type to create
both a db(3) hash-style
alias file, and an
ndbm(3)-style database. It
creates both to support NIS compatibility.
Although you can declare and use this type in a
configuration file, there is no reason to do so. It
is of use only to the internals of
sendmail. If
implicit fails to open
an aliases file, probably
because of a faulty AliasFile option (AliasFile on page 970),
sendmail will issue the
following error if it is running in verbose
mode:
WARNING: cannot open alias database bad filenameIf the source aliases file exists
but no database form exists,
sendmail will read that
source file into its internal symbol table using the
stab type
(stab on page 938).
You can experiment with this implicit database-map type using a mini
configuration file such as this:
V10 Kxlate implicit -a.Yes -o /etc/mail/aliases Stest R$* $: $(xlate $1 $)
Here, we declare a database map named xlate to be of type
implicit. We
use it to look up aliases in the file
/etc/mail/aliases (which can
optionally not exist because of the -o switch). We don’t
care whether that file is a db
file, a dbm file, or a text
file. The implicit type will find the right type
and use it. A successful match will append a
.Yes suffix to
the returned value.
The -d38.20
command-line switch (-d38.20 on
page 568) can be used to observe this type’s lookups
in db files and
dbm files.
The Lightweight Directory Access Protocol V8.8 and later
LDAP stands for Lightweight Directory Access Protocol and provides access to a service based on X.500. Additional information about LDAP is available from:
| http://www.ldapman.org/ |
The ldap
database-map type is used to look up items in that
directory service. (Prior to V8.10, this was called
ldapx to
reflect its experimental condition at the time. That
prior name still works but is deprecated.) The
ldap
database-map type is declared like this:
Kname ldap switches
Lookups via LDAP are defined entirely by the switches specified. To illustrate, consider the following X.500 entry:
cn=Full Name, o=Organization, c=US sn=Name uid=yourname mail=yourname@mailhub.your.domain objectclass=person objectclass=deptperson
To look up a login name in this database and have the official email address for that user returned, you might use a declaration such as this:
Kgetname ldap -k"uid=%s" -v"mail" -hldap_host -b"o=Organization, c=US"
Here we use only three switches:
The -k
switch is in the form of an ldap_search(3) filter.
Here, the key will replace
the %s and then
the whole expression will be searched using the
new key.
The -b
switch is necessary if you wish to specify the
base from which to search.
The -h
switch is required to specify the host to contact
to perform the lookup.
The -k, -h, and -v switches are
mandatory.
You can omit selected switches from the K configuration command
by defining them with the LDAPDefaultSpec option (LDAPDefaultSpec on page 1039). In
general, this option is used to define the -b and -h switch settings. You
can, however, use it to define any number of
defaults that you wish.
The following rule can be used with the preceding declaration to look up the preferred mail address for a user:
R $* <@ $=w . > $* $: $(getname $1 $: $1<@$2>$3 $)
Here, we presume that this rule was preceded by a call
to the canonify
rule set 3 to focus on the host part of the address.
If the lookup succeeds, the new (unfocused) address
is returned from the mail= line in the database. Otherwise,
the original address is returned.
This ldap type has
more database switches available for it than most
other types. They are all listed in Table 23-16.
|
§ |
Description | |
|
|
The −1 ldap database-map switch on page 915 |
Consider successful only if one key is matched. |
|
|
-A on page 886 |
Append values for duplicate keys. |
|
|
-a on page 887 |
Append tag on successful match. |
|
|
The -b ldap database-map switch on page 915 |
Base from which to begin the search. |
|
|
-D on page 887 |
Don’t use this database map if |
|
|
The -d ldap database-map switch on page 915 |
DN to bind to server as. |
|
|
-f on page 887 |
Don’t fold keys to lowercase. |
|
|
The -H ldap database-map switch on page 915 |
Specify an LDAP URI (V8.13 and later). |
|
|
The -h ldap database-map switch on page 916 |
Hosts that serve this network database (required). |
|
|
The -K ldap database-map switch (V8.14 and later) on page 916 |
Use |
|
|
The -k ldap database-map switch on page 917 |
The search query (required). |
|
|
-l (lowercase L) on page 888 |
Set a timeout for the lookup. |
|
|
The -M ldap database-map switch on page 917 |
The method to use for binding. |
|
|
-m on page 888 |
Suppress replacement on match. |
|
|
The -n ldap database-map switch on page 917 |
Retrieve attribute names only, not values. |
|
|
-o on page 889 |
The database map is optional. |
|
|
The -P ldap database-map switch on page 917 |
The secret password to use for binding. |
|
|
The -p ldap database-map switch on page 917 |
Port to use when connecting to host. |
|
|
-q on page 889 |
Don’t strip quotes from key. |
|
|
The -R ldap database-map switch on page 917 |
Don’t autochase referrals. |
|
|
The -r ldap database-map switch on page 918 |
Allow dereferencing of aliases. |
|
|
-S on page 890 |
Space replacement character. |
|
|
The -s ldap database-map switch on page 918 |
Search scope of “base,” “one,” or “sub”. |
|
|
-T on page 890 |
Suffix to append on temporary failure. |
|
|
-t on page 891 |
Ignore temporary errors. |
|
|
The -V ldap database-map switch on page 918 |
Specify a separator (V8.12 and later). |
|
|
The -v ldap database-map switch on page 919 |
Specify the list of attributes to return (required). |
|
|
The -w ldap database-map switch on page 921 |
Specify the LDAP API/protocol version (V8.13 and later). |
|
|
The -z ldap database-map switch on page 921 |
Specify return value delimiter. |
|
|
The -Z ldap database-map switch on page 921 |
Limit the number of matches to return. |
Although some of these switches are also used by other
database-map types, many of them are unique to this
ldap
database-map type. In addition to setting switches
with the K
command, you can also preset selected switches with
the LDAPDefaultSpec option (LDAPDefaultSpec on page 1039).
Each successful lookup can cause a line such as the
following to be logged via
syslog(3) when the LogLevel option (LogLevel on page 1040) is greater than
9:
qid: ldap key => value
Note that the ldap
type can be used only if the LDAPMAP compile-time
macro was defined when sendmail
was compiled (LDAPMAP on page
119). Also note that the USING_NETSCAPE_LDAP
compile-time macro (USING_NETSCAPE_LDAP
on page 150) will need to be defined if your
ldap libraries are from
Netscape or are derived from Netscape’s
libraries.
As of V8.13, the default schema for alias lookups using LDAP has been changed to include LDAP recursion support. Recall that you declare alias lookups with LDAP like this:
define(`ALIAS_FILE', `ldap:')
This causes aliases to be looked up using LDAP and the following default schema:
ldap -k (&(objectClass=sendmailMTAAliasObject)
(sendmailMTAAliasGrouping=aliases)
(|(sendmailMTACluster=${sendmailMTACluster})
(sendmailMTAHost=$j))
(sendmailMTAKey=%0))
-v sendmailMTAAliasValue,
sendmailMTAAliasSearch:FILTER:sendmailMTAAliasObject,
sendmailMTAAliasURL:URL:sendmailMTAAliasObjectNote that sendmail macros (like $j) are not expanded
when the default schema is first defined. Rather,
they are expanded each time an LDAP lookup is
performed.
In the event you wish to use your own schema
rather than the default, you may do so by
appending it to ldap: when defining ALIAS_FILE:
define(`ALIAS_FILE', `ldap:-k (&objectClass=mg)(mail=%0) -v mmember')Here, we replaced the long, recursive default schema shown earlier with a much shorter and nonrecursive schema of our own design.
See cf/README in the sendmail source distribution for an additional discussion of the default schema and how to use it.
As of V8.13, the default schema for class macro assignments using LDAP has been changed to include LDAP recursion support. For example, recall (in Class via ldap map lookups on page 862) that you declare classes with LDAP like this:
RELAY_DOMAIN_FILE(`@LDAP')
This causes the class $=R to be filled with values that match
a sendmailMTAClassName with the value
R. More
generally, for any class X, the following default schema will be
used:
F{X}@ldap:-k (&(objectClass=sendmailMTAClass)
(sendmailMTAClassName=X)
(|(sendmailMTACluster=${sendmailMTACluster})
(sendmailMTAHost=$j)))
-v sendmailMTAClassValue,
sendmailMTAClassSearch:FILTER:sendmailMTAclass,
sendmailMTAClassURL:URL:sendmailMTAClassNote that sendmail macros (like $j) are not expanded
when the default schema is first defined. Rather,
they are expanded each time an LDAP lookup is
performed.
See cf/README in the sendmail source distribution for an additional discussion of this default schema and how to use it.
The −1
switch prevents LDAP from returning multiple
values when only one is sought. This can be used
to save the server from extra work. If −1 is specified,
sendmail tells the LDAP
server to examine only enough records to determine
whether there is a single match. That is, if there
is more than one match, and if this −1 switch is specified,
the lookup will return that
no matches were found.
Note the difference between the -Z and −1 switches. A -Z1 (The -Z ldap database-map switch on
page 921) will return only the first match, while
ignoring the rest of the matches. A −1 returns failure if
there is more than one match.
The -b
switch is used to specify the base tree from which
to search. In general, if specified, it should
ensure that sendmail will
always get a unique result:
-b"o=Organization, c=US"
If the base contains a space character, the
entire expression should be quoted. Here, the
search will include only records under the tree
shown. Essentially, this -b tree specification is prepended to
each -k query
value just before it is looked up.
The -d
switch specifies the distinguished name (DN) to
use when binding to the server.[347] In general, such names contain spaces
and other special characters, and therefore should
be quoted. For example:
-d"cn=Directory Manager, o=igloo CA, l=Melbourne, st=Victoria, c=AU"
There is no default, and this switch is
optional. (See also the -P [The -P ldap database-map switch on
page 917] and -M [The -M ldap database-map switch on
page 917] switches.)
Modern versions of LDAP allow you to use
Universal Resource Identifiers (URIs) in place of
host and port combinations when specifying an LDAP
server. Beginning with V8.13
sendmail, you may specify an
LDAP URI using the new -H database-map switch. For example,
prior to V8.13 sendmail, you might have used an
mc
configuration statement like this:
define(`confLDAP_DEFAULT_SPEC', `-h ldap.example.gov -p 8389')
Here, -h
specifies the LDAP server host and -p specifies the
nonstandard port 8389. Beginning with V8.13, you
can simplify this declaration by using the
-H database-map
switch:
define(`confLDAP_DEFAULT_SPEC', `-H ldap://ldap.example.gov:8389')
One advantage of -H is that it allows you to fetch the
URI from a secure server by using ldaps:// instead of
ldap://, as for
example:
define(`confLDAP_DEFAULT_SPEC', `-H ldaps://ldap.example.gov -b dc=example,dc=gov')
Here, the -b LDAP database-map switch (The -b ldap database-map switch on
page 915) specifies the base from which to begin
the search for the URI. If, rather than reading
from a TCP/IP socket, your LDAP server uses a
Unix-domain socket, you may use ldapi:// instead of
ldap://, to
access that Unix-domain socket:[348]
define(`confLDAP_DEFAULT_SPEC', `-H ldapi:///path/to/file -b dc=example,dc=gov')
Note that when you build sendmail with LDAP
support, the sendmail code will look to see whether
you have a working ldap_init() function in your LDAP
library. If you do (and all modern versions of
LDAP do), you will be allowed to use the new
-H database-map
switch. If not, you will see the following warning
when you attempt to use it:
Must compile with -DUSE_LDAP_INIT to use LDAP URIs (-H) in map nameIf you believe sendmail interpreted your LDAP setup
wrongly, you may define USE_LDAP_INIT when building to correct
the error.
The -h is
mandatory. It specifies the host, or hosts, to
which to connect for the LDAP lookup. If you wish
to specify a sequence of hosts, you can do so by
listing them, each separated from the others by
space characters:
-h"hostA hostB"
Here, because a space is the separator, this expression must be quoted. The lookup will cause sendmail to connect to hostA first. If it connects, and if a successful match is found, the lookup terminates and that value is returned. If the lookup fails, no further hosts are connected. If the connection cannot be established, a connection to the next host in the sequence (hostB) is tried, and if successful, the lookup is made on that host. This continues until all connections to all hosts have failed, or until a connection can be made.
In the event that you need to specify a port
for a host different from that specified by the
LDAP_PORT macro in the LDAP source, you can do so
by using the -p
switch (The -p ldap database-map switch on
page 917) or by adding a port specification to one
or more hosts. You add a port specification to a
host by appending a colon, and then the port
number:
-h"hostA hostB:463"
Here, hostA is contacted on the default port, and hostB is contacted on port 463.
In general, the hosts specified should be fully qualified hostnames:
-h ldaphost ← not this -h ldaphost.your.domain ← this is preferred
The -K
switch is optional. When used, it allows the
arguments of -k
to include the positional arguments %1 through %9. For example:
-K -k gid=%2
See your LDAP documentation to learn about the
special meaning of certain characters (such as
% and *) in lookup keys, and
how to correctly formulate key lookup
expressions.
The -k
switch is mandatory. It is used to specify the key
to look up. The lookup key is in the form of an
ldap_search(3),
which can be simple:
-k uid=%s
or omplex (note that we split the line to fit the page):
-k (&(objectClass=sendmailMTAClass)(sendmailMTAClassName=ClassName)
(|(sendmailMTACluster=${sendmailMTACluster})(sendmailMTAHost=$j)))See your LDAP documentation to learn about the
special meaning of some characters (such as
% and *) in lookup keys, and
how to correctly formulate key lookup
expressions.
The -M
switch specifies the method to use for binding. It
can be one of three case-insensitive, literal
expressions that specify the method: none, simple, or krbv4. Or it can be any
of these with an LDAP_AUTH_ prefix. If it is any other
expression or word, the following error is printed
and logged when sendmail
starts:
Method for binding must be [none|simple|krbv4] (not bad word) in map name
The default method is none, which means anonymous access to
LDAP. This switch is optional. See also the
-P switch
(The -P ldap database-map switch
on page 917) for simple and krbr4, and the -d switch (The -d ldap database-map switch on
page 915) for simple only.
The -n
switch is used to limit the returned information
to attributes only. An attribute is the
information to the left of the = in an X.500
entry:
cn=Full Name,o=Organization,c=USsn=Nameuid=yournamemailfrom=youraddress
One use for this switch might be to look up an
address to see whether it is associated with a
mailfrom or
mailto
attribute. If the address is not found, neither
attribute will be returned. Otherwise, the
attribute that defines the address will be
returned.
The -P
switch specifies the secret password to use when
authenticating the distinguished name set by the
-d switch
(The -d ldap database-map switch
on page 915). For the simple method (see -M; The -M ldap database-map switch on
page 917), this is the pathname of the file
containing the secret key. For the krbv4 method, this is
the name of the Kerberos ticket file.
The -p
switch specifies the port to which to connect on
the LDAP server. The default port is defined by
LDAP_PORT in the LDAP source. See also the
-h switch
(The -h ldap database-map switch on
page 916) to see how a port number can be
associated with individual hosts.
The -R
switch is used to enable V2 and later LDAP to
follow referrals. If the contacted server does not
have the information sought, it can return a
referral to one or more other servers that might
have the information. With this -R switch specified,
sendmail will follow
referrals until either the information sought is
found, or no more referrals are given. The
-R switch can
be used only if sendmail was
compiled with the LDAP_REFERRALS compile-time
macro defined.
The -r
switch specifies how LDAP aliases are
dereferenced. In LDAP, you can set a leaf entry
(such as ou=hardware) to point to another object
in the same name space (such as ou=engineering). This is
called an alias entry. When you perform a lookup
using an alias, the alias is dereferenced so that
what is returned is the value of the object
pointed to by the alias. For example, if your
company once had two departments:
ou=hardware ou=software
and those departments were merged into a
single one called ou=engineering, you could achieve
backward compatibility by turning the two, old
leaf entries into aliases pointing to the new one.
When sendmail encounters an
LDAP alias it has four choices that are reflected
by four possible, case-insensitive settings for
the -r switch:
never means to
not follow aliases and instead to return a failed
lookup; always
means to follow aliases (the default); search means to perform
a lookup first and to follow an alias only if the
lookup succeeded; and find means to follow an alias only if
all attributes match (that is, for example, the
alias "cn=x,
ou=y" won’t be followed if only ou= is looked up). These
four keywords can also be prefixed with a literal
LDAP_DEREF_
expression. If another word or expression is used,
the following error is printed and logged:
Deref must be [never|always|search|find] (not badword) in map name
The -s
switch is used to specify the scope of the search
to perform on the LDAP server. There are three
allowable scopes and, thus, three settings for the
-s switch. They
are: base (the
default), which retrieves information only about
the base distinguished name specified (with the
-b switch,
The -b ldap database-map switch
on page 915); one, which retrieves information about
entries one level below the base distinguished
name, where the base entry is not included in this
scope; and sub,
which retrieves information about entries at all
levels below the base distinguished name, where
the base entry is included in this scope. The
scope can also be any of these three keywords with
an LDAP_SCOPE_
prefix. If it is any other word or expression, the
following error is printed and logged when
sendmail starts:
Scope must be [base|one|sub] (not badword) in map nameThe -V
switch (new with V8.12) allows you to specify a
separator such that a lookup can return both an
attribute and a value separated by that separator.
Without this switch, only values are returned.
With this switch, attributes/value pairs are
returned. For example:
-V=
might cause a successful return to appear like this:
user=bob
The -v
switch specifies a list of attributes to return.
The attributes must be separated from each other
by commas. If the attributes contain spaces, the
entire expression must be quoted:
-voc,ou -v"oc, ou"
If more than one attribute is requested (and
if the -z
switch [The -z ldap database-map switch on
page 921] is omitted), only the first attribute
value returned from the LDAP server is given to
the rule set. If the -z switch is used to specify a
delimiter, all the attributes returned from the
LDAP server are returned to the rule that did the
lookup, each value separated from the others by
that delimiter. For the earlier -v example, and a
-z:, the
following values might be returned to the rule
that did the lookup:
foo:org:bar
When you query multiple attributes from the
LDAP server, it can be beneficial to also specify
a -V switch
(The -V ldap database-map switch
on page 918), which causes the attribute name to
be returned along with each value. For a -V= (along with the
earlier -z:),
for example, the following attribute names and
returned values might be returned to the rule that
did the lookup:
oc=foo:ou=org:oc=bar
Note that if you list too many attributes with
-v (usually
more than 64), the following error will print and
log:
Too many return attributes in name (max 64)
Prior to V8.13, LDAP lookups could only return the actual data sought, rather than information that would automatically result in another lookup, but beginning with V8.13, lookups are allowed to be recursive. LDAP recursion allows a query to return either a new query, a Distinguished Name (DN) or an LDAP URL. When any of these are returned, they result in another lookup.
LDAP recursion is requested with this -v ldap database-map
switch, which specifies the list of attributes to
return, like this:
-vattribute:type:objectclass|objectclass|...
Here, the type can
be one of four literal values: NORMAL, DN, FILTER, or URL.
The NORMAL
type says that the
attribute will be added
to the result of the lookup if the record found is
a member of the
objectclass specified.
NORMAL is the
default type if type is
omitted.
The Distinguished Name (DN) type expects that
any matches of the
attribute have a fully
qualified distinguished name. If so, the sendmail program will
perform a second lookup of the
attribute using the
returned DN
record.
The FILTER
type requires that any matches of the
attribute have the
value of an LDAP search filter. If so, the
sendmail
program will perform the same lookup again but
will replace the original search filter with the
new filter returned.
The URL
type expects that the lookup will return a
URL. If so, the
sendmail
program will perform a lookup using the returned
URL and will
then use the resulting attributes returned.
The objectclass
list, in the -v
expression, is optional and, if present, contains
the object-class values for which the
attribute applies. If
there is more than one object-class value, each
must be separated from the next by a vertical bar
character (|). If object-class values are listed,
the attribute will be
used only if the LDAP record returned by a lookup
is a member of any of the object-class values
listed.
Note that recursion is liberal. That is, no error results if recursion ultimately fails to lead to an LDAP record. The lookup will simply fail in the same manner as it would if the record did not exist.
To illustrate, consider the following mc configuration file lines.
define(`confLDAP_DEFAULT_SPEC', `-H ldaps://ldap.example.com -b dc=example,dc=gov') LOCAL_CONFIG Kgetname ldap -k (&(objectClass=sendmailMTAAliasObject)(sendmailMTAKey=%0)) -v sendmailMTAAliasValue, mail:NORMAL:inetOrgPerson, uniqueMember:DN:groupOfUniqueNames, sendmailMTAAliasSearch:FILTER:sendmailMTAAliasObject, sendmailMTAAliasURL:URL:sendmailMTAAliasObject
First, we use -H when defining confLDAP_DEFAULT_SPEC.
The use of ldaps://, instead of ldap://, allows us to
fetch the LDAP URI from the secure server,
ldap.example.com.
Second, under the LOCAL_CONFIG part of our mc configuration file,
we define a database map using the K configuration command.
We give the database map the name getname and the type
ldap. The
-k LDAP
database-map switch specifies the LDAP search
query to use.
Note how LDAP recursion is used here. There
are five statements following -v, each on its own line
for clarity, and each separated from the next by a
comma.
The first statement following the -v is a lone attribute
named sendmailMTAAliasValue. Because it lacks
a colon-keyword type, it is presumed to be type
NORMAL. Here,
any value in the sendmailMTAAliasValue attribute will be
added to any result string regardless of any
object classes (because the attribute has no
object-classes).
The second statement contains an attribute
named mail,
defined to be the type NORMAL, with a single object class
called inetOrgPerson. The value in the
attribute mail
will be added to the result string only if the
LDAP record that is looked up is a member of the
inetOrgPerson
object class. The type NORMAL is not recursive. Only a single
lookup is performed and only a single result is
added to the string.
The third statement contains an attribute
named uniqueMember, defined to be the type
DN, with a
single object class called groupOfUniqueNames. The
type DN makes
the action associated with the attribute uniqueMember recursive.
When uniqueMember is looked up, the return
value may contain zero or more DN records that belong
to the object class groupOfUniqueNames. Each of those
returned DN
records will again be searched to find any of the
attributes listed in the -v line.
The fourth statement contains an attribute
named sendmailMTAAliasSearch, defined to be
the type FILTER, with an object class of
sendmailMTAAliasObject. The type
FILTER makes
the attribute sendmailMTAAliasSearch recursive. A
lookup is made using the initial filter (the
-k line) to
find any new filters that are in the object class
sendmailMTAAliasObject. For any that
are found, a second lookup is performed using each
new filter, to return any records that contain any
of the attributes listed in the -v line.
The fifth statement contains an attribute
named sendmailMTAAliasURL, defined to be the
type URL, with an object class called sendmailMTAAliasObject.
The type URL makes the attribute sendmailMTAAliasURL
recursive. A lookup is made using the default URL
to find any new URLs that are in the object-class
sendmailMTAAliasObject. For any that
are found, a second lookup is performed using each
new URL to return records that contain the
attributes requested in the original URL.
If your LDAP library returns one API version,
but your LDAP server uses a different one, you
force sendmail to use the
version on the server by supplying this new
-w switch with
your ldap
database-type declaration. For example, to look up
a login name in an LDAP database and have the
official email address for that user returned, you
might use a declaration like this:
Kgetname ldap -k"uid=%s" -v"mail" -hhost -b"o=Organization, c=US" -w3
Note that the trailing argument to this
K configuration
line is the new -w switch, which specifies the use of
LDAP API version 3 with the server running on
host.
If your system’s <ldap.h> include file defines a
maximum API version, and you exceed that maximum
with -w, the
following error will print:
LDAP versionspecifiedexceeds max ofmaxin mapname
If your system’s <ldap.h> include file defines a
minimum API version, and you specify too low a
minimum with -w, the following error will
print:
LDAP versionspecifiedis lower thanminin mapname
Either error will cause the API version
specified with -w to be ignored. For example, on
Solaris 9, with Sun-supplied LDAP, the minimum and
maximum are both set to 3.
By default, if a single query matches multiple
values, only the first value will be returned
unless the -z
database-map switch is specified. The -z switch specifies a
separator (delimiter) character that will separate
one return value from the next when multiple
values are returned:
-zcharHere, char is a
single, printable character. If you wish to
specify a newline, tab, or backslash, you can do
so using backslash-escaped notation (\n for newline, \t for tab, and \ for a backslash). In
general, the character selected should not be one
that you expect to be part of a returned value. No
internal check is made to ensure that the
character chosen by you makes sense for your
values.
The -Z
switch is used to limit the number of entries
returned on a single query. The default is
unlimited.
Note the difference between the -Z and −1 switches. A -Z1 will return only the
first match, while ignoring the rest of the
matches. A −1
(The −1 ldap database-map switch
on page 915) returns failure if there is more than
one match.
When using ldap, it can be desirable to reroute an
address to another host or a different email
address. To accomplish this, V8.10
sendmail introduced FEATURE(ldap_routing).
In its simplest form, it is declared in your
mc configuration file like
this:
FEATURE(`ldap_routing')
This declaration causes two ldap-type database maps
to be defined:
Kldapmh ldap −1 -v mailHost
-k (&(objectClass=inetLocalMailRecipient)(mailLocalAddress=%0))
Kldapmra ldap −1 -v mailRoutingAddress
-k (&(objectClass=inetLocalMailRecipient)(mailLocalAddress=%0))Here, the ldapmh stands for LDAP mail host, and
the ldapmra
stands for LDAP mail routing address.
Note that the LDAP server’s hostname (set with
-h) and the
base of the lookup (set with -b) were both omitted.
FEATURE(ldap_routing) presumes you will
set those values with the confLDAP_DEFAULT_SPEC option (LDAPDefaultSpec on page 1039) in your
mc configuration file. If you
don’t, FEATURE(ldap_routing) will fail.
For an example of how these database maps work, consider the following partial listing of an LDAP record:
mailLocalAddress: alice@your.domain mailHost: another.domain mailRoutingAddress: alice@another.domain
Assume that a rule set first checks to see
whether the recipients domain is in the class
$={LDAPRoute}
(LDAPROUTE_DOMAIN and
LDAPROUTE_DOMAIN_FILE on page 924). If it isn’t, it skips these
lookups. Otherwise, the first database map, the
ldapmh, looks
up the attribute mailLocalAddress, and if the value
following that item matches, it looks for the
attribute mailHost. If that attribute is found,
it returns that field’s value. The second database
map, the ldapmra, also looks up the attribute
mailLocalAddress, and if the value
following that item matches, it looks for the
attribute mailRoutingAddress. If that is found,
it returns that field’s value.
The preceding two K configuration commands can be
replaced with ones of your own design by adding
extra arguments to FEATURE(ldap_routing):
replaces the declaration following Kldapmh ↓ FEATURE(`ldap_routing', `newldapmh', ` newldapmra') ↑ replaces the declaration following Kldapmra
For example, the following declaration:
FEATURE(`ldap_routing', `ldap −1 -T<TMPF> -v relayHub
-k (&(objectClass=inetLocalMailRecipient)(mailLocalAddress=%0))')would result in this new ldapmh K configuration
line:
Kldapmh ldap −1 -v relayHub
-k (&(objectClass=inetLocalMailRecipient)(mailLocalAddress=%0))For backward compatibility, FEATURE(ldap_routing)
will not bounce addresses that fail to be found
with a lookup. Instead, they will be delivered as
is. If you want to bounce those failed lookups,
you can add a third argument to the preceding
declaration:
FEATURE(`ldap_routing', `newldapmh', ` newldapmra', `bounce')If the third argument is present and is
neither an empty string nor the string passthru, failed lookups
will bounce. To make your meaning clear, we
recommend you restrict your choices to the two
literal words bounce or passthru. Table 23-17
shows the relationship between the two database
maps and the lack or presence of a bounce. Beginning with
V8.13, two additional arguments are allowed
(discussed shortly).
|
Value of mailHost |
Value of mailRoutingAddress |
Result |
|
Is a local host |
Exists |
Deliver to |
|
Is a local host |
Does not exist |
Deliver to original address. |
|
Is a remote host |
Exists |
|
|
Is a remote host |
Does not exist |
Original address is relayed via |
|
Does not exist |
Exists |
Deliver to |
|
Does not exist |
Does not exist |
If |
Beginning with V8.13, a new literal word,
sendertoo, may
be used in place of either bounce or passthru. When you
specify sendertoo, you cause the envelope
sender to also be rejected if that address is not
found in LDAP. Thus, sendertoo acts as if bounce was also
specified (that is, both not-found recipients and
senders will be rejected).
If you wish to define how +detail
addresses (Plussed Detail Addressing on page 476)
are handled, you can do so by adding a fourth
argument to FEATURE(ldap_routing). That fourth
argument must be either a literal strip or a literal
preserve:
FEATURE(`ldap_routing', `newldapmh', ` newldapmra', `bounce', `strip')If an address contains a +detail
(such as george+nospam),
strip causes
the address to first be looked up with the
+detail
attached, and if no match is found, strip removes the
+detail and
looks up the address again. A preserve is the same as
strip except
that if a mail routing address match is found
(with ldapmra),
the +detail is
copied from the original address and appended to
the new address. If neither preserve nor strip is specified, the
address is looked up only with the +detail
attached.
For FEATURE(ldap_routing) to work, you need
to set your LDAP entries with an objectClass of inetLocalMailRecipient.
If present, there must be only one mailHost attribute, and
it must contain a fully qualified hostname as its
value. If present, there must be only one mailRoutingAddress
attribute, and it must contain a legal RFC2822
address as its value. For example:
dn: uid=alice, o=your.domain, c=US uid: alice objectClass: inetLocalMailRecipient mailLocalAddress: alice@your.domain mailRoutingAddress: alice@another.domain
This entry would cause mail destined for
alice@your.domain to be delivered to
the new address alice@another.domain.
The flow of FEATURE(ldap_routing) through the
parse rule set
0 looks like this:
Basic canonicalization (list syntax, delete local host, etc.)
LOCAL_RULE_0 (LOCAL_RULE_0 mc macro on page 596)
FEATURE(ldap_routing)
FEATURE(virtusertable) (FEATURE(virtusertable)
on page 645)
Addresses of the form user@$=w passed to local
delivery agent (The parse Rule Set 0 on page
696)
FEATURE(mailertable) (FEATURE(mailertable) on page 629)
UUCP, BITNET_RELAY ($B on page 808), etc.
LOCAL_NET_CONFIG (LOCAL_NET_CONFIG mc macro on page 598)
SMART_HOST (SMART_HOST mc macro on page 597)
SMTP, local, etc. delivery agents
Beginning with V8.13, two more arguments are now available for your use:
FEATURE(`ldap_routing', `newldapmh', ` newldapmra', `bounce', `detail', ` nodomain', `tempfail')
The new argument, nodomain (in the fifth
position following ldap_routing), is an argument with no
literal word required—for example, any one of
nodomain,
no, or UncleBob will work.
Without this new argument (if there are fewer than
five arguments or if this argument is present but
empty), a failed lookup of an address
(user@host.domain) would
cause the @host.doman part of
the address to also be looked up in LDAP. But the
presence of an argument in the nodomain position
prevents that secondary lookup.
The new sixth argument, tempfail, can be one
of two possible literal expressions: tempfail or queue. These tell
sendmail what
to do if sendmail cannot connect to the LDAP
server, and what to do if the LDAP lookup fails
because of a temporary LDAP failure. If this sixth
argument is missing (if there are fewer than six
arguments or if this argument is present and
empty) or if it contains the literal queue, the message will
be queued for a later attempt. If the sixth
argument contains the literal tempfail, the message
will be temporarily rejected with a 4yz reply
code. We recommend you make your intent clear by
specifying a literal queue rather than omitting the sixth
argument and relying on the default.
FEATURE(ldap_routing) (explained
earlier) only looks up addresses with domains that
are listed with the $={LDAPRoute} class. The
mc configuration technique
provides two macros that facilitate the process of
adding domains to the $={LDAPRoute} class:
LDAPROUTE_DOMAIN(`list of domains') LDAPROUTE_DOMAIN_FILE(`file')
The first form directly adds the list of
domains to the $={LDAPRoute} class by creating a
C configuration
file command. The second indirectly adds domains
to the $={LDAPRoute} class by reading them
from a file. It does this by
creating a F
configuration file command.
In addition to looking up hosts in the
$={LDAPRoute}
class (explained earlier), FEATURE(ldap_routing)
will also look up hosts in the $={LDAPRouteEquiv}
class. The difference is that hosts in this
$={LDAPRouteEquiv} class are converted
into the MASQUERADE_AS (MASQUERADE_AS mc Macro on
page 600) host’s name just before the
lookup.
The mc configuration
technique provides two macros that facilitate the
process of adding hosts to the $={LDAPRouteEquiv}
class:
LDAPROUTE_EQUIVALENT(`list of domains') LDAPROUTE_EQUIVALENT_FILE(`file')
The first form directly adds the list of
domains to the class by creating a C configuration file
command. The second indirectly adds domains to it
by reading them from a file.
It does this by creating an F configuration file
command.
Store a value into a macro via a rule V8.10 and later
Not only is it possible to use defined macros in rule
sets, but as of V8.10 sendmail,
it is also possible to place new values into defined
macros from inside rule sets. This marvel is
accomplished using the macro-type database map. It is an
internal type, always available regardless of how
sendmail was compiled.
The macro type can
be used in three ways. For example:
Kstore_it_in macro
R$* $: $(store_it_in {MyMacro} $@ $1 $) ← store new value into macro
R$* $: $(store_it_in {MyMacro} $@ $) ← clear macro to empty string
R$* $: $(store_it_in {MyMacro} $) ← undefine the macroThe first line declares store_it_in to be the name of a
macro
database-map type that is used in the rules that
follow. Those three rules show three different ways
to affect the value stored in the macro {MyMacro}. Note that the
macro name must not be prefixed with a $. If it is, its value
will be used as the name, instead of its actual
name. We cover the use of $& later.
The first rule shows that the value to be stored into
the macro is passed as the first $@ argument, the
$1. If this
value is that of an undefined macro, the stored
result is an empty string. Otherwise, the value is
stored as is into the {MyMacro} macro. If the value contains
macro-like expressions (such as $x), their values are
used. If {MyMacro} was previously undefined, it
becomes defined.
The second rule shows what happens when the value to
be stored is missing (or undefined). A missing value
has the effect of clearing the value stored in the
{MyMacro} macro
to that of an empty string. If {MyMacro} was previously
undefined, it becomes defined.
The third rule shows what happens when the argument
part (the $@
part) is omitted. The effect is to undefine the
{MyMacro}
macro.
Regardless of how you update the value in the macro, an empty string is returned. This can cause the original workspace to be lost. If you need to preserve the original workspace (or part of it), consider a variation such as the following:
R$* $: $(store_it_in {MyMacro} $@ $1 $) $1
↑
return original workspaceThis macro type can
also be used as an indirect way to store values into
different sendmail macros. To
illustrate, consider the following mini
configuration file and its use of $&:
V10
Kput macro
D{Target}{LocalTarget}
Stest
R $* $: $(put $&{Target} $@ $1 $)Here, the intention is to store the value (the
$@ $1) into the
macro whose name is stored in {Target}. The D line initializes that
name as {LocalTarget}. To witness this indirect
method in action run this mini configuration file in
rule-testing mode:
%/usr/sbin/sendmail -Cdemo.cf -btADDRESS TEST MODE (ruleset 3 NOT automatically invoked) Enter <ruleset> <address> >test foo in local targettest input: foo in local target test returns: >${LocalTarget}foo in local target >.D{Target}{NewTarget}>test foo in new targettest input: foo in new target test returns: >${NewTarget}foo in new target
This sort of indirection can be useful in rules that might, for example, cause one relay host to be selected under high load and another under low load. Another use might be to reject certain outside mail during business hours, but accept it after business hours.
No database-map switches are useful with this type.
NeXT, Darwin, and Mac OS X NetInfo V8.7 and later
NetInfo is NeXT’s implementation of a network-based
information service. It has also been adopted by the
Darwin and Mac OS X operating systems. The
netinfo type expects a
database-map declaration to be of the following
form:
Kname netinfo database-map
The database-map name
defaults to /aliases.
The netinfo type
uses only a handful of database switches, as shown
in Table 23-18.
|
§ |
Description | |
|
|
-a on page 887 |
Append tag on successful match. |
|
|
-D on page 887 |
Don’t use this database map if |
|
|
-k on page 888 |
Specify column for key or key name. |
|
|
-m on page 888 |
Suppress replacement on match. |
|
|
-q on page 889 |
Don’t strip quotes from key. |
|
|
-S on page 890 |
Space replacement character. |
|
|
-T on page 890 |
Suffix to append on temporary failure. |
|
|
-t on page 891 |
Ignore temporary errors. |
|
|
-v on page 891 |
Specify the value’s column. |
|
|
-z on page 891 |
Specify the column delimiter. |
The -v property
returns defaults to members. The -z column delimiter defaults to a
comma.
Support of netinfo database maps is available only if you declare NETINFO when compiling sendmail (NETINFO on page 127).
Sun’s Network Information Services (NIS) V8.1 and later
Sun Microsystems offers a network information service
called NIS. It provides the ability to look up
various kinds of information in network databases.
The nis type
allows you to access that network information by way
of rules in rule sets. You declare an nis database-map type
like this:
Kname nis nismap
Here, name is the
identifier that you will later use in rule sets. The
nismap is any NIS
database map that defaults to
mail.aliases. Lookups will
occur in the default NIS domain. If you wish to
specify some other domain, you can append an
@ character and
the domain name to the
nismap:
Kname nis nismap @ domain
To illustrate, consider the need to look up the name of the central mail server for your department. If such a database map were called mailservers, you could use the following configuration file line to look up your domain in that database map:
Kmailservers nis -o mailservers ... R $* <@ $+ > $* $: $1<@$2>$3 <$(mailservers $2 $)> R $* <@ $+ > $* <$+> $#smtp $@ $4 $: $1 < @ $2 > $3 ...
Here, we look up the host part of an address ($2) in the mailservers NIS database
map. The -o makes
the existence of the database map optional. If the
host part is found, it is rewritten to be the name
of the mail server for that host. In the last rule,
we forward the original address to that
server.
Without the -o, the
nonexistence of a database map will cause this error
to be logged:
Cannot bind to map name in domain domain: reason here
If NIS is not running or if sendmail cannot bind to the domain specified for the default domain, the following error is logged:
421 4.3.5 NIS map name specified, but NIS not runningOnly a few database switches are available with this
nis
database-map type. They can be found in Table 23-19.
|
§ |
Description | |
|
|
-a on page 887 |
Append tag on successful match. |
|
|
-D on page 887 |
Don’t use this database map if |
|
|
-f on page 887 |
Don’t fold keys to lowercase. |
|
|
-m on page 888 |
Suppress replacement on match. |
|
|
-N on page 889 |
Append a null byte to all keys. |
|
|
-O on page 889 |
Never add a null byte. |
|
|
-o on page 889 |
This database map is optional. |
|
|
-q on page 889 |
Don’t strip quotes from key. |
|
|
-S on page 890 |
Space replacement character. |
|
|
-T on page 890 |
Suffix to return on temporary failure. |
|
|
-t on page 891 |
Ignore temporary errors. |
The nis
database-map type is available only if
sendmail is compiled with NIS
defined (NIS on page 128).
Sun’s newer version of NIS V8.7 and later
Sun Microsystems’ NIS+ is a complete redo of its
earlier NIS system. The nisplus type allows you to look up
information using NIS+. The form of that type
declaration looks like this:
Kname nisplus nismap.domain
Here, the nismap is an NIS+
database-map name, such as
mail_aliases.[349] If the domain
or .domain is missing,
the nisplus default domain is
used. If the entire
nismap.domain is
missing, the default becomes
mail_aliases.org_dir. The
domain org_dir contains all the
systemwide administration tables.
Any lookup failures that can be retried will
automatically be retried up to five times, with a
sleep(3) of 2 seconds between
each try. If the
map.domain doesn’t
exist in the local NIS+ system, no error is
reported.
Only a modest number of database switches are available for this type. They are listed in Table 23-20.
|
§ |
Description | |
|
|
-a on page 887 |
Append tag on successful match. |
|
|
-D on page 887 |
Don’t use this database map if |
|
|
-f on page 887 |
Don’t fold keys to lowercase. |
|
|
-k on page 888 |
Specify column for key or key name. |
|
|
-m on page 888 |
Suppress replacement on match. |
|
|
-o on page 889 |
This database map is optional. |
|
|
-q on page 889 |
Don’t strip quotes from key. |
|
|
-S on page 890 |
Space replacement character. |
|
|
-T on page 890 |
Suffix to append on temporary failure. |
|
|
-t on page 891 |
Ignore temporary errors. |
|
|
-v on page 891 |
Specify the value’s column. |
You can use the -k
switch to specify a key
column to look up. Under
nisplus, columns are named,
so the -k must be
followed by a valid name. You can also use the
-v switch to
specify the value’s
column, and a name. If the -v is omitted, the last column becomes
the default.
IRIX nsd database maps V8.10 and later
The nsd
database-map type implements an interface to the
Unified Name Service supplied under IRIX 6.5 and
later. That service is a translation layer between
any program and a wide range of services (ranging
from NIS to LDAP). You declare an nsd database-map type
like this:
Kname nsd switches nsdmap
The name is the symbolic
name you will later use in the RHS of rule sets. The
nsdmap is a full path
into the nsd(8) daemons’ name
space (such as
/ns/engr.sgi.com/passwd.byname).
This nsd
database-map type supports only a few switches. They
are listed in Table 23-21.
|
§ |
Description | |
|
|
-a on page 887 |
Append tag on successful match. |
|
|
-D on page 887 |
Don’t use this database map if |
|
|
-f on page 887 |
Don’t fold keys to lowercase. |
|
|
-q on page 889 |
Don’t strip quotes from key. |
|
|
-S on page 890 |
Space replacement character. |
|
|
-T on page 890 |
Suffix to append on temporary failure. |
|
|
-t on page 891 |
Ignore temporary errors. |
This nsd type was
contributed by Bob Mende of SGI Inc.
Provide a never-found service V8.7 and later
The null
database-map type is an internal service that always
returns a failed lookup.
Normally, the null
type is used only internally. It can, however, be
useful when used to replace another database-map
type so that it can force failure without causing an
error. Consider, for example, a tiny configuration
file that does not need the use of the
aliases facilities. One way
to declare aliases would be like this:
O AliasFile=null:
This tells sendmail to use the
null type for
looking up aliases. Therefore, no aliases will ever
be found.
None of the K
command switches can be used with the null database-map type.
If you try to use any, they will be silently
ignored. No debugging switch is available to watch
this null
database-map type.
CCSO Nameserver (ph) lookups V8.10 and later
Prior to V8.10 sendmail,
redirecting email with a ph
server required running the
phquery program. Beginning
with V8.10 sendmail, a
database-map type called ph has been added that allows
sendmail to perform direct
ph queries. You declare it
like this:
Kname ph switches
The complete list of switches for this database-map type is shown in Table 23-22.
|
§ |
Description | |
| [a] | ||
|
|
-A on page 886 |
Append values for duplicate keys. |
|
|
-a on page 887 |
Append tag on successful match. |
|
|
-D on page 887 |
Don’t use this database map if |
|
|
-f on page 887 |
Don’t fold keys to lowercase. |
|
|
The -h ph database-map switch on page 931 |
Hosts that serve this network database map. |
|
|
The -k ph database-map switch on page 931 |
Specify a list of fields to query. |
|
|
-l (lowercase L) on page 888 |
Set a timeout for the lookup.[a] |
|
|
-m on page 888 |
Suppress replacement on match. |
|
|
-N on page 889 |
Append a null byte to all keys. |
|
|
-O on page 889 |
Never add a null byte. |
|
|
-o on page 889 |
This database map is optional. |
|
|
-q on page 889 |
Don’t strip quotes from key. |
|
|
-S on page 890 |
Space replacement character. |
|
|
-T on page 890 |
Suffix to append on temporary failure. |
|
|
-t on page 891 |
Ignore temporary errors. |
|
|
Deprecated, and as of V8.13 removed, use -k instead. | |
[a] a As of V8.10,
_FFR_PHMAP_TIMEOUT must be defined when compiling
sendmail to enable this
| ||
This ph database
map was contributed by Mark Roth of the University
of Illinois at Urbana-Champaign. For additional
information see:
| http://www.feep.net/sendmail/phmap/ |
The -h
switch is used to specify the host to which to
connect for the lookup. In general, the host
specified should be a fully qualified
hostname:
-h phserver.your.domain
In the event you wish to employ multiple
ph servers, you
can list them, one separated from the next by a
space character:
-h "phserver.your.domain phserver2.your.domain"
Because the host list contains space characters, it must be quoted.
Note that this -h switch is mandatory. If it is
omitted, the following error is printed and
logged:
ph_map_parseargs: -h flag is required
The -k
switch[350] specifies a quoted, space-delimited
list of fields to query.[351] Fields are queried in the order
listed, and the first query that returns a single
match is the one whose returned value is used. If
the -k switch
is omitted, the list of fields to query is
obtained by looking up the mailmatches field in the
ph server’s siteinfo list.
Run an external program to look up the key V8.7 and later
The program type
allows you to perform lookups via arbitrary external
programs. The form for the declaration of this
database-map type looks like this:
Kname program /path arg1 arg2 ...The /path must be the full
pathname to the program. Relative paths will not
work, and attempts to use them will log the
following error and cause the lookup to fail:
NOQUEUE: SYSERR(user): relative name: cannot exec: No such file or directory
The program is run as the user and group specified by
the DefaultUser
option (DefaultUser on page 1000)
unless the RunAsUser option (RunAsUser on page 1083) is declared,
in which case it will run as the user and group
declared by that latter option.
The arguments to the program always have the key to be looked up added as a final argument:
Kname program /path arg1 arg2 ... ↑ key added here
This is the only way the key can be passed to the program. The key will specifically not be piped to the program’s standard input.
The value (result of the lookup) is read from the
program’s standard output. Only the first MAXLINE-1
characters are read (where MAXLINE is defined in
conf.h, currently as 2048).
The read result is processed like an address and
placed into the workspace (unless the -m switch is used with
the K
command).
To illustrate, consider the need to look up a user’s preferred address in an external relational database:
Kilook program /usr/sbin/ingres_lookup -d users.database
This program has been custom-written to accept the key as its final argument. To prevent spurious errors, it exits with a zero value regardless of whether the key is found. Any system errors cause it to exit with a value selected from those defined in <sysexits.h > (those recognized by sendmail). Error messages are printed to the standard error output, and the found value (if there was one) is printed to the standard output.
In general, it is better to use one of the database formats known to sendmail than to attempt to look up keys via external programs. The process of fork(2)ing and exec(2)ing the program can become expensive if it is done often, slowing down the handling of mail.
This type of database map employs only a small set of switches. They are listed in Table 23-23.
|
Switch |
§ |
Description |
|
|
-a on page 887 |
Append tag on successful match. |
|
|
-D on page 887 |
Don’t use this database map if |
|
|
-m on page 888 |
Suppress replacement on match. |
|
|
-q on page 889 |
Don’t strip quotes from key. |
|
|
-S on page 890 |
Space replacement character. |
|
|
-T on page 890 |
Suffix to append on temporary failure. |
|
|
-t on page 891 |
Ignore temporary errors. |
Use regular expressions V8.9 and later
The regex type
allows you to parse tokens in the workspace using
POSIX regular expressions. For information on how to
use regular expressions, see the online manuals
ed(1) and
regexp(1). A regex database-map type
is declared like this:
Kname regex expression
The name is the symbolic
name you will use to reference this database map
from inside the RHS of rule sets. The
expression is the
literal text that composes your regular expression.
Here is a simple example:
Knumberedname regex ^[0-9]+<@(aol|msn).com.?>
The intention here is for this regular expression to
match any address that has an all-numeric user part
(the part before the <@) and a domain part that is either
aol.com or
(the | character)
msn.com. To
make rules that use this type easier to write, you
can add a -a
switch to the declaration:
Knumberedname regex -a.FOUND ^[0-9]+<@(aol|msn).com.?>
Here the -a
database switch causes .FOUND to be appended to any successful
match.
Note that because of the way we have declared this
database map, nothing but the suffix will be
returned on a successful match. To get the original
key returned you need to also use the -m database switch
(-m on page 888).
This regex type can
use a number of switches to good advantage. The
complete list is shown in Table 23-24.
|
Switch |
§ |
Description |
|
|
-a on page 887 |
Append tag on successful match. |
|
|
The -b regex database-map switch on page 933 |
Use basic, not extended, regular expression matching. |
|
|
-D on page 887 |
Don’t use this database map if |
|
|
The -d regex database-map switch on page 934 |
The delimiting string. |
|
|
-f on page 887 |
Don’t fold keys to lowercase, and cause the regular expression to match in a case-insensitive manner. |
|
|
-m on page 888 |
Suppress replacement on match. |
|
|
The -n regex database-map switch on page 934 |
NOT—that is, invert the test. |
|
|
-q on page 889 |
Don’t strip quotes from key. |
|
|
-S on page 890 |
Space replacement character. |
|
|
The -s regex database-map switch on page 934 |
Substring to match and return. |
|
|
-T on page 890 |
Suffix to append on temporary failure. |
|
|
-t on page 891 |
Ignore temporary errors. |
Note that some additional explanation for a few of
these switches is provided in the sections that
follow. Also, for an actual example of the regex type, see the file
cf/cf/knecht.mc, which
demonstrates a way to deal with one type of spam
email.
The -b
switch limits the regular expression to a more
limited but faster form. If you are using only
simple regular expressions, as in the nature of
those defined by ed(1), you
can use this -b
switch to slightly speed up the process:
Kmatch regex -b -aLOCAL @localhost
Here, the search is for a workspace that
contains the substring @localhost. Because this is a very
simple regular expression, the -b switch is
appropriate. If you use the -b on a complex match
(such as the one in the previous section’s
-n example),
you might see an error such as this:
configfile: line num: field (2) out of range, only 1 substring in pattern
There might be times when you would prefer
some other character, operator, or token to
replace the $|
that is returned when using the -s switch. If so, you
can specify a different one with the -d database switch.
Consider:
Kmatch regex -s2,3-d+|+-a.FOUND (\<a\>|\<b\>)@(\<bob\>|\<ted\>).(\<com\>|\<org\>)
Here, we specify that the three characters
+|+ will
replace the single operator $| in the returned
value:
> test a@bob.com
test input: a @ bob . com
test returns: bob+|+com . FOUNDNote that here the bob+|+com is a single token.
You can opt to have the original key returned.
This is done by specifying the -m database
switch:
Kmatch regex -s2,3-m-d+|+ -a.FOUND (\<a\>|\<b\>)@(\<bob\>|\<ted\>).(\<com\>|\<org\>)
Note that the -m switch overrides the presence of the
-s and -d switches:
> test a@bob.com
test input: a @ bob . com
test returns: a @ bob . com . FOUNDThe -n
switch inverts the entire sense of the regular
expression lookup. It returns a successful match
only if the regular expression does
not match. Consider:
Kmatch regex -m-n-a.FOUND (\<a\>|\<b\>)@(\<bob\>|\<ted\>).(\<com\>|\<org\>)
If you view the effect of this switch in rule-testing mode, you will see that the result is inverted:
> test a@bob.com test input: a @ bob . com test returns: a @ bob . com > test x@y.net test input: x @ y . net test returns: x @ y . net . FOUND
The -s
database-map switch is used with the regex type to specify a
substring to match and return. To illustrate,
consider the following mini configuration
file:
V10
Kmatch regex -s (\<bob\>|\<ted\>)
Stest
R $* $@ $(match $1 $)The regular expression looks to match either
the name bob or
the name ted,
but no other names. The -s says to return the substring
actually matched in the expression along with the
key, the two separated from each other by a
$| operator.
Now, observe this mini configuration file in
rule-testing mode:
%/usr/sbin/sendmail -bt -Cdemo.cfADDRESS TEST MODE (ruleset 3 NOT automatically invoked) Enter <ruleset> <address> >test bobtest input: bob test returns: bob $| bob >test alicetest input: alice test returns: alice
By adding a -a switch, which appends text to the
matched key:
Kmatch regex -s -a.FOUND (bob|ted)we see that the matched key with -s is second:
> test bob
test input: bob
test returns: bob $| bob . FOUNDWhen multiple substrings can be matched, the
-s database
switch can be used to specify which substring
match to return. Consider:
Kmatch regex-s2-a.FOUND (\<a\>|\<b\>)@(\<bob\>|\<ted\>)
There are two substring searches here, first
the (\<a\>|\<b\>) choice and
then the (\<bob\>|\<ted\>) choice.
Because the -s
has a 2 as its
argument, the second matched substring will be
returned, not the first:
> test a@bob
test input: a @ bob
test returns: bob . FOUNDIn more complex expressions, it might be
desirable to return multiple substrings. To do
that just list them following the -s with each separated
from the next by a comma:
Kmatch regex-s2,3-a.FOUND (\<a\>|\<b\>)@(\<bob\>|\<ted\>).(\<com\>|\<org\>)
When multiple substrings are listed in this
way, they are separated by the $| operator when they
are returned:
> test a@bob.com
test input: a @ bob . com
test returns: bob $| com . FOUNDSearch a series of database maps V8.7 and later
The sequence type
allows you to declare a single name that will be
used to search a series of databases. It is declared
like this:
Kname sequence map1 map2 ...
Here, a key (in a later rule set) will be looked up
first in the database map named
map1, and if not found
there, it will be looked up in the database map
named map2. The type of
each of the listed database maps should logically
relate but need not be the same. Consider, for
example, a rule’s RHS, where a lookup will match if
the workspace contains either a user’s login name or
the name of a host, with the hostname taking
precedence:
Khosts host -a<+> /etc/hosts Kpasswd user -a<-> /etc/passwd Kboth sequence hosts passwd R$- $: $(both $1 $)
Here, we say that the database map named both is of type sequence. Any single
token in the LHS will be looked up first in the
database map named hosts, and if it is found there the
hostname will be returned with a <+> appended. If
it is not found in the hosts database map, it will be next
looked up in the passwd database map. If it is found
there, the original workspace will be returned with
a <->
appended. If the workspace is not found in either
database map, the lookup fails and the workspace
remains unchanged.
If any database map in the series of database maps
declared with the K command does not exist, as for
example:
Kboth sequence hosts passwd badnamethe following error is logged and printed, and that database map is ignored:
Sequence map both: unknown member map badname
If the number of database maps that are sequenced exceeds the maximum allowed (MAXMAPSTACK in conf.h, currently 12), the following error is printed and the overflow of database maps is ignored:
Sequence map name: too many member maps ( max max)
None of the K
command switches can be used with the sequence type. If you
try to use any, they will be wrongly interpreted as
database-map names.
Perform lookups over a socket V8.13 and later
Beginning with V8.13 sendmail, a
new database-map type called socket is available for
your use.[352] You declare a socket database-map type like
this:
Kname socket type:port@hostHere, is
the identifier that you will later use in rule sets.
The name
is declared in the same fashion as a Milter is
declared using the X configuration command (The X Configuration Command on page
1173). For example:type:port@host
Ktrustedip socket inet:8020@db5.example.gov
Here, lookups can be made in rule sets using the
database map named trustedip. The
sendmail program will make an
IPv4 connection (the inet) to port 8020 on the host db5.example.gov. Once
the connection has been made, lookups are performed
using a simple dialog that looks like this:
sendmail sends: database_map_name key sendmail receives: status datum
Note that neither the request sent nor the reply received may end in a carriage-return/linefeed pair, a carriage return, or a line feed. Also note that the two parts of each dialog are separated by a single space character.
Both the request and the reply begin and end with characters that denote their length and termination. The length is an ASCII representation of the number of characters sent or received, stated as a prefix and a colon. Both the request and the reply are terminated by a comma. But note that the length prefix must not include the comma in its length computation. For example:
sendmail sends: 17:trustedip 1.2.3.4, sendmail receives: 14:OK VERYTRUSTED,
The sendmail
program sends the database-map name declared earlier
using a K
configuration command. In our example, that would be
the database map named trustedip. That name is followed by a
single space and then the key to look up in the
database. Again, the entire request is prefixed with
the length and a colon and terminated with a comma
(and excludes any terminating newline or
carriage-return characters).
The connected-to host replies with one of the keywords shown in Table 23-25. Each must be completely uppercase. Each keyword is followed by a single space, then information appropriate to the keyword (the keyword OK, for example, would be followed by the sought datum). The entire reply is prefixed with a length and a colon and terminated with a comma.
|
Keyword |
Description |
|
OK |
The key was found in the database, and the datum is the value sought. |
|
NOTFOUND |
The key was not found in the database, and the datum is empty. |
|
TEMP |
A temporary failure occurred while performing the lookup. The datum may contain an explanatory message. |
|
TIMEOUT |
The lookup timed out. The datum may contain an explanatory message. |
|
PERM |
A permanent failure occurred while performing the lookup. The datum may contain an explanatory message. |
To illustrate, consider the need to look up the name
of the central mail server for your department. If
such a database map were called mailservers, you could
use the following configuration file line to look up
your domain in that database map:
Kmailservers socket -o inet:8020@db4.example.gov ... R $* <@ $+ > $* $: $1<@$2>$3 <$(mailservers $2 $)> R $* <@ $+ > $* <$+> $#smtp $@ $4 $: $1 < @ $2 > $3 ...
Here, we look up the host part of an address ($2) in the mailservers database on
the host db4.example.gov. The -o makes the existence
of the database map optional. If the host part is
found, it is rewritten to be the name of the mail
server for that host. Finally, in the last rule, we
forward the original address to that server.
Note that only a few database switches (shown in Table 23-26) are available with this socket database-map type.
|
Switch |
§ |
Description |
|
|
-a on page 887 |
Append tag on successful match. |
|
|
-D on page 887 |
Don’t use this database map if |
|
|
-f on page 887 |
Don’t fold keys to lowercase, and cause the regular expression to match in a case-insensitive manner. |
|
|
-m on page 888 |
Suppress replacement on match. |
|
|
-N on page 889 |
Append a null byte to all keys. |
|
|
-O on page 889 |
Never add a null byte. |
|
|
-o on page 889 |
This database map is optional. |
|
|
-q on page 889 |
Don’t strip quotes from key. |
|
|
-S on page 890 |
Space replacement character |
|
|
-T on page 890 |
Suffix to append on temporary failure |
|
|
-t on page 891 |
Ignore temporary errors. |
Note that the socket database-map type is available
only if sendmail is compiled with the
SOCKETMAP compile-time macro (SOCKETMAP on page 145) defined when
you build sendmail (which is normally not done
by default).
For examples of how to use this new socket database-map
type, see the files contrib/socketmapServer.pl and
contrib/socketmapClient.pl.
Internally load aliases into the symbol table V8.10 and later
The stab
database-map type is used internally by
sendmail to load the raw
aliases(5) file into its
internal symbol table.[353] This is a fallback position that is
taken if no database form of aliasing is
found.
The stab type
should never be used in
configuration files.
Build sequences based on service switch V8.7 and later
The switch
database-map type is used internally by
sendmail to create sequence types of
database maps based on external service-switch
files. The lines inside a service-switch file look
like this:
service methodA methodBas, for example:
aliases files nis
This line tells sendmail to search for its aliases in files first, and then using NIS.
To illustrate the switch type, consider the need to look
up aliases inside rule sets in the same way that
sendmail looks up its own
aliases. To do this, you would declare a switch database map. For
example:
Kali switch aliases
This causes sendmail to search
for the service named
aliases in the
service-switch file. In this example it finds such a
line, so for each how
that follows the aliases in that line,
sendmail creates a new
database map with the name ali followed by a dot and the
how:[354]
aliases files becomes → ali.files aliases nis becomes → ali.nis
These named database maps are then sequenced for you.
Recall that sequence database maps are declared
like this:
Kname sequence map1 map2,...
The name given to the
sequence is ali. In our
example, the following sequence is automatically
created for you from your original switch
declaration:
Kali sequence ali.files ali.nis
In rule sets, when you look up aliases with the
ali database
map:
R... $( ali $1 $)
↑
the sequence named aliyou will use the sequence named ali that was automatically built for
you from a combination of your original switch definition and
your service-switch file’s aliases line. That is, you declare a
switch, but you
use a sequence.
Log information using syslog(3) via rule sets V8.10 and later
The syslog
database-map type allows you to log messages
directly from inside rule sets. If you are
unfamiliar with syslog, see
Log with syslog on page 513 for
a general discussion of
syslog-style logging.
The syslog type is
declared like this:
Kname syslog switches
The name is the database-map name you will use in rule sets. The switches are selected from those shown in Table 23-27.
|
§ |
Description | |
|
|
-D on page 887 |
Don’t use this database map if |
|
|
The -L syslog database-map switch on page 940 |
The logging level at which to log. |
|
|
-S on page 890 |
Space replacement character. |
In rule sets, the syslog type is used, for example, like
this:
R $* $: $(name what to log $)The information in the position of the key is logged as is via
the syslog facility. An empty
workspace is returned as a result of logging. That
is, for the syslog type, the $( and $) expressions evaluate
to an empty string.
Any use of defined macros in the message should use
the $& prefix
so that the current value is logged. For example,
the following might be used to log the load
average:
Kdolog syslog
R $* $: $(dolog The cutoff was caused by a load average of $&{load_average}. $)If you need to have a sendmail
macro or positional macro literally logged as is,
just prefix it with an extra $ character. For
example, the following shows the macro and logs its
value:
R $* $: $(dolog Failure detected with $$1=$1 $)
Don’t use quotation marks to surround macro
references. Quotation marks cause the macro’s
internal binary value to print, instead of its
defined value. For example, the following will log
$1=^U1:
R $* $: $(dolog $$1="$1" $) ← wrongIf macros are not included inside quotation marks, you can use quotation marks for clarity. They will be stripped from the output:
R $* $: $(dolog "Aborting the use of ETRN because of high load" $)
In general, this syslog type of
database map will be used in conjunction with other
database maps that can make decisions about
behavior, such as arith (arith on page
898). You should avoid the temptation to overlog
because rule sets can be parsed every time mail is
sent or received, and if you place a logging rule in
the wrong place, you risk flooding your site’s
syslog facility with
extraneous messages.
Normally, the logging priority (syslog(3) on page 514) defaults to LOG_INFO. If this
priority is inappropriate, you can change it with
this -L switch.
Just specify the new priority following the
-L. The
following, for example, sets the logging priority
to LOG_CRIT:
Kname syslog -LLOG_CRITNote that omitting the leading four characters
after the -L
switch (the LOG_) but leaving the rest (the CRIT)
will also work:
Kname syslog -LCRITIf an unknown or unsupported priority is specified, the following error will be logged and printed:
syslog_map_parseargs: Unknown priority LOG_MAIL
Here, the syslog facility LOG_MAIL was wrongly used in place of a priority.
Look up in flat text files V8.7 and later
The text
database-map type allows you to look up keys in flat
text files. This technique is vastly less efficient
than looking up keys in real databases, but it can
serve as a way to test rules before implementing
them in database form.
For the text
database map, columns for the key and value are
measured as an index. That is, the first column is
number 0. To illustrate, consider the following mini
configuration file that can be used to check
spelling:
Kspell text /usr/dict/words Spell R$- $: $(spell $1 $: not in dictionary $)
The /usr/dict/words file contains only a single column of words. This rule shows that the key is (by default) the first column (index 0). And the value is (by default) also the first column (index 0).
For more sophisticated applications you can specify
the key’s column (with the -k switch), the value’s column (with
the -v switch),
and the column delimiter (with the -z switch). To
illustrate, consider the need to look up a
user-id in the
/etc/passwd file and to
return the login name of the user to whom it
belongs:
Kgetuid text -k2 -v0 -z: /etc/passwd R$- $: $(getuid $1 $)
The lines of a password file look like this:
ftp:*:1092:255:File Transfer Protocol Program:/u/ftp:/bin/sh
The third column (where the columns are separated by
colons) is the uid field. The
first is the login name. Note that the -k and -v switches show these
fields as indexes, where the first is 0 and the
third is 2.
Note that if a file cannot be opened because it is unsafe (DontBlameSendmail on page 1009), the following warning will be logged and printed:
text map "name": unsafe map file filename
This message will not be printed if the -o switch is specified
with the database-map declaration.
Only a handful of database switches are available with
this text type.
The are listed in Table 23-28.
|
§ |
Description | |
|
|
-a on page 887 |
Append tag on successful match. |
|
|
-D on page 887 |
Don’t use this database map if |
|
|
-f on page 887 |
Perform a case-insensitive search. |
|
|
-k on page 888 |
Specify column for key or key name. |
|
|
-m on page 888 |
Suppress replacement on match. |
|
|
-o on page 889 |
This database map is optional. |
|
|
-q on page 889 |
Don’t strip quotes from key. |
|
|
-S on page 890 |
Space replacement character. |
|
|
-T on page 890 |
Suffix to append on temporary failure. |
|
|
-t on page 891 |
Ignore temporary errors. |
|
|
-v on page 891 |
Specify the value’s column. |
|
|
-z on page 891 |
Specify the column delimiter. |
The -d38.20
debugging command-line switch (-d38.20 on page 568) is available to
watch this text
type.
Look up in the User Database V8.7 and later
The User Database is a special database file that you
create for use by sendmail. It
causes sender and recipient addresses to be
rewritten under control of an external database.
Ordinarily, any local address is first looked up in
the aliases database. If it is
not found there, that user’s
~/.forward is next examined.
If the User Database is enabled, the address is
looked up in that database after aliasing and before
forwarding, but only if the selected delivery agent
has the F=@ flag
set (F=@ on page
766).
In the sections that follow, we describe the use of this database in detail, but first we will note a few important points.
Although we illustrate here that a lookup can be done using a database file, a remote lookup can also be done via a User Database server, or via a network service. Those forms of lookup are described in UserDatabaseSpec on page 1116.
You can also look up addresses in the User Database
with rule sets using this userdb database-map type. To do so, you
declare it like this:
Kname userdb switches field
Here, the name is
the name you will use in later rule sets. The
field is either a
literal maildrop
or mailname (see
Create the User Database on page
944). The possible
switches are shown in
Table 23-29.
|
§ |
Description | |
|
|
-a on page 887 |
Append tag on successful match. |
|
|
-D on page 887 |
Don’t use this database map if |
|
|
-f on page 887 |
Perform a case-insensitive search. |
|
|
-m on page 888 |
Suppress replacement on match. |
|
|
-q on page 889 |
Don’t strip quotes from key. |
|
|
-S on page 890 |
Space replacement character. |
|
|
-T on page 890 |
Suffix to append on temporary failure. |
|
|
-t on page 891 |
Ignore temporary errors. |
One use for this database-map type might be to
intercept each RCPT
To: address, and log whether it will be
transformed by the User Database:
Kudb userdb -f -a.FOUND maildrop Klog syslog SLocal_check_rcpt R $* $: $>canonify $1 R $+ < @ $* > $* $: $1<@$2>$3 $| $(udb $1 $) R $* $| $* . FOUND $: $(log $1 transformed by userdb into $2 $) $1
Here, we declare a userdb database-map type called
udb. The
-f says to look
up addresses in a case-insensitive manner. The
-a says to
append a literal .FOUND to any match. Finally, the
maildrop says
to look up a recipient address with a :maildrop suffix
attached.
We also declare a syslog database-map type (syslog on page 939) named log, which we will use
to syslog the result.
The rule set in Local_check_rcpt (Local_check_rcpt and check_rcpt
on page 257) contains three rules, and they are
called just after each RCPT
To: command. In the first rule, we make
sure the address is focused. In the second rule, we
first arrange to return the original address in the
workspace (the $1<@$2>$3 in the RHS) and a
$| separator.
Then we perform the lookup and add that result to
the workspace.
The third rule looks for a workspace that ends in a
literal .FOUND
and, if it finds such a workspace, logs the result.
For a focused address such as
gw<@wash.dc.gov>, the
result might be:
gw<@wash.dc.gov> transformed by userdb into george@retired.wash.dc.gov
The User Database is automatically enabled
when you compile sendmail if
you include support for NEWDB or HESIOD (USERDB on page 150). To see whether a
precompiled version of
sendmail includes User
Database support, run it with the -d0.1 switch:
%/usr/sbin/sendmail -d0.1 -bt < /dev/nullVersion 8.12 Compiled with: LOG MIME8TO7 NETINET NETUNIX NEWDB SCANFUSERDBXDEBUG ↑ note
If USERDB is listed, User Database support is included.
Next, you must declare the location of the
database file with the UserDatabaseSpec option (UserDatabaseSpec on page 1116):
OU/etc/mail/userdb ← in your cf file (V8) O UserDatabaseSpec=/etc/mail/userdb ← in your cf file (V8.7 and later) define(`confUSERDB_SPEC', /etc/mail/userdb) ← in your mc file
Here, the location of the database file is set
to be /etc/mail/userdb. You
can also enable a default location for the
database file that will take effect should the
UserDatabaseSpec option be missing by
defining that location with UDB_DEFAULT_SPEC when
compiling (UDB_DEFAULT_SPEC
on page 149).
The User Database is a btree-type (btree on page 901) database file
created from a source text file using the
makemap program:
% makemap btree /etc/mail/userdb.db < /etc/mail/userdb
↑
this type is mandatory for the User DatabaseHere, /etc/mail/userdb is
the source-text file that is input, and
/etc/mail/userdb.db is the
database we are creating (the one defined by the
UserDatabaseSpec option in the previous
section).[355]
The source text file is composed of key and value pairs, one pair per line:
key value ↑ whitespace
The key is a user’s
login name, a colon, and one of two possible
keywords: maildrop or mailname. The keyword determines the
nature of the
value:
maildropFor maildrop, the
value is the official
delivery address for this user. If there are
multiple official addresses, they can be listed as
a single compound value, with separating commas.
For example:
root:maildrop sysadmin@here.us.edu,bill@there.us.edu
Or they can be listed on individual lines:
root:maildrop sysadmin@here.us.edu root:maildrop bill@there.us.edu
This latter form requires you to use the
-d command-line
switch with the makemap(1)
program (-d on page 372) when
creating the database, but it has the advantage of
being a simpler source file to manage.
mailnameThe mailname keyword causes a “reverse
alias” transformation. That is, it causes the
login name in the key to be changed into the
address in the value for outgoing mail. For
example:
bob:mailname Bob.Roberts@Here.US.EDU
This causes mail sent by bob to go out addressed
as though it is from Bob.Roberts@Here.US.EDU.[356] This transformation occurs in the
header and envelope. But note that the sender
envelope is not rewritten by UDB unless the
F=i flag (F=i on page 772) is present in
the delivery agent that is selected for the
sender. Also note that the recipient headers are
not rewritten by UDB unless the F=j flag (F=j on page 773) is set for the
delivery agent that was selected for the
recipient.
Naturally, the maildrop and mailname keywords should occur in
pairs. Each outgoing address that is created with
mailname should
have a corresponding maildrop entry so that return mail can
be delivered. In the previous example, a
reasonable pair might look like this:
bob:mailname Bob.Roberts@Here.US.EDU Bob.Roberts:maildrop bob
Here, outgoing mail from the user named
bob will be
addressed as though it is from Bob.Roberts@Here.US.EDU.
Incoming mail (whether it is original or in reply
to the outgoing mail) will be addressed as though
it is to the name Bob.Roberts, which will be transformed
into and delivered to the local user bob.
The mailname keyword allows the host part
of outgoing addresses to mask the real hostname of
the originating machine. This property can, for
example, be used to convert the hostname into a
firewall name:
bob:mailname bob@Firewall.US.EDU
Here, the canonical name of bob’s machine is
Here.US.EDU.
The mailname
keyword causes outgoing mail from bob to appear as though
it is from the firewall machine (Firewall.US.EDU)
instead.
Ordinarily, this transformation is not
automatic. Each username that is to appear to be
from the firewall machine will need an entry such
as that in the User Database (see earlier
example). To automate this process, you can use
the special username :default in a mailname declaration:
:default:mailname Firewall.US.EDU
If a maildrop entry is found for a
particular name, but no corresponding mailname record is
found, the outgoing address is ordinarily
unchanged. If, however, a default hostname has
been defined with :default, that hostname replaces the
local hostname for all addresses that lack their
own mailname
entry:
:default:mailname Firewall.US.EDU bob:maildrop bob@here.us.edu
In this example, the user bob has a maildrop entry but lacks
a mailname
entry. Outgoing mail from this user will have the
:default
hostname used instead of the local hostname. The
user sally, on
the other hand, has neither a maildrop entry nor a
mailname entry
and so will not have her outgoing address
rewritten.
Look up local passwd information V8.7 and later
The user type is
used to look up passwd(5)
information using the method defined by the MailboxDatabase option
(MailboxDatabase on page 1042).
A password entry typically looks like this:
ftp:*:1092:255:File Transfer Protocol Program:/u/ftp:/bin/sh
Here, there are seven fields, each separated from the
others by colon characters. The key is always
compared to the first field. The value returned is
(by default) the first field unless you specify
another field with a -v switch:
Kname user -vfield
Here, field can be either a
number 1 through 7, or one of the names name, passwd, uid, gid, gecos, dir, or shell, which correspond
to the numbers. For example, to look up usernames
and get the full name (GECOS) field returned, you
could use something such as this:
Kgetgecos user -vgecos ... R$- $: $( getgecos $1 $)
Note that this returns the full GECOS field in its
rawest form. It is not cleaned up to provide a
reliable full name, as is the $x macro ($x on page 851).
The user
database-map type can be used in conjunction with
the Local_check_rcpt rule set (Local_check_rcpt and check_rcpt
on page 257). In the following, for example, we
check to see whether a recipient is a local user
and, if so, reject the user if that user’s home
directory is
/home/retired/tars:
Kislocal user -vdir SLocal_check_rcpt R$* $: $>canonify $1 focus on host R$* <@ $+ > $* $: $1 discard host R$+ $: $1 $(islocal $1 $) R$- /home/retired/tars $#error $@ 5.1.3 $: 553 Sorry, $1 is retired, no forwarding
Here, we focus on the host part with the canonify rule set 3, and
then discard all but the user part in the second
rule. The third rule performs the lookup. If the
user is not found, that username is returned
unchanged. If, on the other hand, the user is found,
that user’s name and home directory are placed into
the workspace. The last rule rejects any SMTP RCPT
command that contains a local-user part whose home
directory is
/home/retired/tars.
Only a few database switches are useful with this
user type. All
are listed in Table 23-30.
|
Switch |
§ |
Description |
|
|
-a on page 887 |
Append tag on successful match. |
|
|
-D on page 887 |
Don’t use this database map if |
|
|
-m on page 888 |
Suppress replacement on match. |
|
|
-q on page 889 |
Don’t strip quotes from key. |
|
|
-S on page 890 |
Space replacement character. |
|
|
-T on page 890 |
Suffix to append on temporary failure. |
|
|
-t on page 891 |
Ignore temporary errors. |
|
|
-v on page 891 |
Specify the column to return. |
This user
database-map type can be watched with the -d38.20 debugging
command-line switch (-d38.20 on
page 568).
[337] * This simplified example won’t work if the /etc/hosts file has multiple hostnames on the righthand side. For more complicated situations such as this, a shell script might be required.
[338] * The
sendmail source calls this
class, but we
chose type to make it
clear that this is different from class
macros.
[339] * This is true as
of V8.12. Future versions might change the
semantics of the K line such that switches can
follow.
[340] * Note that the
-m switch
(-m on page 888) prevents the
found value from replacing the $( and $) enclosed
expression.
[341] * Note that this
substitution technique does not work for most
internal database-map types. For example, it does
not work with arith or dequote, but it does work with regex.
[342] * This happens
only for V2 and higher configuration files. Below
that level, the dot is not appended unless it is
specifically added by the -a of the K command.
[343] * However, space is reclaimed in the file for future use.
[344] * We are clutching at straws here for an example. Note that sendmail already does all this, including looking up more than just the first MX record.
[345] * We are
clutching at straws here for an example. Note that
sendmail already does all
this for you and puts the result in the ${client_resolve} macro
(${client_resolve}
on page 814).
[346] * If you need to
find the lowest-cost (or other preference) MX
record, or multiple MX records, use the bestmx database map
instead (bestmx on page
902).
[347] * Under LDAP, binding to the server is sort of like “logging in” to a Unix machine.
[348] * Note, however, that if you wish to use Unix domain sockets, your underlying LDAP library must support Unix-domain sockets.
[349] * Note that under NIS+, names cannot contain a dot, whereas under NIS they can—for example, mail_aliases for NIS+ but mail.aliases for NIS.
[350] * This used to be
the -v switch,
but -v has been
deprecated in this role.
[351] † Note that the
spacedname
field name is no longer understood by
ph.
[352] * The sendmail program needs to be built with SOCKETMAP defined (SOCKETMAP on page 145) in order to use this new database-map type. NETUNIX is required to use Unix-domain sockets but is generally defined by default.
[353] * As such, it is
somewhat misnamed. One might reasonably expect a
type named stab
to provide access to the symbol table, but alas,
this is not so.
[354] * Your switch database-map
declaration references the new database maps named
ali.files and
ali.nis. These
must be declared before the switch database map is
declared. Note that switch database-map declarations
always reference other
database-map names!
[355] * The .db is added
automatically if it is missing. We include it here
for clarity.
[356] † Using full names in outgoing mail is probably not a good idea. Unlike login names, full names are not guaranteed to be unique. If current users expect to be able to receive mail under full names, future users with the same full name might be out of luck. Always weigh convenience against maintainable uniqueness when designing your mail setup.