In this section we detail each of the general macros available when configuring with the m4 technique. Here we list them in alphabetical order.
This reference is not comprehensive. Options, macros, and delivery agents, for example, are described in chapters dedicated to those topics.
The BITNET relay
(V8.1 and above)The host that will forward BITNET-addressed email. If not defined, the .BITNET pseudo-domain won't work. See Section 31.10.5 for a description of this relay and of the
$B
macro.
The DECnet relay
(V8.7 and above)The host that will forward DECnet addressed email. If not defined, the .DECNET pseudo-domain won't work, nor will an address of the form node::user. See Section 31.10.9 for a description of this relay and of the
$C
macro.
Insert literal $ in m4 output
(V8.1 and above)Ordinarily, the
$
character is interpreted by m4 inside itsdefine
expressions. But for ambitious undertakings, such as designing your own DOMAIN, FEATURE, or HACK files, you may need to include reference to a macro or operator (and hence a$
) inside an m4define
expression. The way you do this is with the DOL m4 macro. For example,define(`DOWN', `R DOL(*) < @ $1 > DOL(*) DOL(1) < @ $2 > DOL(2)')Here, we define the m4 macro named DOWN, which takes two arguments (
$1
and$2
). When used in one of your.m4
files,DOWN(badhost, outhost)it creates a rule by substituting the above arguments for the corresponding
$1
and$2
in its original definition:R $* < @ outhost > $2The DOL m4 macro in the original definition allowed the insertion of
$
characters (such as$*
) while protecting those characters from being wrongly interpreted by m4.Needless to say, you should never redefine the DOL macro.
Masquerade all but these
(V8.6 and above)Class macro
$=E
is used by the V8 configuration file to hold a list of usernames that should never be masqueraded (even if masquerade is enabled with the MASQUERADE_AS m4 macro). By default, the user root is always in that class. There are two ways to add usernames to the classE
. They can be added individually with the EXPOSED_USER m4 macro:EXPOSED_USER(user
)Here, we cause the name
user
to be appended to the classE
. This is identical to the following use of LOCAL_CONFIG to add to the class directly:LOCAL_CONFIG CE userIf you wish to store the list of nonmasqueradable users in an external file, you can cause that file to be read with an
F
configuration command (see Section 32.1.2, "The F Class Command"):LOCAL_CONFIG FE/usr/local/mail/visible.users
The FAX relay
(V8.6 and above)The host that will forward email faxes. If not defined, and if you don't have a
fax
delivery agent on your local machine, the .FAX pseudo-domain won't work. See Section 31.10.15 for a description of this relay and of the$F
macro. Note that if you service faxes locally, you will also need to declare the fax delivery agent with the MAILER() m4 command instead (see Section 19.3.2).
Masquerade the sender too
(V8.2 and above)If a MASQUERADE_AS host is defined, that hostname replaces all sender addresses. The
allmasquerade
feature causes header recipient addresses to also have that treatment.But note that this feature can be extremely risky and that it should be used only if the MASQUERADE_AS host has an aliases file that is a superset of all aliases files and a passwd file that is a superset of all passwd files at your site. To illustrate the risk, consider a situation in which the masquerade host is named hub.domain and mail is being sent from the local workstation. If a local alias exists, say thishost-users, that does not also exist on the masquerade host, this
allmasquerade
feature will cause theTo:
header to go out as:To: [email protected]Here, the address thishostusers does not exist on the masquerade host, and as a consequence, replies to messages containing this header will bounce.
The form for the
allmasquerade
feature is:define(`MASQUERADE_AS', `your.hub.domain
') FEATURE(`allmasquerade')Note that MASQUERADE_AS (see Section 19.6.42) must also be defined and must contain a fully qualified hostname.
Add the local domain even on local mail
(V8.1 and above)Normally, header recipient addresses and header and envelope sender addresses that select the
local
orprog
delivery agents are left as is. If thealways_add_domain
feature is defined, local addresses that lack a host part have an@
and the MASQUERADE_AS host appended (if it is defined). If MASQUERADE_AS is not defined, an@
and the value of$j
(see Section 31.10.20, $j) are appended.The form for the always_add_domain feature is
FEATURE(`always_add_domain')The
always_add_domain
feature is safe and recommended. It ensures that all addresses that are locally delivered will be fully qualified. See theallmasquerade
feature for a description of the risks surrounding masquerading addresses.
Accept best MX record as local if in $=w
(V8.6 and above)The class
w
(see Section 32.5.8) is recommended for defining which hostnames will be treated as being equivalent to the local hostname. That method, however, requires that the mail administrator manually keep the class up to date.As an alternative, for low- to medium-volume sites, use the
bestmx_is_local
feature. When enabled, this feature looks up each hostname that it finds in thebestmx
internal database map (see Section 33.8.2, bestmx). That map returns the best MX record (if it is known) for that name. That returned record is then compared to the list of hostnames in classw
to see whether it is equivalent to the local host. If so, the address is accepted for local delivery.The form for the
bestmx_is_local
feature:FEATURE(`bestmx_is_local')If you wish to limit lookups to a small list of domains, you can add them as a second argument:
FEATURE(`bestmx_is_local', `domain1 domain2 etc.')The list of domains is added to the class
$=B
. Only hosts in those domains are allowed to list your site as the best MX record for use with this feature.Use of this feature is best limited to low-volume sites. Looking up every address in the
bestmx
map can cause numerous DNS enquiries. At high-volume sites the magnitude of extra DNS enquiries can adversely tax the system.There is also a risk to this feature. Someone could create an MX record for your site without your knowledge. Bogus mail might then be accepted at your site without your permission.
bogus.site.com. IN MX 0 your.real.domainHere, mail to bogus.site.com would be sent to your site, where the name bogus.site.com would be looked up with the
bestmx_is_local
feature. Your sendmail would find itself listed as MX for bogus.site.com and so would accept the bogus mail and attempt to deliver it locally. If the bogus name were designed to discredit you, it could be set to sex.bogus.site.com for example, and mail to root@sex. would be delivered to you without your knowing the reason.
Convert BITNET addresses into Internet addresses
(V8.1 and above)Many Internet hosts have BITNET addresses that are separate from their Internet addresses. For example, the host icsi.berkeley.edu has the registered BITNET name ucbicsi. If a user tried to reply to an address such as:
[email protected]that mail would fail. To help with translations from registered BITNET names to Internet addresses, John Gardiner Myers has supplied the
bitdomain
program in the contrib subdirectory. It produces output in the formucbicsi icsi.berkeley.eduthat can be put into database form for use with the
K
configuration command. Thebitdomain
feature causes rules to be included in the configuration file that perform the necessary translation:R$* < @ $+ .BITNET > $* $: $1 < @ $(bitdomain $2 $: $2.BITNET $) > $3Note that this rule requires BITNET addresses to be so identified with a
.BITNET
suffix. If the address, without the suffix, is found in thebitdomain
database, the Internet equivalent address is used in its place. (See also the UUCPSMTP m4 macro and thedomaintable
feature.The form of the
bitdomain
feature isFEATURE(`bitdomain')This declaration causes the following
K
configuration command to be included in addition to the above rule:Kbitdomain hash -o /etc/bitdomain.dbThe
bitdomain
feature is one of those that can take an argument to specify a different form of or name for the database:FEATURE(`bitdomain',`dbm -o /etc/bitdomain')The extra argument causes the above
K
command to be replaced with the following one:Kbitdomain dbm -o /etc/bitdomainThe
bitdomain
feature is safe. You can routinely include it in all configuration files. The database lookup is performed only if the.BITNET
suffix is present and the database file exists.Note that you must also define BITNET_RELAY (see Section 31.10.5) if you want
.BITNET
suffixed mail that is not found in the database to be routed to a relay machine. If BITNET_RELAY is not defined,.BITNET
suffixed mail that is not found in the database is bounced.
Accept old as equivalent to new domain
(V8.2 and above)Some sites need to use multiple domain names when transitioning from an old domain to a new one. The domaintable feature enables such transitions to operate smoothly by rewriting the old domain to the new. To begin, create a file of the form:
other.domain local.host.domainIn it the left side of each line has one of possibly many fully qualified hostnames, and the right side has one of your local hostnames. The makemap(1) program (see Section 33.2, "Create Files with makemap") is then used to convert that file into a database.
The
domaintable
feature causes a rule like this to be included in your configuration file:R$* < @ $+ > $* $: $1 < @ $(domaintable $2 $) > $3Here, each host part of an address in rule set 3 is looked up in the
domaintable
map. If it is found, the local name from that map replaces it, and the address is treated as local.The
domaintable
feature enables this lookup by including aK
configuration command:Kdomaintable hash -o /etc/domaintableThe form of domaintable feature is
FEATURE(`domaintable')The
domaintable
feature is one of those that can take an argument to specify a different form of or different name for the database:FEATURE(`domaintable',`dbm -o /etc/domaintable')The extra argument causes the above
K
command to be replaced with the following one:Kdomaintable dbm -o /etc/domaintableThe
domaintable
feature is safe. You can routinely include it in all configuration files. The database lookup is performed only if the database file exists. (See Section 33.3.4.8, "-o the database file is optional (V8.1 and above)" for a description of theK
command's-o
switch.)Although this feature might appear suitable for a service provider that wishes to accept mail for client domains, it really is not. Such a service provider should use the
virtusertable
feature instead.
Transform sender addresses
(V8.8 and above)The User Database (see Section 33.5, "The User Database") allows recipient addresses to be changed so that they can be delivered to new hosts. For example, [email protected] can be transformed with the User Database into [email protected]. The
genericstable
provides the same type of transformation on the sender's address.To begin, create a file of the form
user [email protected]In it, each line begins with the user part of an address. On the right is the new address for that sender. One example of a use for this table might be to make the user news always appear as though it was from the news machine:
news [email protected]The makemap(1) program (see Section 33.2) is then used to convert this file into a database:
makemap hashfile
The
genericstable
feature causes a rule like this to be included in your configuration file:R$+ < @ $=G . > $: < $(generics $1 $: @ $) > $1 < @ $2 . >Here, in rule set 93, any address whose host part is in the class
$=G
has the user part looked up in thegenericstable
database. If it is found, it is rewritten to be the address from the right-hand side of the original file. Note that local and non-local hosts can appear in$=G
for use with this feature. Also note that the members of$=w
are not automatically placed in$=G
.The
feature enables this lookup by including a
genericstable
K
configuration command:Kgenericstable hash -o /etc/genericstableThe form of
genericstable
feature's declaration isFEATURE(`genericstable')The
genericstable
feature is one of those that can take an argument to specify a different form of or a different name for the database:FEATURE(`genericstable',`dbm -o /etc/genericstable')The extra argument causes the above
K
command to be replaced with the following one:Kgenericstable dbm -o /etc/genericstableSee Section 33.3.4.8 for a description of the
K
command-o
switch.The
genericstable
should be enabled only if you intend to use it. It causes every sender to be looked up in that database.
Only masquerade $=M hosts
(V8.8 and above)Ordinarily, addresses can be masqueraded if they are unqualified (lack a domain part) or if they match any hostname in
$=w
. Masquerading replaces the hostname part of an address with the fully qualified hostname defined by MASQUERADE_AS.Some sites handle mail for multiple domains. For these sites it is important to recognize all incoming mail as local via
$=w
. On the other hand, only a subset of the hosts in$=w
should be masqueraded. Consider, for example, the host our.domain that receives mail for the domains his.domain and her.domain:Cw our.domain his.domain her.domainIn this scenario we want all but her.domain to be masqueraded as our.domain. The way to create such exceptions is with the
limited_masquerade
feature.The
limited_masquerade
feature causes masquerading to be based on$=M
instead of$=w
. You uselimited_masquerade
like this:define(`MASQUERADE_AS', `our.domain
') FEATURE(`limited_masquerade') LOCAL_CONFIG Cw our.domain his.domain her.domain MASQUERADE_DOMAIN(our.domain his.domain)MASQUERADE_AS needs to be declared first. Then the
limited_masquerade
feature is declared. Finally, the LOCAL_CONFIG allows two classes to be declared. The first is the normal$=w
. The second uses MASQUERADE_DOMAIN to indirectly declare$=M
and puts a subset of the$=w
hosts in it. Specifically, the second class omits the her.domain.The
limited_masquerade
feature causes sendmail to masquerade the hosts in$=M
, instead of the normal masquerading of$=w
. Note that$=M
is also used to list the domains for themasquerade_entire_domain
feature.
Use procmail(1) as local delivery agent
(V8.7 and above)The procmail (1) program can handle a user's mail autonomously (for example, sorting incoming mail into folders based on subject) and can function as a sendmail delivery agent. Some administrators prefer procmail(1) in this latter role over normal UNIX delivery agents. If this is your preference, you can easily use procmail(1) in that role with the local_procmail feature:
FEATURE(`local_procmail')The local_procmail feature changes the
P=
,F=
, andA=
equates for thelocal
delivery agent intoP=/usr/local/bin/procmail see Section 30.4.9, P= F=SPfhn see Section 30.4.5, F= A=procmail -Y -a $h -d $u see Section 30.4.1, A=If you have installed procmail in a different location, you can specify that alternative location with a second argument:
FEATURE(`local_procmail', `/admin/mail/bin/procmail')If you need to use different
F=
flags than those shown, you may declare new flags with LOCAL_MAILER_FLAGS (see Section 30.4.5.1, "m4 modification of F="). If you need to specify different command line arguments, you may do so with LOCAL_MAILER_ARGS (see Section 30.4.1.1, "m4 A= definitions"). Both must appear before the feature.
Database selects new delivery agents
(V8.1 and above)A mailertable is a database that maps host.domain names to special delivery agent and new domain name pairs. Essentially, it provides a database hook into rule set 0. The new domain names are used for routing but are not reflected in the headers of messages. For example, one mapping in a source text file could be:
compuserv.com smtp:compuserve.comThe key portion (on the left) must be either a fully qualified host and domain name, such as lady.bcx.com, or a partial domain specification with a leading dot, such as .bcx.com. On the right the delivery agent name must be separated from the new domain name by a colon. The source text file is converted into a database with the makemap(1) program (see Section 33.2). Beginning with V8.8 sendmail, the host part can also specify a user:
downhost.com smtp:postmaster
@mailhub.our.domainThe mailertable feature causes rules to be included in your configuration file that look up host.domain names (on the left in the source file) in the mailertable database:
R< $+ > $* $: < $(mailertable $1 $) > $2 lookup R< error : $- $+ > $* $#error $@ $1 $: $2 check - error?Here, the host.domain is looked up in the
mailertable
database, and a delivery agent, colon, and domain pair are returned. If the delivery agent (inmailertable
) iserror
, the#error
delivery agent is called. This allows error messages to be put into the database, as, for example,badhost error:nohost mail to badhost is prohibitedThe first token following the
error:
is passed in the$@
part of the#error
delivery agent. Note that you must use words or <sysexits.h> codes here, not DSN values (such as3.1.0
), because the latter would be wrongly broken up into five tokens. See Section 30.5.2, "The error Delivery Agent" for a full description of the#error
delivery agent and for tables of useful words and codes for the$@
part.If the host is found and it is not an
error
delivery agent, that delivery agent is selected. Otherwise, the unresolved host.domain is passed to rule set 90 for further mailertable lookups. Rule set 90 recursively strips the leftmost part of the host.domain away and looks up the result in themailertable
. This continues until either a match is found or only a dot is left. Then that dot is looked up to give you a hook for failed lookups:. smtp:smarthostAs a special case, the delivery agent named
local
causes slightly different behavior in that it allows the name of the target user to be listed without a host part:virtual.domain local:bobHere, any mail that is received for the virtual.domain is delivered to the user bob on the local machine. If the user part is missing,
virtual.domain local:the mail is delivered to the user part of the original address.
The form for the mailertable feature is:
FEATURE(`mailertable')This causes the following database declaration in the configuration file:
Kmailertable hash -o /etc/mailertable.dbIf you wish to use a different form of database (such as dbm), the mailertable feature accepts an argument:
FEATURE(`mailertable',`dbm -o /etc/mailertable')The mailertable feature was inspired by the IDA version of sendmail.
Masquerade all hosts under a domain
(V8.8 and above)Ordinarily, masquerading transforms any host from a list of hosts in the class
$=w
(see Section 32.5.8) into the host defined by MASQUERADE_AS. If domains are also masqueraded with MASQUERADE_DOMAIN, they too are transformed. For example, consider these declarations:MASQUERADE_AS(`our.domain') MASQUERADE_DOMAIN(`her.domain')The first line causes any host part of an address contained in the class
$=w
to be transformed into our.domain. The second line transforms any domain part of her.domain into our.domain.The key point here is that the domain part her.domain will be transformed, whereas hosts under that domain will not be transformed:
[email protected] becomes [email protected] [email protected] remains [email protected]If you wish MASQUERADE_DOMAIN to transform all the hosts under the declared domain, you may use the
masquerade_entire_domain
feature:MASQUERADE_AS(`our.domain') MASQUERADE_DOMAIN(`her.domain') FEATURE(`masquerade_entire_domain')This feature extends masquerading of her.domain to include all the hosts under that domain:
[email protected] becomes [email protected] [email protected] becomes [email protected] [email protected] becomes [email protected]Note that you may masquerade only domains that are under your direct jurisdiction and control. Also note that domain masquerading is intended for actual domains. Virtual (fictional) domains are better handled with the
virtusertable
feature (see Section 19.6.28). But note that thevirtusertable
feature handles only incoming mail.
Masquerade the envelope too
(V8.7 and above)Ordinarily, masquerading (see Section 19.4.4, "Masquerading") affects only the headers of email messages, but sometimes it is also desirable to masquerade the envelope. [4] For example, error messages are often returned to the envelope-sender address. When many hosts are masquerading as a single host, it is often desirable to have all error messages delivered to that central masquerade host.
[4] See Section 1.7, "The Envelope" for a description of the envelope and how it differs from headers.
The
masquerade_envelope
feature causes masquerading to include envelope addresses:MASQUERADE_AS(`our.domain') masquerade headers FEATURE(`masquerade_envelope') also masquerade the envelopeThese mc lines cause all envelope addresses (where the host part is declared as part of class
$=w
; see Section 32.5.8) to be transformed into our.domain. See MASQUERADE_DOMAIN for a way to also masquerade other domains, and see themasquerade_entire_domain
feature for a way to also masquerade all the hosts under other domains.In general,
masquerade_envelope
is recommended for uniform or small sites. Large or variegated sites may prefer to tailor the envelope on a subdomain-by-subdomain or host-by-host basis.
Don't canonify with $[ and $]
(V8.1 and above)Ordinarily, as part of rule set 3, sendmail tries to canonify (add a domain to) any hostname that lacks a domain part. It does this by passing the unadorned hostname to the
$[
and$]
operators (see Section 28.6.6, "Canonicalize Hostname: $[ and $]"). Thenocanonify
feature prevents sendmail from passing addresses to$[
and$]
for canonicalization. This is generally suitable for use by sites that act only as mail gateways or that have MUAs that do full canonicalization themselves.The form for the
nocanonify
feature is:FEATURE(`nocanonify')You might also want to use:
define(`confBIND_OPTS',`-DNSRCH -DEFNAMES')to turn off the usual resolver options that perform a similar function (see Section 34.8.55, ResolverOptions (I)).
Note that the
nocanonify
feature disables only one possible use of$[
and$]
in the configuration file. If the nouucp feature is omitted (thereby including UUCP support), addresses that end in a.UUCP
suffix still have the preceding part of the address canonified with$[
and$]
even if thenocanonify
feature was declared.Note that sending out any unqualified addresses can pose a risk. Be sure to read Section 16.5, "Qualify All Addresses?" for a discussion of why you might not want to use this feature.
Omit DNS support from configuration file
(V8.6)The V8.6 sendmail configuration files usually assumed that you were using DNS to get host information. If you did not have DNS available (for example, if you were on a remote UUCP node), you could declare that fact:
FEATURE(`nodns')This told sendmail to assume that DNS was not available. It did this by not setting any of the _res.options flag bits. Note that this was really only a suggestion, because other features (such as
bestmx_is_local
temporarily set those flag bits and used DNS anyway.Beginning with V8.7 sendmail, you should either use the service-switch file (see Section 34.8.61, ServiceSwitchFile) to control use of DNS or compile a sendmail without DNS support (see Section 18.8.23, NAMED-BIND).
Note that the result of a hostname lookup failure differs depending on whether or not DNS is used. If a hostname is looked up with DNS and not found, the message will be queued, and the name will be looked up again later. If the host is looked up in /etc/hosts and the lookup fails, the message bounces.
Eliminate all UUCP support
(V8.1 and above)If your site wants nothing to do with UUCP addresses, you can enable the
nouucp
feature. Among the changes this causes that are the!
character is not recognized as a separator between hostnames; and all the macros that relate to UUCP (see Section 19.4.6) are ignored. This feature truly means no UUCP.You declare
nouucp
is like this:FEATURE(`nouucp')Note that all the other UUCP declarations (such as UUCP_RELAY) will be ignored if you use
nouucp
.
Relay all mail through a mail host
(V8.6 and above)Some sites have a number of workstations that never receive mail directly. They are usually clustered around a single mail server. Normally, all clients in a cluster like this send their mail as though the mail is from the server, and they relay all mail through that server rather than sending directly. If you have such a configuration, use
FEATURE(`nullclient', `server')See Chapter 16, The null.mc File and m4, for a lesson in how to use this feature. Also see the
nocanonify
feature, which can also be used withnullclient
.If you wish to prevent the nullclient version of sendmail from trying to access aliases, add this line to your
.mc
file:undefine(`ALIAS_FILE')Note that this works only with V8.8 and above
.mc
files.
Add support for address.REDIRECT
(V8.1 and above)The
redirect
feature allows aliases to be set up for retired accounts. Those aliases bounce with an indication of the new forwarding address. A couple of lines from such an aliases(5) file might look like this:george: [email protected] william: [email protected]The
redirect
feature causes mail addressed togeorge
, for example, to be bounced with a message like this:551 User not local; please try <[email protected]>Note that the message is bounced and not forwarded. No notification is sent to the recipient's new address.
The form of the
redirect
feature isFEATURE(`redirect')This feature adds the pseudo-domain .REDIRECT to class
$=P
, which prevents that suffix from being looked up with DNS. It then adds rules to rule set 0 that handle this suffix only if the{opMode}
macro (see Section 31.10.28, ${opMode}) has any value other thani
(for initialize aliases as set by the-bi
command line switch, see Section 36.1.3, "newaliases"). The actual bounce is caused by calling theerror
delivery agent with a RHS like this:$# error $@ 5.1.1 $: "551 User not local; please try " <$1@$2>The
5.1.1
is a DSN error code (see RFC1893), and the551
is an SMTP code (see RFC821).To illustrate why the message is bounced rather than forwarded, consider a fictional MTA that is clever about getting this message:
551 User not local; please try <[email protected]>Instead of bouncing the outgoing message, the fictional MTA tries to be clever and to deliver to new.site.edu. If new.site.edu also responds with a REDIRECT message, the MTA tries the next host in line. This is a bad idea for two reasons: First, elaborate loop detection would need to be designed to catch infinite REDIRECT loops, and second, a down host anywhere in the sequence would necessitate that the series of connections be made over and over again until they all succeeded.
Use smrsh (sendmail restricted shell)
(V8.7 and above)Although sendmail tries to be very safe about how it runs programs from the aliases(5) and ~/.forward files (see Section 24.2.3, "Delivery via Programs"), it still may be vulnerable to some internal attacks. To limit the selection of programs that sendmail is allowed to run, V8 sendmail now includes source and documentation for the smrsh (sendmail restricted shell) program. See Section 22.8.2, "The smrsh Program" for a full description of the smrsh program.
After you have compiled, installed, and configured smrsh, you can include support for it in your configuration file with the
smrsh
feature:FEATURE(`smrsh') MAILER(`local')Note that the
smrsh
feature must precede thelocal
delivery agent declaration. If these lines are reversed, the following error will print when you run m4:*** FEATURE(smrsh) must occur before MAILER(local)The default location for the smrsh program is /usr/local/etc/smrsh. If you installed smrsh in another location, you will need to add an argument to the
smrsh
feature:FEATURE(`smrsh', `/usr/bin/smrsh\')Use of smrsh is recommended by CERT, so you are encouraged to use this feature as often as possible.
Don't differ user from [email protected]
(V8.1 through V8.6)Mail addressed to a local user that includes the name of the local host as part of the address (i.e., local.host) is delivered locally. From V8.1 to V8.6 sendmail, if the address has a host part, lookups in the User Database (see Section 33.5) and the additional processing of rule set 5 (see Section 29.7, "Rule Set 5") are skipped. Under V8.6, addresses with just the
user
part are always processed by the User Database and rule set 5.The V8.6
notsticky
feature changes this logic. If this feature is chosen, all users are looked up in the User Database, and the additional processing done by rule set 5 is skipped.Beginning with V8.7, the default is now as if
notsticky
were used, and thestickyhost
feature is used to restore the previous default.
Differ user from [email protected]
(V8.7 and above)Beginning with V8.7 sendmail, addresses with and without a host part that resolve to local delivery are handled in the same way. For example, user and [email protected] are both looked up with the User Database (see Section 33.5) and processed by rule set 5 (see Section 29.7). This processing can result in those addresses being forwarded to other machines.
With the
stickyhost
feature, you may change this behavior:FEATURE(`stickyhost')By defining
stickyhost
, you are telling sendmail to mark addresses that have a local host part as "sticky":user not sticky [email protected] stickySticky hosts tend to be delivered on the local machine. That is, they are not looked up with the User Database and are not processed by rule set 5.
One use for this feature is to create a domainwide name space. In it, all addresses without a host part will be forwarded to a central mail server. Those with a local host part will remain on the local machine and be delivered in the usual local way.
Note that this is opposite the behavior of the former
notsticky
feature of V8.6.
Use /etc/sendmail.ct for a list of trusted users
(V8.7 and above)V6 sendmail removed the concept of trusted users (see Section 22.8, "Security Features"). V8.7 reintroduced trusted users, but in a different form from that used by V5 sendmail. Now, trusted users are those who may run sendmail with the
-f
switch (see Section 36.7.21, -f and -r) without generating an authentication warning (see Section 35.10.35, X-Authentication-Warning:):X-Authentication-Warning:host
:user
set sender toother
using -fTo prevent this warning, the
user
should be added to the class$=t
(see Section 32.5.7, $=t). There are three ways to do this. You may use theT
configuration command:Tuser
Or you may use the class command:
Ctuser
Or you may use the
use_ct_file
and adduser
to the /etc/sendmail.ct file. To use this latter approach, declare the following in your mc file:FEATURE(`use_ct_file')If you want to locate the /etc/sendmail.ct in a different place or give it a different name, you may do so with this declaration:
define(`confCT_FILE', `/etc/mail/trusted.list')Note that the file must exist before sendmail is started, or it will complain:
fileclass: cannot open /etc/mail/trusted.list: No such file or directoryIf you want the file to optionally exist, you may add a
-o
(see Section 32.1.2) to the conf-CT_FILE definition:define(`confCT_FILE', `-o /etc/sendmail.ct')Here, we don't rename the file: we make the default file's presence optional.
Use /etc/sendmail.cw for local hostnames
(V8.1 and above)The
use_cw_file
feature causes the file /etc/sendmail.cw to be read to obtain alternative names for the local host. One use for such a file might be to declare a list of hosts for which the local host is acting as the MX recipient. Theuse_cw_file
is used like this:FEATURE(`use_cw_file')This feature causes the following
F
configuration command (see Section 32.1.2) to appear in the configuration file:Fw/etc/sendmail.cwThe actual filename can be changed from /etc/sendmail.cw (the default) by defining the
confCW_FILE
macro:define(`confCW_FILE', `-o /etc/mail/sendmail.cw')Here, we both rename the file and make its presence optional by adding the
-o
switch (see Section 32.1.2).If the local host is known by only a few names, an alternative is to instead include the following
C
configuration command (see Section 32.1.1, "The C Class Command") in place of the above feature:Cwname1 name2
Here,
name1
andname2
are alternative names for the local host.
Convert UUCP hosts via a database
(V8.1 and above)The uucpdomain feature is similar to bitdomain but is used to translate addresses of the form
[email protected]into the
!
path form or routing used by UUCP. The database for this would contain, for example, key and data pairs like this:host a!b!c!hostThis source text file is converted into a database with the makemap(1) program (see Section 33.2). But note that no software is supplied to transform the UIUC pathalias(1) program's output into a form that is suitable for this database.
The way you declare
uucpdomain
is like this:FEATURE(`uucpdomain')This causes a rule like this to be added to rule set 3:
R$* < @ $+ .UUCP > $* $: $1 < @ $(uudomain $2 $: $2.UUCP $) > $3Here, the host in the pseudo-domain .UUCP is looked up in the database
uudomain
. Theuucpdomain
feature also creates the declaration for that database:Kuudomain hash -o /etc/uudomainIf you wish to use a different form of database or a different location for the database file, you may do so by adding an argument to the feature declaration:
FEATURE(`uucpdomain', `dbm -o /etc/mail/uudomain')Here, we tell sendmail that we will be using the NDBM form of database instead of the original NEWDB form (see Section 33.1, "Enable at Compile Time"). We also relocated the file into the /etc/mail directory.
Support for virtual domains
(V8.8 and above)A
virtusertable
is a database that maps virtual (possibly nonexistent) domains into new addresses. Essentially, it gives you a database hook into the early part of rule set 0. Note that this only reroutes delivery. It does not change mail headers.By way of example, consider one mapping in a source text file:
[email protected] bob [email protected] [email protected] @fictional.com [email protected]The key portion (on the left) must be either a full address (user, host, and domain name), as in the first two lines, or an address with the user part missing, as in the last line. This source text file is converted into a database with the makemap(1) program (see Section 33.2).
The first two lines illustrate a full address for the key. The first line will be delivered to a local user (bob) the second to a remote user ([email protected]). The third line file shows how all mail to a virtual domain (fictional.com) can be delivered to a single address, no matter what the user part is.
Note that sendmail does a single lookup, so one line may not reference another. The following won't work:
[email protected] [email protected] @fictional.com [email protected]Here, mail to [email protected] will be delivered to [email protected], not to [email protected].
Also note that virtual domains in the key (such as
@fictional.com
) must be added to classw
in order for them to be recognized as local.You declare the
virtusertable
like this in your mc file:FEATURE(`virtusertable')This causes the following database declaration to appear in the configuration file:
Kvirtusertable hash -o /etc/virtusertableIf you wish to use a different form of database (such as dbm) or a different location, the
virtusertable
feature accepts an argument:FEATURE(`virtusertable',`dbm -o /etc/mail/virtusertable')If the value (the right-hand side in
virtusertable
) iserror:
, the#error
delivery agent is called. This allows error messages to be put into the database, as, for example,[email protected] error:nouser We no longer sell things hereThe text following the
error:
is passed to the#error
delivery agent like this:Rerror : $- $+ $#error $@ $1 $: $2Thus the first token following the
error:
is passed in the$@
part. Note that you must use words here, not DSN values (such as3.1.0
), because the latter would be wrongly broken up into five tokens. See Section 30.5.2 for a full description of the#error
delivery agent and for tables of useful words for the$@
part.
Temporary customizations
(V8.1 and above)Some things just can't be called features. To make this clear, they go in the _CF_DIR_/hack directory (see Section 19.2.1, "Maintain local files with _CF_DIR_") and are referenced using the HACK macro. They tend to be site-dependent.
HACK(cssubdomain)This illustrates use of the Berkeley-dependent
cssubdomain
hack (that makes sendmail accept local names in either Berkeley.EDU or CS.Berkeley.EDU).Another way to think of a hack is as a transient feature. Create and use HACK as a temporary solution to a temporary problem. If a solution becomes permanent, move it to the FEATURE directory (see Section 19.3.4) and reference it there.
Add general information and rules
(V8.1 and above)The LOCAL_CONFIG macro allows custom configuration lines to be inserted by using the mc file. The inserted lines are carried literally into the output and appear in the resulting configuration file just before the rules.
LOCAL_CONFIG FE/usr/local/mail/visible.users Khostmap hash /etc/hostmap.dbIn this example the class
$=E
has additional names read from the file visible.users, and the hostmap database is declared.New rule sets can be inserted with LOCAL_CONFIG. For V8.7 and above we recommend using symbolic names to avoid collision with rule set numbers used by sendmail:
LOCAL_CONFIG Sfoo custom rules hereSee the discussion of diversions (see Section 19.1.4, "m4 diversions") to cause LOCAL_CONFIG lines to output in a predetermined order.
Relay for unqualified user (deprecated)
(V8.1 and above)Unless you specify otherwise, any address that is a username without any @host part is delivered using the
local
delivery agent. If you prefer to have all such mail handled by a different machine, you may define that other machine with the LOCAL_RELAY m4 macro.Note that a relay is different from the knowledgeable hub defined with MAIL_HUB. (See later in this section for an illustration of how MAIL_HUB and LOCAL_RELAY interact.)
This macro is deprecated because it doesn't work well with some MUAs (for example, mh(1)). This is because some MUAs put a host part on all addresses even if only the user part was specified.
Add rules to rule set 0
(V8.6 and above)In rule set 0, after the
local
delivery agent has been selected and before theuucp
,smtp
, and the like have been selected, you can insert custom delivery agents of your own. To do this, use the LOCAL_RULE_0 macro:LOCAL_RULE_0 # We service lady via an mx record. R$+ < @ lady.Berkeley.EDU. > $#uucp $@ lady $: $1Here, we introduce a new rule to select a delivery agent. The host lady is a UUCP host for which we accept mail via an MX record.
Note that LOCAL_RULE_0 fits into flow of rules through rule set 0 like this:
1. Basic canonicalization (list syntax, delete local host, etc.)
2. LOCAL_RULE_0
3. UUCP, BITNET_RELAY (see Section 31.10.5), etc.
4. LOCAL_NET_CONFIG (see Section 19.6.37)
5. SMART_HOST (see Section 19.6.47)
6. SMTP, local, etc. delivery agents
Add rules to rule set 1
(V8.6 and above)See LOCAL-RULE-2.
Add rules to rule set 2
(V8.6 and above)Rule sets 1 and 2 are normally empty and not included in the configuration file created from your mc file. Rule set 1 processes all sender addresses (see Section 29.9, "Rule Set 1"), and rule set 2 processes all recipient addresses (see Section 29.8, "Rule Set 2"). These m4 macros are used just like LOCAL_RULE_0, above but they introduce rules that would otherwise be omitted, rather than adding rules to an existing rule set.
Add rules to rule set 3
(V8.6 and above)All addresses are first rewritten by rule set 3 (see Section 29.4, "Rule Set 3"). For complex configuration needs, you can define special rules and cause them to be added to rule set 3. New rules are added to the end of rule set 3 by way of rule set 6. That is, each final decision in rule set 3 (denoted by a
$@
in the RHS) calls rule set 96 (with$>96
) before returning.The m4 macro LOCAL_RULE_3 is used to introduce new rules that can be used in canonicalizing the hostnames. Note that any modifications made here are reflected in the header.
One suggested use for LOCAL_RULE_3 is to convert old UUCP hostnames into domain addresses using the m4 UUCPSMTP macro. For example,
LOCAL_RULE_3 UUCPSMTP(decvax, decvax.dec.com) UUCPSMTP(research, research.att.com)This causes the following address transformations:
decvax!user becomes [email protected] research!user becomes [email protected]Another suggested use for LOCAL_RULE_3 is to introduce a new rule to look up hostnames in a locally customized database:
LOCAL_RULE_3 R$*<@$+>$* $:$1<@ $(hostmap $2 $) >$3The declaration and definition of local database maps with the
K
configuration command (see Section 33.3, "The K Configuration Command") should appear in the LOCAL_CONFIG section.
Group local rules with others
(V8.8 and above)Prior to V8.8 sendmail, you had to use the
divert9
m4 directive to force your new rule set declarations to be emitted alongside the normal m4-generated rules sets. Beginning with V8.8, that bit of "black magic" has been removed.The LOCAL_RULESETS m4 command causes all the rule sets and rules that follow it to be emitted into your configuration file along with all the rules that are automatically generated. You use it like this:
LOCAL_RULESETS your new rule sets and rules here
Add rules for SMART-HOST
(V8.6 and above)One possible setup for mail is to allow hosts on the local network to deliver directly to each other but for all other mail to be sent to a "smart host" that forwards it offsite. Commonly, such arrangements are used by sites with inhouse networks that have access to the outside world only through a UUCP link. For such sites you can use LOCAL_NET_CONFIG:
define(`SMART_HOST', `uucp-new:uunet') LOCAL_NET_CONFIG R$* < @ $* .$m. > $* $#smtp $@ $2.$m $: $1 < @ $2.$m > $3Here, SMART_HOST is first defined as
uucp-new:uunet
(send to the host uunet with theuucp-new
delivery agent). The LOCAL_NET_CONFIG then introduces a rule that causes all names that end in your domain name ($m
) to be delivered via thesmtp
delivery agent. Any other addresses fall through to be handled by the SMART_HOST rules.SMART_HOST can be a network-connected gateway too. Just use
smtp
in place ofuucp-new
in the SMART_HOST definition, and the name of the gateway.Note that LOCAL_NET_CONFIG fits into the flow of rules through rule set 0 like this:
1. Basic canonicalization (list syntax, delete local host, etc.)
2. LOCAL_RULE_0 (see Section 19.6.32)
3. FEATURE(mailertable) (see Section 19.6.14)
4. UUCP, BITNET_RELAY (see Section 31.10.5), etc.
5. LOCAL_NET_CONFIG (see Section 19.6.37)
6. SMART_HOST (see Section 19.6.47)
7. SMTP, local, etc. delivery agents
Users that must be delivered locally
(V8.1 and above)Some unqualified (without an @host part) usernames need to be delivered on the local machine even if LOCAL_RELAY is defined. The user root is one such example. By remaining local, aliasing is allowed to take place.
The LOCAL_USER m4 macro is used to add additional usernames to the list of local users. Note that root is always a member of that list.
LOCAL_USER(operator
)This causes the name
operator
to be appended to the list of local users. That list is stored in the class$=L
. The disposition of local usernames that include the name of the local host is determined by thestickyhost
feature.
Relay for local looking usernames
(V8.7 and above)The host that handles usernames that appear to be local even though they are not. See Section 31.10.23 for a discussion of this relay.
Define custom delivery agents
(V8.8 and above)Prior to V8.8 sendmail you had to use a
divert(7)
statement to force your new delivery agent definitions to be grouped with all the other delivery agent definitions. Beginning with V8.8, this bit of "black magic" has been removed.To force your new delivery agent definitions to be grouped with the others delivery agent definitions, use the MAILER_DEFINITIONS m4 command:
MAILER_DEFINITIONS your new delivery agent definitions hereSee Section 30.3.1, "Tuning Without an Appropriate Keyword" for an example of this m4 command.
All local delivery on a local server
(V8.1 and above)One scheme for handling mail is to maintain one mail spool directory centrally and to mount that directory remotely on all clients. To avoid file locking problems, delivery to such a spool should be performed only on the central server. The MAIL_HUB macro allows you to specify that all local mail be forwarded to the central server for delivery. The point is to let unqualified names be forwarded through a machine with a large aliases file.
If you define both LOCAL_RELAY and MAIL_HUB, unqualified names and names in class
L
are sent to the LOCAL_RELAY and other local names are sent to MAIL_HUB. To illustrate, consider the result of various combinations for the user you on the machine here.our.site.If LOCAL_RELAY is defined as relay.our.site and MAIL_HUB is not defined, mail addressed to you are forwarded to relay.our.site, but mail addressed to [email protected] is delivered locally.
If MAIL_HUB is defined as hub.our.site and LOCAL_RELAY is not defined, mail addressed to you and mail addressed to [email protected] is forwarded to hub.our.site for delivery.
If both LOCAL_RELAY and MAIL_HUB are defined as above, mail addressed to you is sent to relay.our.site for delivery, and mail addressed to [email protected] is forwarded to hub.our.site.
If you want all outgoing mail to go to a central machine, use SMART_HOST too.
Note that LOCAL_RELAY and MAIL_HUB act identically (except that MAIL_HUB takes precedence) unless the
stickyhost
feature is used. Also note that thenullclient
feature can be used if you want all mail to be forwarded to a central machine.
Masquerade as the server
(V8.1 and above)At sites with one central mail server (see MAIL_HUB, it can be advantageous for mail from the clients to appear as though it is from the hub. This simplifies mail administration in that all users have the same machine address no matter which workstations they use. You can cause a workstation to masquerade as the server (or as another host) by using the MASQUERADE_AS m4 macro:
MASQUERADE_AS(server)This causes outgoing mail to be labeled as coming from the server (rather than from the value in
$j
see Section 31.10.20). The new label is in all but theReceived:
(see Section 35.10.25, Received:) andMessage-ID:
(see Section 35.10.19, Message-ID:) headers.Some users (such as root) should never be masqueraded because one always needs to know their machine of origin. Such users are declared by using the EXPOSED_USER m4 macro. Note that root is always exposed.
If you wish to have recipient addresses also masqueraded, cautiously use the allmasquerade feature.
Masquerade other domains
(V8.6 and above)Ordinarily, MASQUERADE_AS enables only hosts in the local domain, to be transformed into the masquerading host. If you wish to masquerade a domain other than your local one, you can use the MASQUERADE_DOMAIN macro:
MASQUERADE_DOMAIN(`other.domain
')Essentially, all that MASQUERADE_DOMAIN does is to assign its argument to the class
$=M
, so you can list multiple domains in a single MASQUERADE_DOMAIN statement:MASQUERADE_DOMAIN(`domain1 domain2 domain3
') CM domain1 domain2 domain3 the sameNote that MASQUERADE_DOMAIN masquerades only the domain and not any hosts under that domain. If you wish to masquerade all hosts under a domain (including the domain itself), see the
masquerade_entire_domain
feature.
Masquerade other domains
(V8.6 and above)In masquerading other domains, as with MASQUERADE_DOMAIN above, it may prove advantageous to store the list of masqueraded domains in an external file. The MASQUERADE_DOMAIN_FILE macro allows you to do just that:
MASQUERADE_DOMAIN_FILE(`/etc/mail/domains')Essentially, all that MASQUERADE_DOMAIN_FILE does is to assign its argument to the class
$=M
via anF
configuration command:MASQUERADE_DOMAIN_FILE(`-o /etc/mail/domains') FM -o /etc/mail/domains the sameHere, we added a
-o
to make the existence of the file optional.
Declare sites for SITECONFIG (obsolete)
(V8.1 and above)Local UUCP connections (obsolete)
(V8.1 and above)The SITECONFIG m4 macro (now obsolete but retained for backward compatibility) is useful for maintaining lists of UUCP connections. There are two types of connections: those connected to the local host and those connected to another host. The first type is declared with SITECONFIG like this:
SITECONFIG(`file
',`host
',`class
')Here,
file
is the name of a file (without the .m4 suffix) that is in the directory _CF_DIR_/cf/siteconfig. That file contains a list of SITE declarations (described soon). The host is the UUCP node name of the local host. The class is the name (one letter) of a class that holds the list of UUCP connections. For example,SITECONFIG(`uucp.arpa',`arpa',`U')Here, the file _CF_DIR_/cf/siteconfig/uucp.arpa.m4 contains a list of UUCP hosts directly connected to the machine arpa. This declaration would be used only in the machine arpa's mc file. The list of UUCP hosts is added to the class macro
$=U
. The letters available for local connections areU
(foruucp-old
),Y
(foruucp-new
), andZ
(foruucp-uudom
).A second form of the SITECONFIG m4 macro is the one used by hosts other than the one with the direct UUCP connections. It is just like the above one but with the full canonical name of the host:
SITECONFIG(`uucp.arpa',`arpa.Berkeley.EDU',`W')This also reads the file uucp.arpa.m4 but instead of causing UUCP connections to be made locally, it forwards them to the host arpa.Berkeley.EDU.
The hostname that is the second argument is assigned to the
$W
macro. The class$=W
is set aside to hold lists of hosts that appear locally connected. This class is also used with the SITE macro. The letters that are available for remote sites areV
,W
, andX
.If nothing is specified, the class becomes
Y
. If classU
is specified in the third parameter, the second parameter is assumed to be the UUCP name of the local site, rather than the name of a remote site. In this latter case, the specified local name has a .UUCP appended, and the result is added to class$=w
.Note that SITECONFIG won't work if you disable UUCP with the nouucp feature.
The ultimate relay
(V8.1 and above)Some sites can deliver local mail to the local network but cannot look up hosts on the Internet with DNS. Usually, such sites are connected to the outside world with UUCP. To ensure delivery of all mail, such sites need to forward all nonlocal mail over the UUCP link to a smart (or well-connected) host.
You can enable this behavior by defining SMART_HOST:
define(`SMART_HOST\', uucp-dom:supporthost)Here, Internet mail will be forwarded to the host supporthost using the
uucp-dom
delivery agent. For information about other ways to use SMART_HOST, see the file cf/README. Note that the value in SMART_HOST is assigned to$S
(see Section 31.10.34, $S) for later use in rules.
The UUCP relay
(V8.1 and above)If your site handles UUCP traffic, it can be in one of two forms. Either a given host has direct UUCP connections or it does not. If it does not, then you may wish to have all UUCP mail forwarded to a host that can handle UUCP. This is done by defining a UUCP_RELAY, which is done just as you would define any other relay (as described in Section 19.4.5).
If your machine or site does not support UUCP, consider disabling all UUCP with the
nouucp
feature.If your machine has directly connected UUCP hosts, you might wish to use one of or more of the UUCP techniques. But before doing so, be sure to declare the
uucp
delivery agent (see Section 19.3.2).
Individual UUCP to network translations
(V8.1 and above)If your site has hosts that used to be UUCP sites but are now on the network, you may intercept and rewrite the old address into the new network address. For example, mail to the machine wash used to be addressed as wash!user. Now, however, wash is on the network, and the mail should be addressed as [email protected].
The UUCPSMTP m4 macro provides the means to specify a UUCP to network translation for specific hosts. The above example would be declared like this:
UUCPSMTP(`wash',`wash.dc.gov')The UUCPSMTP m4 macro should be used only under LOCAL_RULE_3.
Version of the mc file
(V8.1 and above)The VERSIONID m4 macro is used to insert an identifier into each .mc and .m4 file that becomes a part of your final .cf file. Each of the files that is supplied with sendmail already has such an identifier. You should include a similar identifier in each of your .mc files. .ds dollar $
VERSIONID(`\*[dollar]Revision\*[dollar]')Here, the VERSIONID macro is being used to insert an RCS-style revision number. The \*[dollar]Revision\*[dollar] becomes an actual version number when the file is checked in with ci(1). Arbitrary text may appear between the single quotes. You may use RCS, SCCS, or any other kind of revision identification system. The text may not contain a newline because the text appears in the .cf file as a comment:
##### \*[dollar]Revision: 1.5\*[dollar] #####Use of VERSIONID and revision control in general is recommended.