Accepting Mail for Other Hosts

Mail addressed to one host can be routed to another host for a variety of reasons: forwarding, relaying, mailertable entries, and so on. One common reason for routing mail in this manner is because DNS says to do so. A system sending mail routes the mail based on information obtained from DNS. Mail is addressed to some hostname. The remote system takes that hostname and asks DNS if it has mail exchange (MX) records for that host. If no MX record is found for a given host, the address record of the host is obtained from DNS, and the mail is sent directly to the host. If DNS returns MX records, the remote system sends the mail to the system with the lowest preference number listed on the MX record.

Regardless of why the mail is routed to your mail host, the sendmail system must be configured to accept the mail or it will generate a Relaying denied error. This is an interesting error because the remote system is not necessarily trying to relay mail; it may be attempting to deliver the mail to the mail exchanger as directed by DNS. However, sendmail only accepts inbound mail for delivery that is addressed to the local system. All other mail is relayed. For local delivery, sendmail accepts mail that is addressed to another host only if it finds the name of that host in class $=w. Class $=w is an array that contains all of the names that sendmail considers valid for local mail delivery.

There are three ways to load names into class $=w. The recommended method for solving this problem is to use the use_cw_file feature. Two alternatives are also discussed: placing local hostnames directly in sendmail.cf itself or using the bestmx_is_local feature.

Create an /etc/mail/local-host-names file. Put into that file the hostnames and domain names for which sendmail should accept mail for local delivery. Enter the names with one hostname or domain name per line.

Add the use_cw_file feature to the sendmail configuration to make use of the newly created local-host-names file. Here are sample lines that could be added to the configuration, if it does not already contain the use_cw_file feature:

dnl Load class $=w with other names for the local hostFEATURE(`use_cw_file')

Finally, rebuild the sendmail.cf file, copy the new sendmail.cf file to /etc/mail, and restart sendmail

Using the use_cw_file feature

The use_cw_file feature directs sendmail to load the /etc/mail/local-host-names file into class $=w. It does this by placing the following F command in the sendmail.cf file

Fw/etc/mail/local-host-names

Once the use_cw_file feature is added to the configuration, sendmail expects to find the local-host-names file and displays a nonfatal error message when it doesn’t. It is possible to configure sendmail to treat local-host-names as an optional file by placing the following define in the configuration before the use_cw_file feature:

define(`confCW_FILE', `-o /etc/mail/local-host-names')

The -o flag makes the file optional, which stops sendmail from complaining if the file is not found. The confCW_FILE define can also be used to set a different pathname for the local-host-names file, if you decide to place the file in another directory or give it another name. Don’t change the pathname unless you absolutely must. Use default pathnames for files whenever possible; it makes it easier for others to find these files when maintaining your system.

Frankly, there is little reason to make the local-host-names file optional; in fact, making it optional can hide real errors, such as an error opening the file. If you’re not ready to add hostnames to the file, simply create an empty file. But, in all likelihood, if you add the use_cw_file feature to your configuration, it is because you have hostnames that you want to add to the local-host-names file. As an example, let’s create a local-host-names file for our sample system that contains the following lines:

wrotethebook.com

horseshoe.wrotethebook.com

After creating the local-host-names file and building the new sendmail.cf file, use the -bt option to test the new configuration. First, run sendmail -bt to examine the contents of the class $=w array:

# sendmail -bt -C./sendmail.cf

ADDRESS TEST MODE (ruleset 3 NOT automatically invoked)

Enter <ruleset> <address>

> $=w

chef

localhost.localdomain

localhost

[192.168.0.8]

[127.0.0.1]

[chef.wrotethebook.com]

horseshoe.wrotethebook.com

wrotethebook.com

chef.wrotethebook.com

> /quit

This test shows that the horseshoe.wrotethebook.com and the wrotethebook.com values stored in the local-host-names file are added to class $=w. It also shows that several other values are stored in this array. These values are all of the hostnames, hostname aliases, and IP addresses assigned to this host that sendmail discovered by probing the various network interfaces. The hostnames associated with the interface addresses are obtained from both the /etc/hosts file and from DNS

define(`confDONT_PROBE_INTERFACES', `true')

Mail addressed to any hostname defined in class $=w is delivered by the local mailer. The $=w output shown above tells us that this system will deliver mail addressed to chef, localhost, horseshoe, or wrotethebook.com using the local mailer. A second test, this time using sendmail -bv, verifies this:

# hostname

chef

# sendmail -bv alana@crab.wrotethebook.com

alana@crab.wrotethebook.com... deliverable: mailer esmtp, host crab.wrotethebook.com.

, user alana@crab.wrotethebook.com

# sendmail -bv payton@horseshoe.wrotethebook.com

payton@horseshoe.wrotethebook.com... deliverable: mailer local, user payton

The hostname command shows that the local host is chef to illustrate that none of this mail is actually addressed to the local host. The sendmail -bv command verifies a delivery address and shows the mailer that will be used to deliver the mail. The first -bv test shows that mail addresses to crab will be delivered over the network using the esmtp mailer. This is just what you would expect because crab is an external system. Yet the second -bv test shows that mail addressed to horseshoe, another external system, will be delivered using the local mailer. Mail addressed to horseshoe is treated as if it were addressed to chef. This is because horseshoe is defined in the local-host-names file, and the configuration uses the use_cw_file feature to add hostnames from that file to class $=w. This test shows that the system is properly configured to handle mail addressed to horseshoe as if it were local mail.

Using sendmail.cf directly

The use_cw_file feature works well, and it is the recommended solution for this problem, but there are alternative solutions. For example, placing local hostnames in sendmail.cf itself or using the bestmx_is_local feature. The sample local-host-names file created earlier in this section contained only two lines. Such a small number of names could be placed directly inside of sendmail.cf by using the following two lines instead of the use_cw_file feature:

LOCAL_DOMAIN('wrotethebook.com')

LOCAL_DOMAIN('horseshoe.wrotethebook.com')

This alternative solution, however, is more difficult to maintain as the list of clients grows. Every time a LOCAL_DOMAIN macro is added to the configuration, the sendmail.cf file must be rebuilt, tested, and moved to the /etc/mail directory. When the local-host-names file is used, there is no need to rebuild sendmail.cf just because the local-host-names file has been edited.

Using the bestmx_is_local feature

The bestmx_is_local feature works well if the only reason that hostnames are being added to the local-host-names file is because the local host is a mail exchanger. Mail addressed to any system that lists the local host as its preferred mail exchanger is accepted as local mail when the bestmx_is_local feature is used. To use this approach, put the following line in the configuration:

FEATURE(`bestmx_is_local', `wrotethebook.com')

The great advantage of the bestmx_is_local feature is that it is easy—there is no local-host-names file to maintain. However, that simplicity is also a disadvantage because control over what mail is accepted as local by your system is given to someone else—the domain administrator. The potential problems caused by this lack of control are limited by using an optional domain list in the sample command. Adding the `wrotethebook.com‘ argument to the bestmx_is_local feature means that only MX records from that domain are accepted as proof that a host is a valid client. If the optional domain list is not specified for the bestmx_is_local feature, any domain in the world can control the mail your system accepts as local simply by putting in an MX record that points to your host, which creates an opportunity for abuse.

Another potential problem with the bestmx_is_local solution is that it increases the processing overhead for each piece of mail. This would not be a problem for our small sample system, but it could be a problem for any system that deals with a high volume of mail.

One other limitation of the bestmx_is_local solution is that it depends completely on MX records. bestmx_is_local works for a mail exchanger because all of the hostnames it handles have MX records; however, it is possible to have other reasons to accept mail as local mail. The local-host-names file can store any hostnames that you wish; it is not limited to hosts that define your system as their mail exchanger. local-host-names is fast, flexible, and completely under your control. For those reasons, we chose the use_cw_file feature as the preferred solution for this problem.