The sendmail configuration file is sendmail.cf. It contains most of the sendmail configuration, including the information required to route mail between the user mail programs and the mail delivery programs. The sendmail.cf file has three main functions:
 The default location for the configuration file prior to sendmail 8.11 was the /etc directory. Now the default is /etc/mail, but the file is often placed in other directories, such as /usr/lib.
It defines the sendmail environment.
It rewrites addresses into the appropriate syntax for the receiving mailer.
It maps addresses into the instructions necessary to deliver the mail.
Several commands are necessary to perform all of these functions. Macro definitions and option commands define the environment. Rewrite rules rewrite email addresses. Mailer definitions define the instructions necessary to deliver the mail. The terse syntax of these commands makes most system administrators reluctant to read a sendmail.cf file, let alone write one! Fortunately, you can avoid writing your own sendmail.cf file, as we'll see next.
There is never any good reason to write a sendmail.cf file from scratch. Sample configuration files are delivered with most systems' software. Some system administrators use the sendmail.cf configuration file that comes with the system and make small modifications to it to handle site-specific configuration requirements. We cover this approach to sendmail configuration later in this chapter.
Most system administrators prefer to use the m4 source files to build a sendmail.cf file. Building the configuration with m4 is recommended by the sendmail developers and is the easiest way to build and maintain a configuration. Some systems, however, do not ship with the m4 source files, and even when m4 source files come with a system, they are adequate only if used with the sendmail executable that comes with that system. If you update sendmail, use the m4 source files that are compatible with the updated version of sendmail. If you want to use m4 or the latest version of sendmail, download the sendmail source code distribution from http://www.sendmail.org. See Appendix E for an example of installing the sendmail distribution.
The sendmail cf/cf directory contains several sample configuration files. Several of these are generic files preconfigured for different operating systems. The cf/cf directory in the sendmail.8.11.3 directory contains generic configurations for BSD, Solaris, SunOS, HP Unix, Ultrix, OSF1, and Next Step. The directory also contains a few prototype files designed to be easily modified and used for other operating systems. We will modify the tcpproto.mc file, which is for systems that have direct TCP/IP network connections and no direct UUCP connections, to run on our Linux system.
The prototype files that come with the sendmail tar are not "ready to run." They must be edited and then processed by the m4 macro processor to produce the actual configuration files. For example, the tcpproto.mc file contains the following macros:
divert(0)dnl VERSIONID(`$Id: ch10.xml,v 1.7 2002/09/04 21:08:29 chodacki Exp $') OSTYPE(`unknown') FEATURE(`nouucp', `reject') MAILER(`local') MAILER(`smtp')
These macros are not sendmail commands; they are input for the m4 macro processor. The few lines shown above are the active lines in the tcpproto.mc file. They are preceded by a section of comments, not shown here, that is discarded by m4 because it follows a divert(-1) command, which diverts the output to the "bit bucket." This section of the file begins with a divert(0) command, which means these commands should be processed and that the results should be directed to standard output.
The dnl command that appears at the end of the divert(0) line is used to prevent unwanted lines from appearing in the output file. dnl deletes everything up to the next newline. It affects the appearance, but not the function, of the output file. dnl can appear at the end of any macro command. It can also be used at the beginning of a line. When it is, the line is treated as a comment.
The VERSIONID macro is used for version control. Usually the value passed in the macro call is a version number in RCS (Release Control System) or SCCS (Source Code Control System) format. This macro is optional, and we can just ignore it.
The OSTYPE macro defines operating system-specific information for the configuration. The cf/ostype directory contains almost 50 predefined operating system macro files. The OSTYPE macro is required and the value passed in the OSTYPE macro call must match the name of one of the files in the directory. Examples of values are bsd4.4, solaris8, and linux.
The FEATURE macro defines optional features to be included in the sendmail.cf file. The nouucp feature in the example shown says that UUCP addresses are not used on this system. The argument reject says that local addresses that use the UUCP bang syntax (i.e., contain an ! in the local part) will be rejected. Recall that in the previous section we identified tcpproto.mc as the prototype file for systems that have no UUCP connections. Another prototype file would have different FEATURE values.
The prototype file ends with the mailer macros. These must be the last macros in the input file. The example shown above specifies the local mailer macro and the SMTP mailer macro.
The MAILER(local) macro includes the local mailer that delivers local mail between users of the system and the prog mailer that sends mail files to programs running on the system. All the generic macro configuration files include the MAILER(local) macro because the local and prog mailers provide essential local mail delivery services.
The MAILER(smtp) macro includes all of the mailers needed to send SMTP mail over a TCP/IP network. The mailers included in this set are:
This mailer can handle traditional 7-bit ASCII SMTP mail. It is outmoded because most modern mail networks handle a variety of data types.
This mailer supports Extended SMTP (ESMTP). It understands the ESMTP protocol extensions and it can deal with the complex message bodies and enhanced data types of MIME mail. This is the default mailer used for SMTP mail.
This mailer sends 8-bit data to the remote server, even if the remote server does not indicate that it can support 8-bit data. Normally, a server that supports 8-bit data also supports ESMTP and thus can advertise its support for 8-bit data in the response to the EHLO command. (See Chapter 3 for a description of the SMTP protocol and the EHLO command.) It is possible, however, to have a connection to a remote server that can support 8-bit data but does not support ESMTP. In that rare circumstance, this mailer is available for use.
This mailer allows the destination system to retrieve mail queued on the server. Normally, the source system sends mail to the destination in what might be called a "push" model, where the source pushes mail out to the destination. On demand, SMTP allows the destination to "pull" mail down from the mail server when it is ready to receive the mail. This mailer implements the ETRN command that permits on-demand delivery. (The ETRN protocol command is described in RFC 1985.)
This mailer is used when SMTP mail must be relayed through another mail server. Several different mail relay hosts can be defined.
Every server that is connected to or communicates with the Internet uses the MAILER(smtp) set of mailers, and most systems on isolated networks use these mailers because they use TCP/IP on their enterprise network. Despite the fact that the vast majority of sendmail systems require these mailers, installing them is not the default. To support SMTP mail, you must have the MAILER(smtp) macro in your configuration, which is why it is included in the prototype file.
In addition to these two important sets of mailers, there are nine other sets of mailers available with the MAILER command, all of which are covered in Appendix E. Most of them are of very little interest for an average configuration. The two sets of mailers included in the tcpproto.mc configuration are the only ones that most administrators ever use.
To create a sample sendmail.cf from the tcpproto.mc prototype file, copy the prototype file to a work file. Edit the work file to change the OSTYPE line from unknown to the correct value for your operating system, e.g., solaris8 or linux. In the example we use sed to change unknown to linux. We store the result in a file we call linux.mc:
# sed 's/unknown/linux/' < tcpproto.mc > linux.mc
Then enter the m4 command:
# m4 ../m4/cf.m4 linux.mc > sendmail.cf
The sendmail.cf file output by the m4 command is in the correct format to be read by the sendmail program. With the exception of how UUCP addresses are handled, the output file produced above is similar to the sample generic-linux.cf configuration file delivered with the sendmail distribution.
OSTYPE is not the only thing in the macro file that can be modified to create a custom configuration. There are a large number of configuration options, all of which are explained in Appendix E. As an example we modify a few options to create a custom configuration that converts user@host email addresses originating from our computer into firstname.lastname@domain. To do this, we create two new configuration files: a macro file with specific values for the domain that we name wrotethebook.com.m4, and a modified macro control file, linux.mc, that calls the new wrotethebook.com.m4 file.
We create the new macro file wrotethebook.com.m4 and place it in the cf/domain directory. The new file contains the following:
$ cat domain/wrotethebook.com.m4 MASQUERADE_AS(wrotethebook.com) FEATURE(masquerade_envelope) FEATURE(genericstable)
These lines say that we want to hide the real hostname and display the name wrotethebook.com in its place in outbound email addresses. Also, we want to do this on "envelope" addresses as well as message header addresses. The first two lines handle the conversion of the host part of the outbound email address. The last line says that we will use the generic address conversion database, which converts login usernames to any value we wish to convert the user part of the outbound address. We must build the database by creating a text file with the data we want and processing that file through the makemap command that comes with sendmail.
The format of the database can be very simple:
dan Dan.Scribner tyler Tyler.McCafferty pat Pat.Stover willy Bill.Wright craig Craig.Hunt
Each line in the file has two fields: the first field is the key, which is the login name, and the second field is the user's real first and last names separated by a dot. Fields are separated by spaces. Using this database, a query for dan will return the value Dan.Scribner. A small database such as this one can be easily built by hand. On a system with a large number of existing user accounts, you may want to automate this process by extracting the user's login name and first and last names from the /etc/passwd file. The gcos field of the /etc/passwd file often contains the user's real name.
 See Appendix E for a sample script that builds the realnames database from /etc/passwd.
Once the data is in a text file, convert it to a database with the makemap command. The makemap command is included in the sendmail distribution. The syntax of the makemap command is:
makemap type name
makemap reads the standard input and writes the database out to a file it creates using the value provided by name as the filename. The type field identifies the database type. The most commonly supported database types for sendmail are dbm, btree, and hash. All of these types can be made with the makemap command.
 On Solaris systems, NIS maps and NIS+ tables are built with standard commands that come with the operating system. The syntax for using those maps within sendmail is different (see Table 10-3).
Assume that the data shown above has been put in a file named realnames. The following command converts that file to a database:
# makemap hash genericstable < realnames
makemap reads the text file and produces a database file called genericstable. The database maps login names to real names, e.g., the key willy returns the value Bill.Wright.
Now that we have created the database, we create a new sendmail configuration file to use it. All of the m4 macros related to using the database are in the wrotethebook.com.m4 file. We need to include that file in the configuration. To do that, add a DOMAIN(wrotethebook.com) line to the macro control file (linux.mc) and then process the linux.mc through m4. The following grep command shows what the macros in the file look like after the change:
# grep '^[A-Z]' linux.mc VERSIONID(`$Id: ch10.xml,v 1.7 2002/09/04 21:08:29 chodacki Exp $') OSTYPE(`linux') DOMAIN(`wrotethebook.com') FEATURE(`nouucp', `reject') MAILER(`local') MAILER(`smtp') # m4 ../m4/cf.m4 linux.mc > sendmail.cf
Use a prototype mc file as the starting point of your configuration if you install sendmail from the tar file. To use the latest version of sendmail you must build a compatible sendmail.cf file using the m4 macros. Don't attempt to use an old sendmail.cf file with a new version of sendmail; you'll just cause yourself grief. As you can see from the sample above, m4 configuration files are very short and can be constructed from only a few macros. Use m4 to build a fresh configuration every time you upgrade sendmail.
Conversely, you should not use a sendmail.cf file created from the prototype files found in the sendmail distribution with an old version of sendmail. Features in these files require that you run a compatible version of sendmail, which means it is necessary to recompile sendmail to use the new configuration file. This is not something every system administrator will choose to do, because some systems don't have the correct libraries; others don't even have a C compiler! If you choose not to recompile sendmail, you can use the sample sendmail.cf file provided with your system as a starting point. However, if you have major changes planned for your configuration, it is probably easier to recompile sendmail and build a new configuration with m4 than it is to make major changes directly to the sendmail.cf.
 See Appendix E for information about compiling sendmail.
In the next part of this chapter, we use one of the sample sendmail.cf files provided with Linux. The specific file we start with is generic-linux.cf found in the cf/cf directory of the sendmail distribution. All of the things we discuss in the remainder of the chapter apply equally well to sendmail.cf files that are produced by m4. The structure of a sendmail.cf file, the commands that it contains, and the tools used to debug it are universal.
Most sendmail.cf files have more or less the same structure because most are built from the standard m4 macros. Therefore, the files provided with your system probably are similar to the ones used in our examples. Some systems use a different structure, but the functions of the sections described here will be found somewhere in most sendmail.cf files.
The Linux file, generic-linux.cf, is our example of sendmail.cf file structure. The section labels from the sample file are used here to provide an overview of the sendmail.cf structure. These sections will be described in greater detail when we modify a sample configuration. The sections are:
Defines the information that is specific to the individual host. In the generic-linux.cf file, Local Information defines the hostname, the names of any mail relay hosts, and the mail domain. It also contains the name that sendmail uses to identify itself when it returns error messages, the message that sendmail displays during an SMTP login, and the version number of the sendmail.cf file. (Increase the version number each time you modify the configuration.) This section is usually customized during configuration.
Defines the sendmail options. This section usually requires no modifications.
Defines the various message precedence values used by sendmail. This section is not modified.
Defines the users who are trusted to override the sender address when they are sending mail. This section is not modified. Adding users to this list is a potential security problem.
Defines the format of the headers that sendmail inserts into mail. This section is not modified.
Defines the rules used to rewrite mail addresses. Rewriting Rules contains the general rules called by sendmail or other rewrite rules. This section is not modified during the initial sendmail configuration. Rewrite rules are usually modified only to correct a problem or to add a new service.
Defines the instructions used by sendmail to invoke the mail delivery programs. The specific rewrite rules associated with each individual mailer are also defined in this section. The mailer definitions are usually not modified. However, the rewrite rules associated with the mailers are sometimes modified to correct a problem or to add a new service.
The section labels in the sample file delivered with your system may be different from these. However, the structure of your sample file is probably similar to the structure discussed above in these ways:
The information that is customized for each host is probably at the beginning of the file.
Similar types of commands (option commands, header commands, etc.) are usually grouped together.
The bulk of the file consists of rewrite rules.
The last part of the file probably contains mailer definitions intermixed with the rewrite rules that are associated with the individual mailers.
Look at the comments in your sendmail.cf file. Sometimes these comments provide valuable insight into the file structure and the things that are necessary to configure a system.
It's important to realize how little of sendmail.cf needs to be modified for a typical system. If you pick the right sample file to work from, you may need to modify only a few lines in the first section. From this perspective, sendmail configuration appears to be a trivial task. So why are system administrators intimidated by it? It is largely because of the difficult syntax of the sendmail.cf configuration language.