9.4 Configuring the Transport Agent

Setting up the transport agent is perhaps the most crucial mail-related job presented to the system administrator. There are a variety of transport agents available on Unix systems, but sendmail is by far the most widely used. According to current estimates, sendmail handles over 75% of all Internet mail traffic (Unix and non-Unix alike). Other transport agents used on Unix systems include Postfix, smail, qmail, and exim. We will consider sendmail and Postfix here.

9.4.1 sendmail

Eric Allman's sendmail package is a very powerful facility, capable of handling email from the moment a user submits a message from a mailer program, transporting it across a LAN or the Internet to the proper destination system, and then finally handing it off to the delivery agent, which actually places the message in the user's mailbox. In fact, because the package includes a delivery agent program, the facility as a whole can handle every aspect of electronic mail except composing and reading messages and retrieving them from message stores. sendmail is also a well-proven facility, and, at this point, is quite secure, provided that it is configured properly.

There are commercial and free versions of sendmail. The commercial versions, developed and sold by Sendmail, Inc., include additional features as well as easy-to-use graphical interfaces, integration with other related commercial products (e.g., virus-scanning software), and technical support. Vendor-supplied versions of sendmail are created from the free package.

sendmail is available from http://www.sendmail.org; see also http://www.sendmail.net, which is Sendmail, Inc.'s site for the free version. For information about commercial sendmail products, see http://www.sendmail.com.

The current sendmail version series is 8.12.3 (circa April, 2002). sendmail's major version number 8 refers to the extensive rewrite of sendmail done in 1993 by its author, Eric Allman. The other numbers are revisions within that series.[8] Unfortunately, vendor-included versions of sendmail tend to lag behind the current version to varying degrees, with free operating systems remaining closest to the current version and commercial operating systems quite a bit further behind. (At the moment, sendmail versions included with commercial operating systems range from 8.8 to 8.10 for the Unix flavors we are considering.)

[8] sendmail Version 9 is in development as of this writing.

You can identify which version of sendmail is running on a system by running the following command:

$ echo | sendmail -bt -d0  Version 8.11.3   Compiled with: LDAPMAP MAP_REGEX LOG MATCHGECOS MIME7TO8 MIME8TO7                NAMED_BIND NETINET NETUNIX NEWDB NIS QUEUE SASL                SCANF SMTP USERDB    ============ SYSTEM IDENTITY (after readcf) ============        (short domain name) $w = poffice    (canonical domain name) $j = poffice.ahania.com           (subdomain name) $m = ahania.com                (node name) $k = poffice.ahania.com  ======================================================== ADDRESS TEST MODE (ruleset 3 NOT automatically invoked)  Enter <ruleset> <address>

This sendmail command runs the facility in its interactive address-testing mode, with some additional debugging output enabled; in this case, the input is taken from standard input, which is null, thereby terminating the session after the initial messages are displayed (/dev/null could also be used as the input source).

The resulting output indicates the sendmail version information and the set of compilation options with which it was built. For example, this version includes support for interfacing with an LDAP database (indicated by the first keyword in the list). The second section of the output displays information about the local system and its DNS domain environment. The final lines pertain to email address translation and can thus be ignored here.

If you want to find out the sendmail version running on a remote system, telnet to port 25 (specified as telnet's second parameter):

$ telnet pauling 25  Trying  Connected to pauling.  Escape character is `^]'.  220 pauling ESMTP Sendmail 8.11.0/8.11.0; Sun, 4 Mar 2001 ... ^] telnet> quit

Taking the last couple of years as the norm, upgrades to sendmail appear very frequently every 2-3 months, barring major bugs or security holes. Ideally, hosts that relay mail into and out of your site should be kept up-to-date with the latest version of sendmail since these are your most vulnerable security points. Other hosts, which usually rely on a central mail server for mail transport, can probably make do with the version that came with the operating system (unless a major security problem is discovered). In any case, check security sites and mailing lists (as well as the sendmail home page) regularly for notices of newly discovered sendmail vulnerabilities and appropriate fixes.

The sendmail facility consists of many components: the sendmail daemon, some related commands and programs, several configuration files and databases, and configuration-file building tools. These files will be located in standard locations only if you install sendmail yourself from source code. Table 9-3 lists sendmail's major components, along with their directory locations for the various Unix operating systems.

Table 9-3. Where to find the components of the sendmail package

sendmail component


sendmail binary





Boot script that starts sendmail













Boot script configuration file (and sendmail-enabling entry)


none used

/etc/defaults/rc.conf, /etc/rc.conf[9] (sendmail_enable="YES") 

[9] Other features can also be specified in these files (e.g., daemon options).

/etc/rc.config.d/mailservsa (export SENDMAIL_SERVER=1) 
/etc/sysconfig/sendmail[10]/etc/rc.config.d/sendmail.rc.configa (SuSE 7) (START_SENDMAIL="yes") 

[10] The /etc/sysconfig/sendmail file does not exist by default and must be created if desired.

/etc/default/sendmaila (DAEMON=yes) 

/etc/rc.config.* (set arguments only)

vacation utility




not provided by standard Red Hat

newaliases and mailq commands








restricted shell (for piping to commands in mail aliases)


not provided





/usr/sbin (Red Hat) /usr/lib/sendmail.d/bin (SuSE) 



not provided


(local delivery agent)


not provided




not provided

/usr/bin (Red Hat) /usr/lib/sendmail.d/bin (SuSE) 



not provided

aliases file










(primary config. file)









Additional config. files







Configuration file build area (i.e., location of Build script)








/usr/share/sendmail-cf/cf (Red Hat)[11]

/usr/share/sendmail/cf (SuSE)




not provided[12]


(contains PID of sendmail process)













syslog mail facilitymessages


not configured






/var/log/maillog (Red Hat)

/var/log/mail (SuSE)





[9] Other features can also be specified in these files (e.g., daemon options).

[10] The /etc/sysconfig/sendmail file does not exist by default and must be created if desired.

[11] On Red Hat systems, you must install the separate sendmail-cf package if you want to modify your sendmail configuration.

[12] The Mail section of the sysman utility offers a prompt-based sendmail.cf setup facility (the direct command is mailsetup). I ignore it and use the real thing.

sendmail's functioning is controlled by the sendmail daemon, and all the other components work under its direction. The daemon is generally started at boot time with a command like the following:

sendmail -bd -q30m

This command runs sendmail as a background daemon and checks its work queue every 30 minutes. In boot scripts, starting the daemon is generally preceded by commands that remove lingering junk files from sendmail's queue directory.

On systems with System V-style boot scripts, you can start or restart the sendmail daemon with a command like this one:

# /sbin/init.d/sendmail restart

See Table 9-3 to determine the configuration file location on your system.

On AIX systems, you use these commands to direct the System Resource Controller to start or restart the daemon:

# startsrc -s sendmail # refresh -s sendmail Configuring sendmail

Previously, configuring sendmail was something of a black art; it took a long time to learn how, and even then the process remained at least somewhat mysterious to all but the true gurus. However, since the sendmail configuration process began using the m4 macro preprocessor facility to create sendmail.cf configuration files, the job has become much, much easier. The discussion that follows presents an introduction to sendmail configuration; of necessity, some of sendmail's complexity is glossed over at times.

When you create a sendmail configuration file, you tell sendmail about the specifics of mail submission and delivery on the local computer system. sendmail is highly configurable, allowing you to specify desired behavior in detail and to modify almost any of its default settings. Fortunately, however, these defaults are well-chosen, and configuring sendmail is quite simple for the most commonly used mail scenarios.

sendmail's main configuration file, sendmail.cf , is created by running a much simpler source file through the m4 macro processor. To build a custom configuration, you must create this second file, process it, install the resulting file into the proper directory, and notify the daemon to reread it.

The configuration file build directory varies for differentLinux distributions (see Table 9-3). The main directory contains a variety of sample configuration source files (their extension is .mc), and you can usually begin a new configuration by copying and then modifying one of them. In their simplest form, these files contain three main types of entries:

Macro invocations

These entries are predefined macros that expand to the items necessary to enable a particular sendmail feature or setting. Macro names are conventionally in uppercase letters, and their arguments are specified as a parenthesized, comma-separated list. The most commonly used macro is FEATURE, which selects the sendmail feature corresponding to its argument. Feature names are keywords with lowercase names: e.g., FEATURE(`smrsh'). Features are defined in files named ../feature/name.m4, and you can examine these files to see what a given FEATURE macro really does.

Additional macro definitions

These macros are performed via the m4 define command, which has the form:


Item names are in uppercase (e.g., MASQUERADE_AS). Such defines are used both to enable sendmail features and to set the values of various sendmail parameters. The latter have names beginning with conf (e.g., confALIAS_FILE).


Source files usually begin with a block of comments, delimited by divert(-1) and divert(0) commands (these tell the preprocessor to ignore all lines between them). Additional comments may appear elsewhere in the file following the string "dnl".[13]

[13] You may also see this string at the end of some configuration file lines. The dnl macro is an m4 construct that says to discard everything following it until the newline character when processing the file.

As the examples illustrated, character strings specified as macro arguments are enclosed with an initial backquote and a closing single quote:

`string'     Note the odd quotes.

You can find information about all of sendmail 's m4-based configuration options in the README file in top-level sendmail.cf build directory (i.e., ../ relative to the directory listed in Table 9-3); this document is titled "Sendmail Configuration Files" and is also available on the sendmail websites. For the goriest of details, consult the book sendmail by Brian Costales with Eric Allman (O'Reilly & Associates). Getting started: A sample mail client configuration

The listing below illustrates the use of these various items within a sendmail source file. This file is used on the client systems of a site that uses a designated mail hub for all nonlocal outgoing mail; in other words, mail submitted on a client system destined for any local system is delivered directly, but all mail destined for systems outside the local domain gets forwarded to the mail hub. This configuration assumes that the aliases file on each system defines the ultimate email destination for all users in the domain.

divert(-1) #####################################################       If you modify this file, you will have      to regenerate /etc/sendmail.cf (run ./Build)    ##################################################### divert(0) VERSIONID(`Config file for Red Hat Linux') OSTYPE(`linux') FEATURE(`smrsh') define(`PROCMAIL_MAILER_PATH',`/usr/bin/procmail') FEATURE(`local_procmail') define(`SMART_HOST',`poffice.ahania.com. ') define(`STATUS_FILE',`/var/log/mail.stats') MAILER(`smtp') MAILER(`procmail')

As usual, the source file begins with comments. The first macro in the file, VERSIONID, specifies a version string identifying this particular version of the source file; often, the value of this macro is a source control system ID string,[14] although in our case it is simply a few words of description.

[14] In other words, "$Id: ch09.xml,v 1.12 2002/09/27 14:49:33 chodacki Exp chodacki $" within the source file, which is filled in with a verbose and ugly version string when you check the file out.

The next macro, OSTYPE , specifies the operating system type of the target system; in this case, Linux is selected. This macro causes another, OS-specific source file to be included within this source file. The various defined ostypes and their associated source files are located in the ../ostype subdirectory (relative to the build directory). You should select and examine the one corresponding to your operating system. Looking at the file is important so that you are aware of predefined defaults set there.

The next three macros select two sendmail features: the first FEATURE macro, smrsh, says that sendmail's smrsh program should be used as the shell through which mail is sent to files and programs. The second feature, local_procmail, says to make procmail the default local delivery agent. The intervening line defines the path to the procmail program (the default is /usr/local/bin/procmail).

The next two lines use the define macro to indicate the system that is the outgoing mail hub for mail outside the local domain (poffice) and to specify an alternate location for the sendmail status/statistics file (usually /etc/mail/statistics). The final two lines of the file use the MAILER macro to specify that SMTP and procmail local mailers (delivery agents) are in use on this system.

Note that the order of items within this file is important. This is the general structure of an .mc source file:

VERSIONID OSTYPE DOMAIN            Domain-wide configuration file FEATURE define MAILER            First "smtp",  then "local", then others LOCAL_RULE_*      Local rewriting rules (advanced feature) LOCAL_RULESET

Thus, FEATUREs generally precede defines. However, if a setting related to a feature is specified in a define macro, that define should precede the corresponding FEATURE. We saw an example of the latter with the local_procmail feature in our example.

The DOMAIN macro may be used to specify a domain-wide configuration file holding settings desired on every host (or across a group of hosts), as in this example which selects the generic domain:


The name specified as its argument is taken as the name of an .m4 file in ../domain relative to the build directory (i.e., ../domain/generic.m4 in this example).

Occasionally, you may want to ensure that some feature is disabled. The undefine macro is used in these cases, as in this example, which disables alias expansion:

undefine(`ALIAS_FILE') Building sendmail.cf

The Build script in the build subdirectory is used to create a configuration file from a .mc source file. I also tend to be a bit cautious in installing the new file, so I use a process like this:

# cd build-dir # emacs test.mc  # ./Build test.cf  # cp /etc/mail/sendmail.cf /etc/mail/sendmail.cf.save  # cp test.cf /etc/mail/sendmail.cf # chmod 444 /etc/mail/sendmail.cf

Whenever you change your sendmail configuration, you must send the running daemon a HUP signal:

# kill -HUP `head -1 /location /sendmail.pid`

The sendmail.pid file stores the process ID of the sendmail daemon (on its first line), along with the command used to initiate it (line two).

Some systems do not provide a Build script. In these cases, use one of the following commands (executed in the build directory):

# make test.cf # m4 ../m4/cf.m4 test.mc > test.cf

The first command is used when there is a Makefile present in the build directory, and the second is the vanilla invocation of the m4 macro processor. In the latter case, the command explicitly prepends the standard sendmail m4 include file to the source file; this step is taken care of for you by the Build script or Makefile. Configuring the mail hub

Here is a source file that might be used to build the sendmail.cf file for the mail hub computer system (the initial comment block and VERSIONID and OSTYPE macros have been omitted):

FEATURE(`use_cw_file')  dnl Send out all mail as user@ahania.com MASQUERADE_AS(`ahania.com')  FEATURE(`masquerade_envelope')  FEATURE(`allmasquerade')  MAILER(`smtp') MAILER(`local')

The first feature specifies that an external configuration file will be used to specify a list of hosts and domains for which this system will accept and deliver mail locally (traditionally known as the cw file, after sendmail's internal "class w"). The default file for this purpose is /etc/mail/local-host-names, an ordinary text file containing one name per line. At a minimum, this should contain all the aliases for the local hostname. You will also need to include the local domain within the file in order to support local delivery of addresses of the form user@local-domain (i.e., user@ahania.com, in our example).

This macro is actually included by default in most sendmail configurations. Therefore, mail client systems also use this file (it is enabled within one of the m4 include files), and you should configure it on such systems as well.

The three lines following the comment enablemasquerading on this host. Masquerading presents a single, common source location for all outgoing mail. For example, it can be used to make all email appear to be coming from a single system, regardless of where it was actually submitted. It can also be used to make all local sender addresses conform to a particular form (often user@site),

In this case, the MASQUERADE_AS macro causes all mail leaving the site to appear to be coming from the user at ahania.com, and all references to any local computer are removed. The masquerade_envelope feature causes masquerading to occur within the message's envelope[15] as well as the standard mail headers, and allmasquerade says to masquerade recipient names as well as sender names (the latter is useful when the recipient list includes both local and nonlocal people).

[15] The envelope is additional data wrapped around the actual message headers and content. It contains the actual delivery addresses, and it is built from the message's mail headers by the mailer (delivery agent).

You can exclude some hosts and/or domains from masquerading using the MASQUERADE_EXCEPTION macro, which takes as its argument the host or domain to be excluded.

A related feature is always_add_domain, which appends the local domain to unqualified usernames (although many mailers also do this). It also respects the setting of MASQUERADE_AS. Including this feature is virtually always safe.

If you decide to use masquerading, you may want to exclude some usernames from the translation process. This is the purpose of the EXPOSED_USER macro. For example, the following macro excludes root from masquerading:


Other system-related mail addresses should also be so excluded, including Mailer-Daemon, postmaster, and so on.

We will consider additional masquerading-related features in Section later in this chapter. Selecting mailers

The final two lines of the example mail hub configuration file the MAILER macros activate various delivery agents: in this case, SMTP and the default local delivery agent.

sendmail has many defined mailers, including the following:


Local mail delivery (using default or defined programs)


SMTP mail transport


Delivery via procmail


Delivery to the Cyrus facility


Delivery to HylaFAX (by Sam Leffler; see http://www.hylafax.org)


Delivery to the QuickPage paging facility (http://www.qpage.org)


Usenet news delivery


UUCP mail transport

Once again, order matters among the selected mailers. You will be safe if you place smtp first, follow it with local, and then list any other mailers. Note that the mailers local and procmail are made equivalent when you include FEATURE(`local_procmail').

Best practice is to include MAILER macros only for those mailers that your site actually uses.

Each of these defined mailers has some associated parameters that can be defined, including mailer_MAILER_PATH and mailer_MAILER_ARGS, which specify the executable path and desired command arguments, respectively (where mailer is replaced by the uppercase mailer name). We'll look at an example in a bit.

The program used for local mail delivery MAILER(local) varies quite a bit from Unix version to version:


In general, you can determine the default local mailer by running a command like the following (the location of the configuration file will vary):

$ grep Mlocal /etc/sendmail.cf Mlocal,         P=/usr/bin/procmail, ...

The path following "P=" indicates the local delivery agent. There are many delivery agents in use on Unix systems: mail, rmail, deliver, mail.local (part of the sendmail package), procmail, and uux with rmail (for UUCP-transported mail).

The default local delivery agent is /bin/mail for mail messages and /bin/sh for mail messages piped to files or programs. You can override these programs and/or locations with define macros such as these:

define(`LOCAL_MAILER_PATH', `/usr/bin/rmail') define(`LOCAL_MAILER_ARGS', `rmail -d $u') define(`LOCAL_SHELL_PATH', `/usr/bin/sh') define(`LOCAL_SHELL_ARGS',`sh -c $u')

These entries define the local delivery agent to be /usr/bin/rmail and specify an alternate location for the shell. The _ARGS parameters specify the command to run in each case: rmail will use the -d option followed by the delivery address ($u, which resolves to the appropriate username), and piped email will be processed with sh -c address (where $u will again expand to the delivery address in this case, the command specified as the alias translation).

If you want to use sendmail's mail.local program as the local delivery agent, you can simply include this macro in your configuration source file:


The second argument is optional and defaults to /usr/libexec/mail.local.[16]

[16] An alternate default directory for mail.local and smrsh can be set by defining the confEBINDIR parameter.

As with the local delivery agent, you can determine which program is used for piped mail messages using a command such as grep Mprog /etc/sendmail.cf. Since piped email is a traditional security hole, many administrators choose to replace sh with a more restricted shell. The smrsh shell included with sendmail fits the bill nicely (it's pronounced "smursh," but it stands for "sendmail restricted shell").

As we've seen, smrsh may be selected using the following FEATURE macro:


The second argument is again optional and defaults to /usr/libexec/smrsh.

Like other restricted shells (see Chapter 7), smrsh ignores all I/O redirection within commands, strips all initial paths from command names, and restricts allowable commands to those stored in its executables directory, usually /usr/lib/sendmail.d/bin. The administrator then places permitted (safe) commands (e.g., vacation) in that directory, usually via symbolic links, taking care to exclude unsafe commands, such as shells (other than smrsh itself), command interpreters (e.g., Perl, Python), and programs offering shell escapes. Neither the directory nor the files within it should be group- or world-writable.

procmail can spawn a subshell, so it should probably not be included in smrsh's set of allowed commands (although it is often included anyway). An alternative method for allowing users to run procmail is to make it the local mailer (as is the default on Linux systems). You'll have to decide which tradeoff is the lesser evil on your system if users need procmail and you want to make them use smrsh for piped email. More about pipes to files and programs

Normally, pipes to files can be made to ordinary files, devices, and other filesystem entities. You may want to limit them to ordinary files (to prohibit device access and prevent inadvertent errors, such as overwriting directories) by defining confSAFE_FILE_ENV :


If you further want to limit the allowed locations for writes to files, specify the root of the desired directory as the second parameter. For example, the following entry restricts such writes to files under /home:


Finally, you can disable mail message relaying to files and programs by removing the / and | characters from the list of flags given to the local mailer:

MODIFY_MAILER_FLAGS(`LOCAL',`-|/') Some client and mail hub variations

In this section, we look briefly at a potpourri of additional features related to general client or hub configuration. An isolated internal network

A non-Internet-connected LAN can easily rely on a single host to serve as its conduit to the outside world. The client systems in such a network use an additional feature: nocanonify . This feature tells sendmail not to expand email addresses to their fully qualified form on the local system. Instead, it will be done on the mail hub. Delaying it until then saves some unnecessary or redundant DNS lookups locally even for hosts with connections to the Internet. Moreover, it is essential to include this feature when clients with limited or no DNS access will be sending messages to arbitrary Internet destinations that they may not be able to resolve.

On the mail hub, the relay_entire_domain feature allows that system to accept mail for forwarding from any host in the local domain. Relaying is discussed in more detail when we consider sendmail's anti-spam features later in this section. A null client

It is possible to define an even more minimalclient system than the one we examined earlier. sendmail offers the option of a "null client" system in which all mail is sent to another host for processing. It uses a minimal configuration file, consisting of merely the OSTYPE macro and one FEATURE macro:


This example specifies the target host the system to which to forward outgoing mail as poffice. This feature also automatically turns off all address aliasing and forwarding features.[17]

[17] You can disable aliasing and/or forwarding with the macros undefine(`ALIAS_FILE') and define(`confFORWARD_PATH',`'), respectively.

If you decide to set up a null client system, you should examine the corresponding operating system-specific include file (in ../ostype) to ensure that no unwanted features are enabled there. In addition, there is no need to run the sendmail daemon on such a client system (user agents will invoke it themselves when necessary). Mailer-specific and other local relays

More complex mail transport schemes can also be implemented in addition to what is provided by the SMART_HOST feature (which specifies a host to handle mail addressed to hosts outside the local domain). For example, different mailers can each have a specified relay host for forwarding mail traffic using the corresponding protocol. For example, the following macro defines oldmail as the relay host for UUCP-based mail:


Mailer-specific relay settings take precedence over SMART_HOST.

The MAIL_HUB feature routes all outgoing mail to a specified host, as in this example:


Alternatively, LOCAL_RELAY can be defined to route unqualified mail addresses to a specific host:

define(`LOCAL_RELAY',`poste') LOCAL_USER(`root admin')

These macros cause all mail addressed to just a username to be routed to poste for processing, although mail to root and to admin is excepted. The entries in the aliases file are not used for such rerouted addresses.[18]

[18] If you use both MAIL_HUB and LOCAL_RELAY, MAIL_HUB wins, unless you also include the stickyhost feature. In the latter case, mail to unqualified usernames goes to the LOCAL_RELAY destination, and all other local outgoing mail goes to the MAIL_HUB destination.

Here is a summary of the various mail hub specification macros:


Handles mail going outside domain


Handles local domain mail


Handles local unqualified addresses More addressing options

sendmail supports several ways of implementing aliasing of various sorts, including NIS/NIS+, LDAP, and lookup tables (databases, actually), in addition to the aliases file and forwarding mechanisms. In this section, we consider some of these aliasing methods, along with some related issues. Sender aliasing

sendmail supports lookup table-based aliasing in addition to the standard mechanisms; the databases used for these lookups are generically known as "maps." The genericstable feature selects map lookup for outgoing sender addresses. You enable it with configuration source file entries like the following:

FEATURE(`genericstable',`hash /etc/mail/senders') GENERICS_DOMAIN_FILE(`/etc/mail/local-host-names')

The first entry selects the generics table feature and specifies the database as the hash-type Berkeley DB file /etc/mail/senders.db (the argument's syntax is thus db-type path). The default is hash /etc/mail/genericstable.

The second macro specifies that the file listing the domains to which the map should be applied is /etc/mail/local-host-names (the same file listing hosts and domains to be considered as local). Alternatively, a different file could be specified, or the GENERICS_DOMAIN macro could be used to list the local domains explicitly.

Obviously, the associated database file must also be created. The process for doing so is simple:

  • Create a text file containing entries of the following format:

    sender-address desired-translation

    For example:

    chavez     rachel_chavez@ahania.com carr       steve_carr@zoas.org ewood      eve_wood@ahania.com

    Names in the left column implicitly have the local domain appended to them, because only fully qualified sender names are translated by the generics table feature. (More complex entries are also supported; see the sendmail documentation for details.)

  • Create a database file from the text file using the makemap command. For example, to create a database from the file senders.txt, you would generally use this command, which creates the file /etc/mail/senders.db:

    # cd /etc/mail; makemap hash senders < senders.txt

    sendmail supports several database formats. The hash variation of the Berkeley DB database used above is generally preferred, and it is supported by all the systems we are considering, except AIX. On AIX systems, use the dbm file type.[19] Note also that database support is selected at compile time; verify that the list of compiler options includes NEWDB (indicating Berkeley DB support) and/or NDBM (DBM support).

    [19] Under AIX, you must also build the makemap utility from the sendmail source distribution; it is not provided.

So what happens when someone replies to one of these genericized email addresses? The aliasing mechanisms in the local domain need to recognize and translate the address accordingly (e.g., via an aliases file entry) for the mail to be delivered to the proper recipient. You can also use the virtual user table feature for the reverse translations (discussed under Section, a little later in this section).

A few more points: first, it is often a good idea to include the always_add_domain feature when using a generics table to ensure that all names are fully qualified. Second, the generics_entire_domain feature can be used to apply generics table translation to senders from subdomains of the domains using the feature. Finally, be aware that map translations are not recursive; only a single lookup operation is performed. Using LDAP for incoming mail addresses

Another option for address aliasing is to use an LDAP database to store the associated information. Recent versions of sendmail include the capability to issue LDAP queries (provided it is selected at compile-time; check the options for LDAPMAP ). The following configuration source file macros enableLDAP support for our example domain:

FEATURE(`ldap_routing')LDAP_ROUTE_DOMAIN(`ahania.com') define(`confLDAP_DEFAULT_SPEC', `-h orwell.ahania.com -b ou=People,dc=ahania,dc=com')

The first feature enables LDAP support, and the second macro specifies the domain to which it applies. The final macro specifies the LDAP server and the base distinguished name at which to begin the search (see Chapter 6 for a detailed discussion of LDAP).

Once enabled, sendmail uses the following LDAP attributes of the inetLocalMailRecipient object class:[20]

[20] You can change this class and other LDAP-related defaults using optional arguments to the ldap_routing feature.


Incoming mail address


Local address to which to deliver mail


Host to which to route mail (not often used)

Here are some exampleLDAP records:

dn: uid=chavez,ou=People,dc=ahania,dc=com uid: chavez objectClass: posixAccount objectClass: inetLocalMailRecipient mailLocalAddress: rachel_chavez@ahania.com mailRoutingAddress: chavez@dalton.ahania.com    dn: uid=nadia,ou=People,dc=ahania,dc=com uid: nadia objectClass: posixAccount objectClass: inetLocalMailRecipient mailLocalAddress: nadia_rega@ahania.com mailRoutingAddress: nrega    dn: uid=scarr,ou=People,dc=ahania,dc=com uid: scarr objectClass: posixAccount objectClass: inetLocalMailRecipient mailLocalAddress: steve_carr@ahania.com mailRoutingAddress: scarr@zoas.org mailHost: oldmail.ahania.com

(Note that only the relevant attributes are shown; in actual practice, these entries would probably contain additional object classes and their associated attributes.)

The first two examples translate generic incoming addresses: a fully qualified address and a (local) alias, respectively. The final example performs a similar translation, this time introducing a different domain in the target address. In addition, the mail will be routed to the host oldmail (as specified in the mailHost attribute). In other words, incoming messages addressed to steve_carr@ahania.com will be routed to host oldmail, which will deliver them to scarr@zoas.org. The redirect feature

sendmail offers a very convenient way to deal with email that comes to people who have left an organization: its redirect feature. When this is included in the configuration source file, mail addressed to any recipient of the form someone@anywhere.REDIRECT is returned to the sender with the message:

551 User has moved; please try someone@anywhere

To use the feature, you must define aliases of the proper form for users who have left. For example, this alias will notify anyone who sends a message to erika that her mail should now go to eps@essadm.com:

erika:   eps@essadm.com.REDIRECT Virtual hosting

We saw a simple example of address masquerading when we considered the example mail hub configuration earlier. Many times, however, a mail host needs to provide mail services for several distinct domains (often in the context of website hosting). This process is known as virtual hosting, and sendmail provides several features to support it. The most important of these is the virtual user table, which translates incoming addresses according to a map that you set up.

Here are some sample configuration file entries using this feature:

FEATURE(`virtusertable',`hash /etc/mail/vuser') VIRTUSER_DOMAIN_FILE(`/etc/mail/local-host-names')

As you can see, the virtual user table entries are quite similar to those used with the generics table feature.

The format of the source file for the virtual user map is:

incoming-address desired-local-recipient

The entries in this file typically include not only individual user address translations but also blanket transformations of the addresses for entire domains. Here are some examples (assume ahania.com is the local domain):

rachel_chavez@ahania.com   chavez@dalton.ahania.com erika@ahania.com           erikap@mango.essadm.com help@ahania.com            error:No such user @essadm.com                czarina@essadm.com @zoas.org                  %1@ahania.com

The first two entries translate addresses to different users within the same and a different domain, respectively. The third entry returns an error to the sender for any message addressed to help in the local domain.

The final two entries match any address in the specified domain. The entry for essadm.com sends all messages to any user at that domain to the user czarina. The final line maps all addresses of the form user@zoas.com to the same username in the local domain. Note that more complex constructs are possible; see the sendmail documentation for details about the entry syntax.

Once again, the makemap command is used to create the database file. For example:

# cd /etc/mail; makemap hash vuser < vuser.txt

By default, the map is used only for fully qualified addresses in the local domain. The virtuser_entire_domain feature can be used to apply virtual user table translation to addresses referring to subdomains of the associated domain(s).

Virtual hosting requires that the DNS setup for the hosted domains match the setup specified to sendmail. In particular, the MX records for these domains should point to the appropriate system in the host domain. The services switch file

The order of various name-lookup services is controlled, as usual, by the network services switch file, which is /etc/nsswitch.conf on Linux and Solaris systems (more specifically, it is controlled by the aliases entry). For example, the following entry specifies that the standard aliases file should be used for aliases, followed by any NIS, and then the NIS+ maps:

aliases: files nis nisplus

For systems not supporting the services switch file, sendmail provides similar functionality via the confSERVICE_SWITCH_FILE setting:


The file above selects the usual name and location for this file (although the setting isn't configured at all on many systems). The file has a slightly different format, omitting the colon following the initial keyword:

aliases     files nis nisplus hosts       files dns nis nisplus

As this example indicates, the sendmail services switch file can contain entries for both aliases and hosts, providing search orders for mail addresses and hostnames, respectively. See Section 5.2 for more information about the network services switch file. Spam suppression

sendmail offers several features designed for dealing with spam, the electronic equivalent of junk mail.[21] These features can be grouped into four areas:

[21] The official technojargon term for spam is unsolicited commercial email, or UCE; it is also occasionally referred to as unsolicited bulk email (UBE).

Message relaying

Current versions of sendmail disable relaying, the passing on of received messages that are not destined for any local user. Doing so prevents the bad guys from using your mail server as a conduit for generating spam traffic, consuming (stealing) your resources in the process. Accordingly, this item is related more to general spam prevention than to eliminating spam locally.

Verifying sender data

By default, sendmail rejects mail coming from a DNS domain whose name cannot be resolved and from senders without fully qualified mail addresses (there are features to override these defaults). Such messages are very likely to have forged headers and to be spam. You can use the access database to define exceptions to these tests if you need to (see the next item).

Address-based mail filtering via an access database and public blacklists

Mail from various users and/or sites can be rejected. These features are highly configurable to allow both limited relaying and specification of mail sources whose messages you want to ignore or reject.

Mail header checking

sendmail can apply a series of administrator-defined checks to mail headers to determine whether the mail should be accepted. See the sendmail documentation and the file knetch.mc (ostensibly from Eric Allman's own system), which is usually included in the build directory, for more information and examples.

We will consider the first and third items in more detail in the remainder of this section. For a different approach to detecting and processing spam, see Section 9.6 later in this chapter. Message relaying

Prior to sendmail Version 8.9, the transport agent operated in a friendly mode, relaying any mail that was presented to it. This is known as "promiscuous relaying." Unfortunately, systems that allow such relaying referred to as "open relays" have been misused by spammers, who send messages through systems that allow relaying, thus disguising or erasing the true origin of the messages. This is a problem for the relay system because the spammers are consuming bandwidth and system resources on the relay host. For example, all of the DNS lookups needed to deliver, say, 10,000 spam email messages are happening on your system rather than theirs.

As a result, all relaying is turned off by default in recent sendmail versions. However, sendmail does include options to turn on relaying only as needed, in limited and controlled ways. We've already seen one example of this in the relay_entire_domain feature. Also, when you use the cw file for the domain lists for the generics and/or virtual user tables, you effectively turn on relaying for the included domains.

The RELAY_DOMAIN and RELAY_DOMAIN_FILE macros can be used to specify additional domains for relaying. These macros take a domain list and filename (containing the domain list) as arguments, respectively. You can also use the access database to specify allowed relay domains and hosts (see the next section).

You may also want to reject mail addressed to nonexistent local addresses. The LUSER_RELAY macro specifies how such messages should be handled. For example:

define(`LUSER_RELAY',`tundra.ahania.com') define(`LUSER_RELAY',`local:trashman') define(`LUSER_RELAY',`error:wrong number bozo')

The first example reroutes such messages to the host tundra. The second sends them to a local address (via the LOCAL mailer); this address can be an alias pointing anywhere you want. Finally, the third example returns such messages with the indicated error message (which may not be appropriate for use at your site).

If you are using limited relaying, the best practice is to undefine the relay settings for mailers you are not using in order to minimize your site's vulnerability to misuse by spammers. For example:


and similarly for other unused mailers (e.g., DECNET, BITNET and so on).

Some people advise rejecting all mail with any variation of UUCP-style addresses using this macro:


This advice arose from the fact that spammers used to occasionally use such addresses in an attempt to trick sendmail. However, doing this will reject all legitimate email from sites that happen to still use UUCP (and there are more of them than you think). All in all, this feature has no appreciable effect on spam and can block real electronic mail. For this reason, I strongly discourage you from using it. Public blacklists and the access database

We now turn to two features related to stopping spam at the incoming mail host, preventing it from ever reaching user mailboxes.

The first of these is the ability to reject mail from any site included in one of the public lists of known spammers and open relays:


This feature tells sendmail to check senders against such a list. Such facilities use standard DNS facilities to take advantage of the normally unused IP address; the facilities set up an otherwise normal DNS server that returns this address for all sites (IP addresses) in their list. Transport agents can choose to interpret the address as marking a bad site, and sendmail rejects mail from these sites when this feature is enabled.[22]

[22] You can also consult these lists via the procmail mail filtering program and have more options for handling the corresponding messages (see the discussion of this facility later in this chapter).

The default list to check is the Realtime Blackhole List run by the Paul Vixie and coworkers' Mail Abuse Prevention System (MAPS) project (see http://maps.vix.com for more information; the actual server is rbl.maps.vix.com). You can specify a different server to query via the second argument to the macro, and you may include the feature multiple times. MAPS provides other lists as well, as do several other organizations (e.g., theOpen Relay Behaviour-modification System (ORBS); see http://www.orbs.org).

There is always a small possibility of rejecting legitimate mail messages using this feature. If this occurs, you can use the access database to make exceptions without disabling the entire feature.

You enable use of an access database (map) using the following features:

FEATURE(`access_db', `hash /etc/mail/access') FEATURE(`blacklist_recipients')

The access_db feature's arguments specify the type and pathname for the database file (as for the generics and virtual user tables); the default file type and location are given in the example.

The second feature is optional. The blacklist_recipients feature allows you to include access database entries blocking incoming messages for local mail recipients and hosts.

You create the access database file using the makemap command:

# cd /etc/mail; makemap hash access < access.txt

The entry format for access database entries is the following:

item action

where item is a username, host, domain, or network, and action is a keyword indicating how to treat email from that source. The available keywords include:


Accept email even if it fails other tests.


Relay messages from this source.


Reject messages from this source.


Reject messages with a specified error message (see examples).


Silently ignore messages from this source.

In addition, if a site's entry in the access database specifies mail rejection in any of its variations, outbound mail directed there will also be prohibited.

Here are some examples:

bad-guys.org                   REJECT evil-ones.net                  ERROR:"550 No spam accepted" mole.bad-guys.org              OK zoas.org                       RELAY 10.0.22                        RELAY something4nothing@notaol.org   DISCARD mybadguy@                      REJECT fortress.ahania.com            ERROR:"550 No mail allowed"

The first two entries reject mail from the specified domains, using the default and specified error message, respectively. Note that error messages that you specify must begin with the 550 error code. The third entry defines an exception to the preceding rejection of mail from the bad-guys.org domain, allowing mail from host mole to get through.

The fourth and fifth entries allow relaying of mail originating from the zoas.org domain and any host on the 10.0.22 subnet. The following two entries apply to specific mail accounts, discarding any mail received from sender something4nothing in the notaol.org domain and rejecting incoming mail addressed to mybadguy in the local domain. The final entry rejects mail addressed to anyone on host fortress in the local domain.

Note that the last two entries, which apply to local recipients rather than remote senders, require the blacklist_recipients feature in order to be valid.

If finer-grained access control is desired, the access database also supports a slightly modified syntax variation allowing separate entries for senders, recipients, and connections at a site. It consists of prepending one of From:, Connect:, and To: to the simpler entry. For example, the following entry rejects mail from the specified address but allows outgoing messages addressed to it:

From:spammer@notaol.org        REJECT

Similarly, the following entries reject mail to and from evil-ones.org but define an exception for one sender and another recipient:

From:evil-ones.org             REJECT To:evil-ones.org               REJECT From:myguy@evil-ones.org       OK To:mygal@evil-ones.org         OK

You can also use the access database to implement unidirectional relaying. For example, this entry relays messages from zoas.org but does not relay messages from other sources to it:

Connect:zoas.org               RELAY

Note that Connect: is used, not From:. Use To: to allow relaying to a specified destination.

Access control entries allowing access from specific sites or senders cannot protect against address spoofing.

The entries in the access database are used by three distinct sendmail message examination phases.[23] Messages are checked first for allowed relaying (based on the client hostname and address), then for an allowed sender, and finally for an allowed recipient. If a message is rejected in one phase, it cannot be restored later. This means that the preceding syntax does not allow for certain kinds of exceptions to be defined. For example, you cannot allow email to a specific user always to get through regardless of its origin, because the local addresses checks are downstream from the message source checks.

[23] To be more technically accurate, the entries are used by three different sendmail "rulesets": check_relay, check_mail, and check_rcpt.

However, you can use the delay_checks feature to reverse the order of the three test phases. In this mode, recipient-level access controls have the highest precedence, rather than the lowest.

In addition, if you add the friend argument when you invoke the delay_checks feature, you can define local addresses that are exceptions to all access checks, using the following syntax:

To:rubbish@ahania.com          SPAMFRIEND

This entry exempts all mail addressed to rubbish in the local domain from access control tests, causing it to be accepted regardless of its origin. (Thus, "spamfriend" is used to mark recipients who don't mind getting spam.) sendmail security

In this section, we take up several topics related to sendmail security. We'll begin by considering the ownerships and permissions of the various sendmail-related files and directories, to which I've already alluded several times in the course of this discussion. There are several points to keep in mind:

  • The directory locations of all sendmail-related files executables, configuration files, spool directory, and so on should be safe: root should own each subdirectory in the path (along with the appropriate group), and no component of any path should be world-writable.

  • The configuration files themselves should not be world-writable either. This includes sendmail.cf and any other configuration files you are using (usually located in /etc/mail).

  • Ideally, the spool directory should be protected against all but root[24] access, using a mode of 700. However, restricting access in this way prevents ordinary users from listing the queue contents with mailq. If this is a problem, you have the choice of relaxing the permissions with a less restrictive mode or using a privacy option to allow certain users to view the queue despite the protection (discussed below).

    [24] Or another user specified via the confRunAsUser parameter. The sendmail default user

Although it is a SETUID root program, the sendmail process always tries to reduce its privilege to the minimum required to perform a task by giving up its root privilege for some other user context appropriate to the task at hand. For example, it takes on the identity of the recipient user when performing certain mail forwarding tasks.

The confDEF_USER_ID parameter specifies the user/group combination to use when sendmail wants to reduce its privilege but there is no specific user identity to take on. Here is an example:


The macro sets the user and group identities that sendmail assumes to the user and group named mailnull and mailngrp, respectively. The mailnull user should be defined with a password file entry like this one:

mailnull:***:9947:9947:sendmail default:/not/real:/dev/null

The user's home directory should not exist, and no valid login shell should be specified. The password for this account should also be set to an asterisk or other invalid character (either here or in the shadow password file when in use).

The group is set up similarly, for example:


The actual UID and GID do not matter, but this user and group should not own any files or be used for any other purpose. As a result, the nobody user should not be used as the default user. Privacy options

sendmail provides a number of options for restricting or eliminating various sensitive tasks via the confPRIVACY_FLAGS parameter:


The second argument is a comma-separated list of flags that you want to enable. There are several flags you should consider including:

  • authwarnings is the default setting for this parameter. It causes sendmail to add authentication warning headers to suspicious mail messages (see the sendmail documentation for details on these checks).

  • noexpn and novrfy prevent responses to the SMTP EXPN and VRFY commands, respectively. These commands are designed to expand aliases and verify mail addresses, but they are often misused by spammers (to discover legitimate email addresses) and other bad guys. You may also prefer to use goaway, which disables all SMTP verification and status queries.

  • restrictmailq restricts the use of the mailq command to users in the group that owns the /var/spool/mqueue directory. In addition, it permits group members to view the queue even when the directory permissions do not allow file access, allowing you to use a protection mode of 700 without breaking the mailq command.

  • restrictqrun prevents anyone but the user owner of the queue directory (usually root) from processing the queue.

  • noreceipts causes sendmail to ignore return-receipt requests (eliminating the associated bandwidth wastage). SASL authentication

The Simple Authentication and Security Layer ( SASL) provides authentication capabilities to connection-based network communications (for more information, see http://asg.web.cmu.edu/sasl/). SASL authentication can be performed using a variety of mechanisms, and the communications partners can also negotiate a protection method (e.g., encryption) for future messages. A variety of network facilities use SASL, including OpenLDAP and sendmail.

Authentication for SMTP connections via SASL is supported starting in sendmail Version 8.10 using the Cyrus SASL facility (http://asg.web.cmu.edu/cyrus/), and Version 8.11 adds support for encryption via TLS (the Transport Layer Security protocol, designed to replace SSL; see http://www.openssl.org). SASL support must be enabled at compile time (check for the SASL option).

sendmail provides macros that allow you to specify:

  • Allowed authentication mechanisms, as well as those acceptable for relaying

  • Authentication requirements and authentication data (or location) for the local server

  • Authentication and encryption requirements on a per-domain or host level via entries in the normal access map

To use these features, you must install the Cyrus SASL library (see http://asg.web.cmu.edu/cyrus/), compile sendmail with SASL support, and then configure it appropriately. For more information, consult the following:

  • The "STARTTLS" and "SMTP Authentication" sections of the sendmail configuration README file

  • The auth.html and starttls.html pages at http://www.sendmail.org/~ca/email/ and the sysadmin.html page in the cyrus subdirectory at the same location Reducing the sendmail daemon's privileges

In the past, the fact that sendmail runs setuid root has been one of the factors allowing for security breaches. As a result, suggestions for reducing thedaemon's privilege level appear frequently. One method for doing so is to use the chroot facility (see Chapter 3). This approach retains the setuid status but limits the daemon's functioning to a minimal, isolated filesystem.

Version 8.12 provides a different technique for addressing this issue. It separates sendmail into two daemons, one operating as the transport agent and another operating a mail submission agent that handles mail from mailer programs that require message submission services. Their characteristics are described in Table 9-4.

Table 9-4. Dividing the sendmail daemon

Transport agent

Submission program




Owners (user, group)

root, GID 0

sm-msp, sm-msp

File Protection

550 (not SETUID)

555 + SETGID

Run as daemon?



Work queue



Configuration file



The binaries for the two files are copies of the same executable with different ownerships and permissions. The sm-mta program is a drop-in replacement for the current sendmail daemon. It requires changing the name of the program in the system startup files and adding the -L sm-mta option to the startup command. For example:

/usr/sbin/sm-mta -L sm-mta -bd -q30m

The other program is owned by a new user and group and is setgid to that group. Its work queue must be also be owned by this user and group and have the mode 660. It is not run as a daemon and has a separate configuration file, called submit.cf above. The latter includes the msp feature:


The feature enables and sets the various mail submission program-related parameters (e.g., the work queue directory).

Check the documentation for the latest version of sendmail for current information about these features. Monitoring ongoing operation

sendmail provides several utilities for monitoring its ongoing operation. The most important of these is mailq (equivalent to sendmail -bp), which lists the contents of sendmail's work queue (/var/spool/mqueue):

# mailq f3FHZeI08989     1240 Sun Apr 15 13:35 chavez            (Deferred: Connection refused by dalton.ahania.com.)                                        jones@dalton.ahania.com

This display lists only a single entry. The first line indicates the name of the message file in the work queue directory along with its submission time and sender. The second line in this entry indicates the message status; in this case, the remote host to which the message is addressed is not answering. The final line lists the recipient address.

Several different types of files may be present in the work queue directory; all have names consisting of a prefix plus the message ID. The prefix indicates the file content type:


Control file (includes message headers)


Data file (message text)


Holds mailer error messages ("transcript file")


Indicates a bounced message


Temporary file used as scratch when the qf file is being updated


Message processing has generated 32 or more locking failures

There are a couple of situations in which you may have to deal with the contents of the mail work queue:

  • If the queue becomes seriously overloaded, sendmail and/or system performance can be strained. In such cases, the best response is to temporarily stop the sendmail daemon, move the files to an alternate directory (or rename and recreate mqueue, making sure to set the ownerships and protections properly: root and 700), and restart the daemon. Then you can run sendmail manually on the saved files at a more convenient time without affecting any more incoming mail. To do so, use a command like the following, where save_queue is the location of the moved files:

    # sendmail -oQ/var/spool/save_queue -q
  • Check the queue occasionally for files that will never be successfully processed. For example, from time to time you will encounter orphaned df files, messages without any control file (which are therefore undeliverable). You can archive or delete these files as you see fit.

You can also examine sendmail operations by looking at the statistics file contents with the mailstats command, a separate utility included in the sendmail package (the statistics file location is set by defining STATUS_FILE and defaults to /etc/mail/statistics). Here is an example of running mailstats:

#  mailstats Statistics from Sun Apr  8 14:38:37 2001 msgsfr  bytes_from   msgsto  bytes_to  msgsrej msgsdis  Mailer     53        378K        5       12K        0       0  local   1231       7425K        0        0K        0       0  relay --------------------------------------------------------------- T 1284       7803K        5       12K        0       0 C 1284                    5                  0

(The first column, which shows mailer numbers, is omitted to save space.) The columns show the number of messages received (msgsfr), sent (msgsto), rejected (msgsrej), and discarded (msgsdis), as well as the number of bytes received (bytes_from) and sent (bytes_to), broken down by mailer. This output is from a system that holds very few user mailboxes, so the local traffic is quite limited. Most messages are relayed to a mail hub for processing. The final two lines in the output show the totals for the each column and the connection totals. Much larger numbers and additional mailers will probably appear in the output from typical systems at your site.

sendmail includes the ability to keep track of hosts to which delivery has failed and to use that data to prioritize future work. The following macro enables this feature using the conventional directory location:


You can view the current status data using the hoststat command (equivalent to sendmail -bh):

#  hoststat ---Hostname--------------How long ago----------Results--------- dalton.ahania.com          00:00:30   Deferred: Connection refu newton.ahania.com          01:47:03   250 2.0.0 f32Hl3720131 Me

The entries indicate the time and results of the last connection attempt for each host. You can reset all host connection data by issuing the purgestat command (equivalent to sendmail -bH). Performance

In this section, we look at some of the parameters that sendmail provides foroptimizing its performance.

Mail queues can get very large when a great deal of mail arrives at the same time. The mail queue can get large at other times as well. For example, as we've seen, mail messages are held in the work queue when the first attempt to deliver them fails. This can cause two types of performance bottlenecks. First, disk I/O itself can simply overwhelm its I/O capacity. In addition, very large queue directories suffer from the Unix operating systems' degrading directory-lookup performance (which becomes prohibitive at about 2000 files for typical nonlogged Unix filesystems).

One solution to both types of I/O bottlenecks is to use multiple queue directories, ideally each placed on a different physical disk. The following macro configures sendmail to use multiple work queues:


The macro tells sendmail to use all subdirectories with names starting with "q" under the usual directory as its work queues (sendmail picks the queue for each message at random). The directories can be local subdirectories or (better) symbolic links to actual directories on different disks. Multiple queue directories can also allow mail message processing to proceed in parallel across each work location. Files can be moved between queue directories on the same system, because the algorithm used to generate their names is guaranteed not to repeat for 60 years.

Here are some additional settings that may be useful in some situations. Most of them define parameters that serve to throttle back the workload when things get overloaded:


When needed, the main sendmail daemon will create additional child processes to help. This sets the maximum number of additional processes; additional connections will be refused when the maximum is reached. The default is no limit.


The fallback host to which to send bounced messages and messages with bogus addresses for further processing. Defining this can reduce the load somewhat on the local server. This setting is undefined by default.


The rate at which connections are accepted as n per second (the default is no limit). Additional connections are delayed. This setting can be useful for both smoothing out spikes in mail traffic and regulating the general flow rate.


Minimum time a message must wait in the queue before processing. This can be useful on a busy server as a way to process only a part of the queue at a time, as each queue run will skip jobs younger than this. The time is specified as a number followed by s (seconds), m (minutes) or h (hours): e.g., 5m. The default is 0, meaning no delay.


Load averages at which to queue all incoming mail (suppressing attempts at immediate delivery) and at which to refuse additional connections (they default to 8 times and 12 times the number of CPUs, respectively). These may need to be lowered somewhat on very busy systems with slower CPUs.


The number of blocks of free space that must be present in the work queue's filesystem for additional mail to be accepted. The default is 100. This parameter provides a way to reserve a portion of disk space that (greedy) sendmail cannot use.


The maximum size of acceptable messages (larger ones are rejected). The first macro sets the limits for the system; the second form specifies a limit for an individual mailer.


These two macros can be used to queue outgoing SMTP mail without further processing. They can be useful for a very busy system with an intermittent ISP connection where just letting the mail accumulate in the queue is too much of a performance hit.


sendmail provides a plethora of configurable timeout parameters for each phase of message processing. In most cases, the defaults are fine, but you may want to decrease some of them on very busy servers . Debugging techniques

There are several distinct sources of information that can be useful fordebugging sendmail configurations and operations. See the book sendmail , by Brian Costales with Eric Allman (O'Reilly & Associates), for full information about all of the debugging features discussed in this section.

The first of these is the facility'slog file. Here are some sample entries (which we have wrapped to fit the page):

Apr 15 12:44:12 kevin sendmail[25907]: f3FGhti25833:  to=chavez@newton.ahania.com, ctladdr=jones (133/78),  delay=00:00:17, xdelay=00:00:00, mailer= esmtp, pri=210301,  relay=newton.ahania.com., dsn=4.0.0,  stat=Deferred: Connection refused by newton.ahania.com. Apr 15 12:49:49 kevin sendmail[25927]: f3FGnmd25925:  to=ahania@newton.ahania.com, ctladdr=root (0/0),  delay=00:00:01, xdelay=00:00:01, mailer=esmtp, pri=30056,  relay=newton.ahania.com. [], dsn=5.1.1,  stat=User unknown Apr 15 16:22:35 kevin sendmail[20388]: f36KK5h20388:  ruleset=check_mail, arg1=<someone@zoas.org>,  relay=IDENT:root@[],  reject=451 4.1.8 <someone@zoas.org>...  Domain of sender address someone@zoas.org does not resolve

All three of these entries clearly indicate specific mail delivery problems. The first entry indicates that host newton is not currently answering SMTP queries, and so this message from local user jones (UID 133, GID 78) has been sent to the work queue. The second entry indicates that the user ahania is unknown on host newton. Finally, the third entry indicates that the domain name in the sender address cannot be resolved via DNS.

You can also use the telnet command to see the results for various senders and recipients by connecting to port 25. In these example, system kevin plays postman for the local domain. In this mode, you enter actualSMTP commands manually.

Here is the initial connection command:

# telnet kevin 25 Trying Connected to kevin. Escape character is `^]'. 220 kevin.ahania.com ESMTP Sendmail 8.11.0/8.11.0; Mon, 16 Apr 2001 11:22:54 -0400 HELO zebra 250 kevin.ahania.com Hello zebra [], pleased to meet you

(Throughout this output, we've wrapped lines as necessary.)

The test session begins by issuing a HELO[25] command, which begins an SMTP session and gives the connecting hostname as its argument. Next, we set up a test mail message by specifying the sender:

[25] The ESMTP version is EHLO.

MAIL From: luc@bad-guys.org 550 5.7.1 luc@bad-guys.org... Access denied

Access from this sender is denied, as specified by the access map. We clear the message state and try another test message:

RSET 250 2.0.0 Reset state MAIL From: bill@zoas.org 250 2.1.0 bill@zoas.org... Sender ok RCPT To: mybadguy 550 5.7.1 mybadguy... Access denied

The failure this time occurs because the recipient is prohibited by the access map from receiving mail. Here is our next attempt:

RSET 250 2.0.0 Reset state MAIL From: bond@mole.bad-guys.org 250 2.1.0 bond@mole.bad-guys.org... Sender ok RCPT To: chavez 250 2.1.5 chavez... Recipient ok DATA 354 Enter mail, end with "." on a line by itself  This is a test message. . 250 2.0.0 f3GFOD728166 Message accepted for delivery QUIT 221 2.0.0 kevin.ahania.com closing connection Connection closed by foreign host.

The message succeeds, and we enter the message text with the SMTP DATA command (although there is no need to do so if testing the addressing is what we are after). After the message is sent, we end the telnet session.

Properly interpreting the output from such test sessions requires a knowledge of the local sendmail configuration. For example, if the local configuration uses the delay_checks feature, then the output of the first attempt would be different:

MAIL From: luc@bad-guys.org 250 2.1.0 luc@bad-guys.org... Sender ok RCPT To: chavez 550 5.7.1 chavez... Access denied

In this case, the prohibited address seems to pass, and recipient chavez seems to be the problem, but this is simply the result of delaying the sender check until after the recipient check; the "Access denied" message appears after the recipient but applies to the sender.

Another useful SMTP command is ETRN, which tells the sendmail daemon to process the queue for the host given as its argument:

ETRN zebra.ahania.com 250 2.0.0 Queuing for node zebra.ahania.com started

Such commands can be used to retrieve messages manually from a remote source such as an ISP.

You can see sendmail perform the SMTP transactions for a message by using its verbose option, -v, as in this example:

# sendmail -v chavez@ahania.com < /dev/null

sendmail's verify mode (-bv) can be used to verify a recipient address, as in this example, which checks the address chavez:

# sendmail -bv chavez chavez@newton.ahania.com... deliverable:  mailer relay, host kevin, user chavez@newton.ahania.com

The output indicates that the address is deliverable: it will be relayed to user chavez on host newton in the local domain via relay system kevin.

Another useful sendmail feature is itsaddress translation mode (-bt). Traditionally, this mode was used to verify and debug the complex address rewriting rules needed in earlier versions of sendmail, and it can still be used for this task. Over the years, however, many other useful internal commands have been added. Several useful ones are illustrated in the following annotated session:

# sendmail -bt  ADDRESS TEST MODE (ruleset 3 NOT automatically invoked) Enter <ruleset> <address> > /mx zebra                                 List MX records for host. getmxrr(zebra) returns 2 value(s):         zebra.ahania.com.         bella.ahania.com.ahania.com. > $m                                        Display value of internal variable. ahania.com > $=w                                       Display member of a class (here, local hosts). [] kevin localhost [] ahania.com > .Cwsalk                                   Add a member to class w (local hosts): salk. > /map virtuser rachel_chavez@ahania.com map_lookup:                                 Translate an address using the virtual user map. virtuser (rachel_chavez@ahania.com)  returns chavez@ahania.com                   This is the translation (local address). > /try smtp chavez                          Show address translation for mailer/recipient. Trying envelope recipient address chavez for mailer smtp canonify         returns: chavez            Output shortened! PseudoToReal     returns: chavez MasqSMTP         returns: chavez < @ LOCAL > EnvToSMTP        returns: chavez < @ kevin . ahania . com . > final            returns: chavez @ kevin . ahania . com Rcode = 0, addr = chavez@kevin.ahania.com > /tryflags S                               The /try command now applies to senders. > /try smtp chavez                          Show address translation for mailer/sender. Trying envelope sender address chavez for mailer smtp ...     Rcode = 0, addr = rachel_chavez@ahania.com > ^D

The two /try subcommands indicate that incoming SMTP-transported mail to recipient chavez goes to chavez on host kevin (where is it relayed to its final destination, as we've seen), and that outgoing SMTP-transported messages from user chavez will have rachel_chavez@ahania.com as the sender (the same information was also given by the earlier /map subcommand).

Other useful subcommands include =M, which lists defined mailers, and -dn.m, which turns on the specified debugging level , a topic to which we now turn.

sendmail also offers an exhaustive debugging mode, selected with the command's -d option. The option takes a debugging level and optional sublevel as its argument the syntax is -dlevel.sublevel where the level indicates the general area of output information and the sublevel indicates the verbosity level (the default for the latter is 1, the least detailed level). Multiple level specifications can be given, separated by commas.

Table 9-5 lists the most useful debugging options. Note that these options appear on normal sendmail commands: most often, sending a test message, but sometimes using -q to process the work queue. In some cases, you need to include -v to make the debugging output appear.

Table 9-5. Useful sendmail debugging options




Show sendmail version, compile flags, and host and domain information.


Also display defined mailers, with flags ("F=").


Show DNS name resolution process.


Trace the delivery process.


Show MX hosts.


Show alias translation, including forwarding.


Trace header generation (including skipped ones).


Display internal macro values (e.g., $k).


Display options as they are set.


Also show each item added to class lists (e.g., class w, which holds local hosts/domains).


Watch queue processing.


Show all file open attempts (useful primarily for file opening-related failures).


Display map lookup operations.

Here is an example displaying the delivery process for local recipient trucks:

# sendmail -v -d11.2 trucks < /dev/null trucks... aliased to trucks@zebra.ahania.com openmailer: procmail -Y -a  -d trucks trucks... Connecting to local... openmailer: openmailer: running as r/euid=371/0, r/egid=0/0 MCI@80efaf0: flags=2<TEMP>,         errno=0, herrno=0, exitstat=0, state=2, pid=13143,         maxsize=0, phase=NULL, mailer=local,         status=NULL, rstatus=NULL,         host=NULL, lastuse=Wed Dec 31 19:00:00 1969 trucks... Sent giveresponse: status=0, dsn=2.0.0, e->e_message=<NULL>

Here we see that the local mailer is procmail, as well as a great deal of information about the process that delivers the mail.

Similarly, the following command shows the alias translation process for user lilith on host dalton (output is shortened):

# /usr/sbin/sendmail -d27 lilith < /dev/null alias(lilith) lilith (, lilith) aliased to ldonna alias(ldonna) ldonna (, ldonna) aliased to lcapri alias(lcapri) lcapri (, lcapri) aliased to lmc2499@dalton.ahania.com forward(lmc2499) alias(lil) lil (, lil) aliased to lil@garden.ahania.com

This output traces a somewhat lengthy chain of aliases that ultimately translates lilith to lil@garden.ahania.com. Macro summary

We will end our consideration of sendmail with Table 9-6, which lists all the macros we have discussed in this section (ordered alphabetically by the name of the most significant component).

Table 9-6. Essential sendmail macros


Meaning and use


Location of aliases file.


Disable aliases file.


Hold (don't transport) mail for expensive mailers.


Default user and group.


Location of smrsh and mail.local.


Send bounced/bogus mail here.

define(`confFORWARD_FILE',`path[:path . . . ]')

Path to search for forward files ($z = ~).

define(`confLDAP_DEFAULT_SPEC',`-h ldap-host -b root-key')

Specify the LDAP server and root key.


Maximum child processes.


Largest acceptable message.


Required filesystem free space.


Messages stay in queue at least this long.


SMTP privacy options.


Queue all incoming mail when load average is above this level.


Refuse connections when load average is above this level.


Pipe mail only to regular files under the specified path.


Location of network services switch file (when not provided by the operating system).


Set timeout length.


Accept only n connections per second.


How to run the local mailer program.


Path to the local mailer program executable.


Send mail to unqualified names here.


Do so even if the MAIL_HUB feature is also used.


How to run mailer for piped messages.


Path to the shell program.


Send local mail to a different host.


How to run the specified mailer's program.


Add flags to the usual set for the specified mailer.


Maximum message size for the specified mailer.


Path to the executable for the specified mailer.


Use this to relay mail for the specified mailer.


Path to procmail.


Send all nonlocal mail to this host.


Make the SMTP mailer "expensive."


Location of statistics file.


Include the ../domain/name.m4 file.


Exclude user from masquerading.

FEATURE(`access_db', `dbtype path')

Use the specified access database.


Masquerade recipients, too.


Add domain to unqualified names.


Allow incoming address entries in the access map.

FEATURE(`delay_checks'[, `friend'])

Reverse the order of access checks. If the argument is included, enable the SPAMFRIEND feature (overrides checks).


Use the Internet blacklist on the specified server.


Use the generics table for hosts in subdomains of any relevant domain.

FEATURE(`genericstable',`dbtype path')

Use the specified generics table map for rewriting outgoing sender addresses.


Use LDAP for mail routing.


Use mail.local as the local mailer for pipes to files and programs (specifying the path to the executable if necessary).


Use procmail as the local mailer.


Masquerade envelope as well as headers.


Use separate MTA and MSA processes.


Defer DNS lookups (usually to mail hub).


Reject UUCP-style mail addresses.


Send all mail to the specified server for processing.


Enable .REDIRECT alias suffix support for users who have left the organization.


Perform relaying for any host in a local domain.


Use smrsh for piped email messages.


Define local hosts and domains in a file.


Specify the path to the file.


Use the virtual user table for hosts in subdomains of any relevant domain.

FEATURE(`virtusertable',`dbtype path')

Use the specified virtual user table map for routing incoming addresses.


Use the generics table for the specified domain or domains listed in the specified file.


Use LDAP routing for the specified domain or the domains listed in the specified file.


Exclude user from the effect of LOCAL_RELAY.

LUSER_RELAY(`host, address, or error')

Destination/error for invalid local addresses.


Make all messages appear to be coming from the specified domain.

MASQUERADE_EXCEPTION(`host or domain')

Don't apply masquerading to this host or domain.


Add/remove the specified flags from the default list for the indicated mailer.


Specify operating system.


Relay messages for the specified domain or the domains listed in the specified file.


Identify the version of the configuration source file.


Use the virtual user table for the specified domain or the domains listed in the specified file.

9.4.2 Postfix

Postfix is an alternative mail transport agent that has received quite a bit of attention in the past couple of years. It is the work of WietseVenema; he wrote the initial version while spending a sabbatical year atIBM's Thomas J. Watson Research Center (where the program was named VMailer). The first production-quality version of Postfix was released in 1999, and it is still a work in progress. The package's home page is http://www.postfix.org.

This discussion is based on thePostfix version current at the time of this writing (20010228 Patchlevel 01). Fortunately for its users but unfortunately for writers, the package is evolving rapidly. This discussion also assumes familiarity with common electronic mail facility concepts. See the earlier discussion of sendmail if you need such information (even if you don't plan on using sendmail).

Postfix was designed as a sendmail replacement with several goals in mind:

High security

Mail processing activities are divided among several distinct processes to insulate them (and there are no parent/child relationships among the various processes). This separation means that there is no direct path from the Internet to the most privileged parts of the facility. In addition, none of the components are SETUID, and most of the pieces can be optionally run in chrooted environment.

Performance under high loads

The documentation states that Postfix can process and deliver over 1,000,000 mail message a day on a desktop PC (configuration not specified). Postfix includes a considerable number of settings that you can use to optimize its functioning in your specific environment.

Easy configuration and administration

Postfix configuration files are simple, and you can get even a fairly complex configuration up and running in a matter of minutes.

Compatibility with existing mail setups

Postfix provides several commands for compatibility with existing habits and scripts, including sendmail, newaliases, and mailq, and it supports the usual mail aliasing and forwarding mechanisms.

Figure 9-6 illustrates the basic Postfix mail transport process. As it indicates, the package's design is modular, separating the various processes from each other and allowing you to easily disable features you don't need to use. In the diagram, each of the rounded rectangles represents a daemon. The shaded rectangles indicate the message-flow path through the facility, and the white rectangles provide specific auxiliary services.

Figure 9-6. Postfix mail processing

The left part of the diagram depicts howPostfix receives incoming mail. Mail created on the local system is handled by a component named sendmail, which sends it to the maildrop queue to await processing. This queue is processed by the pickup daemon, which feeds messages to the cleanup daemon. Incoming mail from outside sources is handled by the smtpd daemon, which similarly sends it to the cleanup daemon.

The cleanup daemon prepares messages for delivery, adding any required headers, optionally transforming addresses, bouncing invalid and acceptable messages, and so on. The rewrite (address rewriting) and bounce daemons aid in these processes. When finished, cleanup sends the message to the incoming queue to await delivery (packaged as a single file).

With the incoming queue, the Postfix delivery process begins. The queue manager process (qmgr) oversees and controls the delivery process. Jobs from the incoming queue are moved to the active queue and then either delivered or sent to the deferred queue. Whenever space opens up in the active queue, one job each is moved from incoming and deferred. Jobs waiting in the deferred queue are scheduled via an "exponential backup" algorithm: each delivery failure results in a longer wait period before the next attempt.

Within the active queue, jobs are selected using a round-robin selection method based on their final destination (to prevent any one site from consuming a disproportionate share of resources). An unreachable destination list is maintained and used to optimize the selection process.

The bounce and resolve daemons aid the queue manager in its work. Ultimately, qmgr hands messages off to a delivery agent. Two of these are illustrated in the figure: local, which places messages in local user mailboxes, and smtp, which typically routes outgoing messages to the Internet.

A few pieces of the package are not shown in the diagram. The most important of these is the masterdaemon, which serves as the supervisor for the entire facility and is the only daemon that is always running. In addition, there are two other mailers: the error mailer for creating and handling mail resulting from errors, and the pipe mailer, which handles mail destined for other transport protocols (currentlyUUCP).

Table 9-7 lists the standard locations for the various Postfixcomponents.

Table 9-7. Postfix components and their locations

Postfix component


Command binaries



Daemon binaries




/usr/lib/postfix (SuSE)

Queue directory



Configuration files



Boot script that starts Postfix


Modify /etc/rc.tcpip




Create /sbin/init.d/postfix[27]


/etc/init.d/postfix provided in RPMsb


Create /etc/init.d/postfixb


Create /sbin/init.d/postfixb

Boot script configuration file


None used


/etc/rc.config.d/postfix.rc.config (SuSE 7)Make sure POSTFIX_CREATECF="no"/etc/sysconfig/postfix (SuSE 8)

syslog mail-facilitymessages


Not configured






/var/log/maillog (Red Hat)/var/log/mail (SuSE)





[26] The FreeBSD ports collection installs Postfix under /usr/local by default.

[27] You must create/verify links to desired S and K files.

In addition to the daemons, the Postfix facility includes several administrative utilities. The most important of these are postfix (used to start and stop the facility and similar actions) and postmap (createsPostfix lookup maps). We will see examples of their use later in this section. Other commands include:


Maintains the aliases database (used by newaliases)


Displays Postfix configuration parameters


Maintains/cleans up Postfix queues


Displays the contents of queue files


Submits mail to the maildrop queue when the queue is not world-writable

postkick, postlock, and postlog

Scriptable interfaces to Postfix features

Finally, Postfix configuration files reside in /etc/postfix. The only exception to this is the aliases file, which is typically located in /etc. Installing Postfix

Installing Postfix is not difficult, but it does require some care. It is possible to use both Postfix and sendmail on the same system, and the procedures for doing so are discussed in the INSTALL file in the Postfix source distribution. In this discussion, we will assume that Postfix is replacing sendmail.

These are the steps required to installPostfix:

  • Back up your current sendmail installation. Make sure that you save all components of the package: binaries, configuration files, and the build directory, map source files, and so on.

  • Make sure that all sendmail queues are empty (flush them if necessary). Then stop the daemon and disable the associated boot script commands/files.

  • Remove all sendmail components except the aliases file and the directory it resides in. Alternatively, you can copy the aliases file to /etc if this is not its standard location (see Table 9-3).

    On systems with a package manager, you can use the appropriate utility to remove the corresponding package(s) (see Section 3.2). On Linux systems, you will need to include the --nodeps option on the rpm -e command to successfully remove the sendmail RPMs. This is safe because the components that other programs depend on are all included with Postfix and so will remain available once it is installed.

  • Install Postfix, either from a binary package (currently, these are available for Linux and FreeBSD) or from source code.

  • Set up the Postfix configuration files. Run the newaliases command to ensure that the alias file's binary database has been generated.

  • Modify or create the required scripts to start Postfix at boot time (see Table 9-7). At a minimum, you'll need to run the postfix start command.

  • Start Postfix, and test the new mail system.

I recommend trying this process for the first time on a test system, rather than your central mail hub! Configuring Postfix

Postfix configuration files reside in the /etc/postfix directory. This location is assumed in the discussion that follows.

Postfix's primary configuration file is main.cf. The Postfix package includes a sample version of main.cf, which describes most of its possible entries. The package also provides a number of smaller sample files illustrating features related to a single purpose (named sample-*.cf).

The main.cf file often begins with entries specifying the package's file and directory locations. These sample entries list the default settings:[28]

[28] If the daemon and command locations are the same, the program_directory entry may be present instead of the two separate ones in this example.

config_directory = /etc/postfix queue_directory = /var/spool/postfix daemon_directory = /usr/libexec/postfix command_directory = /usr/sbin

These entries also illustrate the general entry format: setting = value. When value is a list, the individual items are separated with spaces and optional commas. Entries in the configuration file may continue onto as many lines as needed by beginning the second and subsequent lines with whitespace.

There are several related settings you should be aware of (but for which the default values are often correct):

myhostname = garden.ahania.com mydomain = ahania.com mydestination = $myhostname, localhost.$mydomain

These entries specify the local hostname, the local domain (defaults to the domain part of myhostname), and a list of destinations that should be considered local (the local host), respectively. Note that parameter settings may be used in other entries by preceding the parameter name with a dollar sign.

On SuSE 7 Linux systems, the SuSEconfig automated system configuration facility will write over your main.cf file every time it is run unless you disable this in the /etc/sysconfig/postfix configuration file (or in /etc/rc.config.d/postfix.rc.config on system running SuSE 7):

POSTFIX_CREATECF="no" Notifying the daemon

Whenever you modify the Postfix configuration, you will need to notify the master daemon with this command:

# postfix reload

This command tells the process to reread its configuration files. Client systems

Next, we consider some settings relevant to mailclient systems. For a minimal client configuration, only two additional entries are needed:

relayhost = poffice.ahania.com mynetworks_class = host

The first entry specifies a destination for all nonlocal mail, and the second prevents Postfix from relaying mail for any computer except the local host.

You can also specify a host to handle all unknown local users. This example redirects mail for unknown local users to the same user on system poffice:

luser_relay = $user@poffice.ahania.com

Finally, if you want to define a null client system, which forwards even seemingly local mail to a mail server, define a relayhost and comment out the entries for smtp unix and local unix in the master.cf configuration file. The mail hub

The configuration file on the mail hub typically has some additional entries. Here are some annotated examples:

# add the domain to list of local destinations mydestination = $myhostname,  localhost.$mydomain,  $mydomain # relay mail from these origins: any host in the domain relay_domains = $mydestination, $mydomain

In both cases, mydomain is added to the parameter's default list. In agreement with current security recommendations, relaying is disabled by default in Postfix.

By default, Postfixrelays mail for all hosts in the domains listed in relay_domains. It also relays for hosts from any subnet the local host trusts, as defined by the mynetworks parameter:

mynetworks =,,

In this case, Postfix will trust any host on the 10.0.19 and 10.0.13 subnets, as well as the local host. It is important to specify the setting for mynetworks correctly. It should consist of only trusted local subnets (and not the entire class A, B, or C address).[29] If this parameter is not explicitly defined, the list defaults to the local subnet and

[29] How this list is interpreted is determined by the mynetworks_style parameter, whose default setting is subnet.

Postfix can also automatically rewrite all local sender addresses on outgoing mail to the user@domain form by including these entries:

masquerade_domains = $mydomain masquerade_exceptions = root, postmaster

The first entry sets the domain used for addressmasquerading, and the second entry lists users whose addresses should be excluded from the operation The local delivery agent

By default, Postfix uses its own local daemon for local mail delivery. You can specify a different program with the mailbox_command parameter. For example, this entry makes procmail the local delivery agent:

mailbox_command = /usr/bin/procmail

If you choose to use procmail this way, you must define an alias for root, or mail for the superuser will be lost.

The mail_spool_directory parameter may be used to specify an alternate directory for user mailboxes, as in this example:

mail_spool_directory = /var/newmail Systems with intermittent Internet connections

On mail hubs having only intermittent Internet connections (for example, via a dialup ISP), you can use these entries to accumulate messages between connections:

relayhost = ISP-host          Relay external mail to this host. defer_transports = smtp       Hold outgoing mail transported via SMTP. disable_dns_lookups = yes     Don't perform DNS name resolution tests.

The final entry is necessary to avoid mail being rejected because of name resolution failures. It may be used on any system that lacks external DNS lookup capabilities.

Postfix also includes a feature designed to optimize the process of delivering mail to an intermittently connected site; the daemon that provides this functionality is known as the flush daemon. It is configured via the fast_flush_domains parameter:

fast_flush_domains = $relay_domains

This entry causes fast flush service to be used for all domains for which this server relays mail. When the connection to one of these locations is made,[30] this service causes Postfix to attempt to deliver only the mail destined for that specified destination rather than flushing the entire queue. Obviously, this is much more efficient for both the client and the mail server.

[30] More specifically, when the connecting system issues an SMTP ETRN command (described in the discussion of fetchmail later in thus chapter), Address transformations

Postfix can perform a variety ofaddress-transformation operations on sender and recipient addresses. The simplest of these is to append the local domain to nonqualified outgoing sender addresses, using the myorigin parameter:

myorigin = $mydomain

This entry is often included on both the mail hub and client systems.

Like sendmail, Postfix can use binary lookup tables called maps to perform various sorts of address translations and for other purposes, such as access control. Maps are created from a text source file with the postmap command.

Outgoing mail address mapping e.g., to a standard form like first.last@domain is done via the canonical map, which is specified via this configuration file entry:

canonical_maps = hash:/etc/postfix/canonical.db

This example specifies that the file canonical.db in the Postfix configuration directory should be used as the canonical address map, and that the file is a hash-type database.

Here are some example entries from the map's source file:

chavez     rachel_chavez@ahania.com carr       steve_carr@zoas.org ewood      eve_wood@ahania.com

When this map is used, the sender name in the left column is translated to the form given in the right column.

The following command may be used to create the canonical.db map from a source file named canonical:

# postmap hash:canonical

The hash: prefix specifies the database type (a hash is the default, so the prefix is actually optional here). Use the postconf -m command to list the database types supported on your system; the list of possibilities includes hash, dbm, and btree.

The default canonical map is applied to both senders and recipients within the message and the envelope. Alternatively, you can specify a map used only for sender addresses or recipient addresses via these configuration file parameters:

sender_canonical_maps = hash:/etc/postfix/sender_canonical  recipient_canonical_maps = hash:/etc/postfix/recipient_canonical

These maps are applied before the general canonical map when it is also enabled.



Postfix can similarly perform map lookup-based transformations on incoming recipient addresses using its virtual map (discussed later in this section).

Postfix also offers a map for generating mail messages indicating the new address for departed users. This is called the relocated map. Here are the associated configuration file entries:

relocated_maps = hash:/etc/postfix/relocated local_recipient_maps = $relocated_maps, $alias_maps,                        unix:passwd.byname

The first entry specifies the type and file location for the map file, as usual. The second entry adds the relocated map to the front of the list of items to use for looking up incoming mail recipients. In this case, the relocated map is checked first, followed by the aliases database and the password file.

Entries in the relocated map consist of the local username and the new email address. Here is an example:

erika      eps@essadm.com Virtual domains

Postfix can be configured to support virtual domains, using its virtual map facility. Here is an exampleconfiguration file entry enabling this feature using the virtual.db map file:

virtual_maps = hash:/etc/postfix/virtual

The map file performs two functions: enabling virtual domain support for listed domains and specifying incoming recipient address translations. Here are some example entries from the virtual map source file (assume the local domain is ahania.com):

zoas.org                   whatever essadm.com                 whatever    webmaster@essadm.com       czarina@lecarre.ahania.com smith@zoas.org             hayes@oldwest.ahania.com jones@zoas.org             kidcurry@oldwest.ahania.com @zoas.org                  @ahania.com rachel_chavez@ahania.com   chavez@dalton.ahania.com

The first two entries enable virtual hosting for the zoas.org and essadm.com domains; the text in the second column for such entries is ignored. The third entry redirects mail for webmaster@essadm.com to a specific local user. The fourth and fifth entries specify local recipients for users smith and jones at zoas.org. The sixth entry, for @zoas.org, will be used for any other recipient in that domain; in this case, mail will be redirected to the same user in ahania.com, the local domain. The final entry illustrates that this map may also be used for general incoming recipient address translation unrelated to virtual hosting, in this case translating the address rachel_chavez@ahania.com to the appropriate, fully qualified recipient address.

As usual, the virtual map database is created with postmap. For example, this command would create the hash-type database virtual.db from the source file virtual:

# postmap virtual

Postfix handles virtual domains somewhat differently than sendmail users may be used to. In particular, usernames that exist in the local domain are not recognized in virtual domains by default. In other words, if chavez is a user in ahania.com, essadm.com is a hosted virtual domain, and there is no virtual map entry for chavez@essadm.com, mail to that address will bounce. In contrast, sendmail-style virtual domains attempt to deliver such mail to chavez@ahania.com (bouncing it when no identically named user exists).

You can implement sendmail-stylevirtual domains by making two modifications to the Postfix configuration:

  • Remove the virtual domain entry from the virtual map.

  • Add the virtual domain name to the mydestination list. LDAP lookups

Postfix can also be configured to useLDAP for local recipient address translations. This capability must be selected at compile time. You can determine whether your installation supports it via the postconf -m command.

Here are some example configuration file entries:

alias_maps = hash:/etc/aliases, ldap:ldapsource ldapaliases_server_host = orwell.ahania.com ldapaliases_search_base = dc=ahania,dc=com ldapaliases_query_filter = (mailacceptinggeneralid=%s) ldapaliases_result_attribute = maildrop

The first entry adds LDAP the list of items to use for address translation, checking it after the aliases file. The remaining entries specify the LDAP server to connect to, the root of the tree to search, the query that should be run, and the record field to return to Postfix (respectively). In this case, the LDAP database is queried by searching the mailacceptinggeneralid field for the address; the contents of the maildrop field from matching record(s) are used as the new address.

Here is a sample LDAP entry using these default attributes:

dn: cn=some-object, dc=ahania, dc=com ... mailacceptinggeneralid: help@zoas.org mailacceptinggeneralid: oliviav@essadm.com maildrop:               vargas@dalton.ahania.com

This example illustrates the use of multiple key fields, any of which will translate to the local mail address vargas@dalton.ahania.com. Of course, you can use any object type, key field, and return field that makes sense in the context of the local LDAP schema. Access control and spam suppression

Postfix includes an access control facility that can be used for both security-related and spam-suppression purposes. Postfix allows you to specify incoming mail restrictions based on the connecting system (the "client"), the sender, and/or the recipient, via the smtpd_client_restrictions, smtpd_sender_restrictions, and smtpd_recipient_restrictions configuration file entries, respectively. It also provides the smtpd_helo_restrictions and smtpd_etrn_restrictions parameters for specifying restrictions for hosts attempting to use the SMTP HELO/EHLO commands (to initiate an SMTP session) and the SMTP ETRN command (to request that pending mail be transferred).

The setting for any of these parameters is a list of items, which can include Postfix keywords and/or a type:file specification for an external map. The most important keywords are listed in Table 9-8.

Table 9-8. Postfix access control keywords




Reject if DNS cannot resolve the connecting system's/sender's/ recipient's address (respectively).


Reject if the connecting system's/ sender's/recipient's hostname is not fully qualified.


Accept if the connecting system is a member of a trusted network


Accept if the client system is a member of one of the domains listed in relay_domains.


Reject/accept if the destination address is in relay_domains or my_destinations.


Reject blacklisted sites, as defined by the maps_rbl_domains parameter.


Prevent unverified SMTP pipelining (exploited by some bulk mailers).


Reject SMTP HELO/EHLO commands from client systems whose hostnames cannot be resolved.


Reject if the hostname in the SMPT HELO/EHLO command uses invalid syntax.

check_client_access type:mapcheck_sender_access type:mapcheck_recipient_access type:mapcheck_helo_access type:map

Determine access by looking up the specified item in the indicated access map.[31]


Permit the access (unconditionally).


Reject the access (unconditionally).

[31] The keyword is optional when used in the corresponding restrictions parameter. Thus, check_sender_access is optional in smtpd_sender_restrictions, and a bare type:file list item will interpreted as the sender access map.

Here are some examples, which also introduce a couple more related parameters:

smtpd_sender_restrictions: hash:/etc/postfix/senders,     reject_non_fqdn_sender, reject_unknown_client    reject_unknown_sender_domain, reject_unauth_destination,     reject_unauth_pipelining, reject_maps_rbl  maps_rbl_domains = blackholes.mail-abuse.org, rbl.maps.vix.com smtpd_recipient_restrictions: hash:/etc/postfix/no-mail, permit smtpd_helo_restrictions = reject_maps_rbl, reject_invalid_hostname smtpd_helo_required = yes smtpd_etrn_restrictions = permit_mynetworks

This configuration is fairly restrictive. Messages from unknown clients and unknown senders are rejected, as are ones from or sent by blacklisted domains (lines 1-3), defined as the two sites in the second entry (line 4). Likewise, messages to nonlocal destinations are also rejected (line 2). Senders (line 1) and recipients (line 6) are checked against access maps. Recipients are accepted provided they pass all the restrictions in the access map (line 5). Blacklisted sites are not allowed to connect to this server, and connections using malformed SMTP HELO/EHLO commands are also rejected (line 6), although this command is required for a successful connection (line 7). Finally, only systems in the local networks may use the SMTP ETRN command to retrieve their mail (line 8).

The recipients entry illustrates the use of the generic permit keyword, which simply makes the entry's effect evident; in other words, all lines end with an implicit permit unless you include an explicit reject. When access is determined, list items are applied in order.

Access map source files consist of user and/or domain names, followed by the desired action. At the moment, actions consist of rejection, specifiable in two forms (as illustrated in the examples below), acceptance, and any of the restriction keywords. Here is an example that might be part of a sender access map:

bad-guys.org                   REJECT evil-ones.net                  550 No spam allowed. zoas.org                       OK mybadguy@                      permit_mynetworks

These entries reject all mail from anyone at bad-guys.org and evil-ones.net (using the indicated error code and message in the latter case). Mail from zoas.org is accepted. When a user named mybadguy sends a message, it is rejected unless the client system is a member of one of the local networks.

You create the binary form of the map using the postmap command as usual:

# cd /etc/postfix; postmap senders

Access control entries allowing access from specific sites and/or senders cannot protect against addressing spoofing.

Postfix also allows you to define "restriction classes": named groups of keywords that can be used within access maps. In fact, if you want to use a reference to an access map within an access map entry, you must do so via a restriction class,[32] as in this example:

[32] This is required because the corresponding map files need to be open already when the access map is processed, which is one of the effects of defining the restriction class in the main Postfix configuration file.

main.cf: smtpd_restriction_classes = no_unknown, check_sender, accept_iffy no_unknown = reject_unknown_sender_domain, reject_unknown_client,               reject_non_fqdn_sender, reject_non_fqdn_hostname check_sender =  check_sender_access hash:/etc/postfix/senders accept_iffy = check_sender_access hash:/etc/postfix/iffy smtpd_recipient_restrictions = /etc/postfix/our-mail /etc/postfix/senders: bad-guys.org                   REJECT /etc/postfix/iffy: mole@bad-guys.org              OK weasel@bad-guys.org            OK ferret@bad-guys.org            OK bad-guys.org                   REJECT    /etc/postfix/our-mail: chavez@ahania.com              OK ahania.com                     no_unknown essadm.org                     check_sender zoas.org                       accept_iffy

This configuration defines three restriction classes: non_unknown, which rejects mail from unknown sources; check_sender, which looks up the sender in an access map named senders; and accept_iffy, which looks up the sender in a different access map, iffy. In addition, recipients are checked against the our-mail access map. This setup allows recipients in different local domains to have different checks applied to their incoming mail.

These restriction classes are actually applied in the recipients map, our-mail. Messages to chavez are accepted without further checking. Messages to other users in the ahania.com domain are checked for unknown client and sender addresses before being accepted for delivery. Messages to users in the essadm.org domain are rejected if they come from a sender at bad-guys.org (via the sole entry in the senders map). Finally, messages to users in zoas.org are usually rejected if they come from someone at bad-guys.org, but they are accepted from the three bad-guy.org users listed in the iffy map.

Postfix can also accept or reject mail based on the contents of either the message headers or body contents, using these configuration file entries:

header_checks = regexp:/etc/postfix/header_checks body_checks = regexp:/etc/postfix/body_checks

These examples define the pathname for the map used to specify the desired header/body checks. They use a map type of regexp, indicating that the specified file is a regular expression map, another of the supported map types (which may be used for any map file throughout the Postfix facility). The map source file looks like this:

/viagra/                     REJECT /^Subject: [-A-Z0-9! ]*$/    REJECT /^To: .*@bad-guys.org/       REJECT /[%!@].*[%!@]/               550 Sender-specified routing rejected

This map, designed to be used to check mail message headers, rejects mail that contains "viagra" anywhere in the mail headers, has a subject that contains only uppercase letters, numbers, dashes, exclamation points and spaces, is addressed to any user @garden.ahania.com, or contains explicit routing within the address. In the latter case, the message is restricted and results in the specified error code and message text.

As usual, the binary map file must be created from this source file using the postmap command.

In addition to this regular expression-based filtering, Postfix also includes full content-filtering hooks (à la procmail). See the FILTER_README file in the top-level directory of the Postfix source tree for details. Postfix security

Postfix is designed to be very secure. In this section, we'll cover various odds and ends related to Postfix security, beginning with these two configuration file parameters:

mail_owner = postfix default_privs = nobody

These entries specify the owner of the Postfix processes and queue directory and the user identity that Postfix assumes when delivering messages to a file or program and there is no associated user context (respectively). The postfix user account should have a unique UID and group (typically also named postfix).

As with any administrative facility, you will need to ensure that the Postfix files and directories have the proper ownerships and permissions. The postfix check command can be used to examine the installation for these problems, and it should be run periodically.

Warning: Programs that "fix" sendmail permissions

The Postfix file and directory permissions can get changed onLinux systems by the automated system configuration utilities: From the Postfix FAQ:

Unfortunately, some Linux systems have a helpful utility called linuxconf that automatically `fixes' file permissions to what they are supposed to be for Sendmail's sendmail command. Even when you reset the SETUID bit on the Postfix sendmail executable file, linuxconf will happily turn it on again for you.

There is at present no way to prevent linuxconf from doing this.

On some older SuSE systems, the SuSEconfig facility does the same thing. However, you can override this by adding the following line to /etc/permissions.local:

/usr/sbin/sendmail root.root 755

You will also want to check these entries in /etc/sysconfig/security (or in /etc/rc.config on pre-Version 8 systems):

CHECK_PERMISSIONS=set                  Fix incorrect permissions
PERMISSION_SECURITY="secure local"     Permission spec. file list

Permission correction happens only when the first entry has the value set. The second entry indicates which files contain the correct file ownerships and permissions; the list of items is used as extensions to files of the form /etc/permissions.*. Note also that if your system is set to easy rather than secure, you should consider changing it (see Chapter 7).

As I've noted before, Postfix gives you two configuration options with respect to the maildrop queue: the queue directory can be world-writable (via chmod o+t), or it can be only group-writable. In the latter case, Postfix uses a SETGID program for local mail submission (owned by the postfix user and group). The non-SETGID configuration is the default. To switch to the second option, you must:

  • Assign the proper ownership and protection to the maildrop queue directory.

  • Run the INSTALL.sh script (located in the root of the Postfix source tree), specifying this group at the SETGID privilege prompt.

Finally, many administrators choose to run Postfix in a chrooted environment (with /var/spool/postfix serving as the root directory). This is easy to configure, but it is not the default. The examples/chroot-setup subdirectory of the source tree contains example scripts showing the required steps for converting to such a setup for various operating systems. For example, here are the files for a FreeBSD and an AIX system:

FreeBSD: umask 022 mkdir /var/spool/postfix/etc chmod 755 /var/spool/postfix/etc cd /etc  cp host.conf localtime services resolv.conf /var/spool/postfix/etc AIX: umask 022 mkdir /var/spool/postfix/etc chmod 755 /var/spool/postfix/etc for file in /etc/environment /etc/netsvc.conf /etc/localtime do    test -e $file && cp $file /var/spool/postfix/etc done cp /etc/services /etc/resolv.conf /var/spool/postfix/etc mkdir /var/spool/postfix/dev chmod 755 /var/spool/postfix/dev mknod /var/spool/postfix/dev/null c 2 2 chmod 666 /var/spool/postfix/dev/null

FreeBSD requires only that a few files from /etc exist in the chroot jail. The script for AIX conditionally copies a list of files (i.e., if they exist), copies two files that it knows it will need, and creates a /dev/null device in the jail (using the mknod command). Note that both scripts are careful to set the umask appropriately and to set the ownership and permissions for any subdirectories they create. Monitoring and performance

As with any system facility, Postfix requires some amount of ongoingmonitoring and occasional maintenance. In this section, we look at some of the features related to monitoring and performance optimization.

We've seen the postfix command several times already. Three of its most important options are start and stop, which start and stop the facility, and flush, which may be used to force processing of the mail queue. These commands may be used to take care of common facility-wide failures and backlogs.

Postfix also allows you to configure what sorts of errors should be reported to postmaster:

notify_classes = list

The item list consists of one or more keywords: bounce (copies message), 2bounce (for double bounces), delay (sends headers only), policy (UCE restriction rejections), protocol (protocol errors), resource (shortages/problems), and software (problems causing failed deliveries). The default list is resource, software.

Postfix also provides many resource usage and performance-related settings that can be used to optimize its configuration on your system. The most important of these are listed in Table 9-9.

Table 9-9. Some Postfix resource usage and performance parameters




Number of parallel deliveries to the same destination. The default of 10 can be lowered if some site(s) are a bottleneck for delivering other mail.


Maximum number of recipients per message delivery (more are batched). The default is 50.


Amount of time to wait after the first failed delivery attempt. The default is 1000s (the units must be specified), about 17 minutes.


Maximum amount of time to wait after a failed delivery attempt (waiting time increases with each failure to this limit). The default is 4000s (about 67 minutes).


Second between qmgr attempts to process the queue. The default is 1000s.


Maximum size in bytes of the body text that is included in a bounced message. The default is 50000.


Maximum number of child processes for each Postfix subsystem.


Maximum size of a message in bytes. The default is 1,024,000 (a pseudo MB).


Maximum number of entries in the active queue.


Amount of free space that must remain available in the filesystem containing the queue directories (the default is 0). Debugging

There are three main sources oftroubleshooting information available with Postfix: syslog entries, verbose command modes, and system call tracing. We will consider each of these in turn.

Normally, Postfix sends status and error messages to the syslog facility. You can configure the minimum severity level for which you want messages reported in the usual way, using the /etc/syslog.conf configuration file.

You can enable verboselogging for the various Postfix daemons by adding the -v option to the command corresponding specifications in /etc/postfix/master.cf (in the final column). For example, this modification enables verbose mode for the smtpd daemon:

smtp   inet   n   -   n   -   -   smtpd -v

The final source of debugging information comes from system call tracing. Be aware, however, that this data is extremely verbose and often obscure. You can enable tracing in this way:

  • Add -D to smtpd line in master.cf.

  • Configure the debugger_command in the main.cf configuration file:

    debugger_command =     PATH=/usr/bin:/usr/X11/bin    strace -p $process_id -o /tmp/pfx_$process_id & sleep 5

    This entry is from a Linux system. strace may need to be replaced by trace, ktrace, truss, or some other command on your system.

Once the daemon is invoked, system call tracing output goes to the specified file in the /tmp directory. You can examine this file as it runs and use the same command to stop the trace operation when appropriate.

It is also possible to run Postfix daemons under a symbolic debugger. See the documentation for details about how to accomplish this.

Essential System Administration
Essential System Administration, Third Edition
ISBN: 0596003439
EAN: 2147483647
Year: 2002
Pages: 162

Similar book on Amazon

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net