Cover V04, I03
Figure 1
Figure 2
Figure 3
Figure 4
Figure 5
Figure 6
Listing 1
Listing 2
Listing 3
Sidebar 1
Sidebar 2


Managing sendmail in a Mixed UUCP/PPP Environment

Arthur Donkers

Doing business over the Internet is common practice today, and electronic mail is the most common communication method. It is thus very important that email arrive at the destination quickly and reliably, by whatever means possible. This article describes a setup for an electronic mail system that automatically chooses between SMTP or UUCP delivery, depending on which is available at the time of sending.

Why Mix UUCP and Dialup PPP?

Why bother setting up sendmail for a mixed UUCP and dialup PPP environment? Configuring sendmail is difficult as it is, even with a fixed delivery policy. There are a few reasons for this self-inflicted torture.

My organization, Le Reseau, operates a dialup PPP connection to the Internet. This connection is used for downloading software via ftp and accessing the booming number of Web services. Apart from this, users may also send mail directly to the addressee by using SMTP. SMTP reduces the number of intermediate hops a message must go through before reaching its destination; in fact, most of the time the message goes directly to the destination via SMTP. Direct delivery is important to message privacy. We do a lot of business via the Internet, so a lot of confidential information is exchanged through email, such as credit card numbers. A direct, interactive connection to the destination meansthat this confidential information can be encrypted. There is no store-and-forward of the data or the crypting keys, so there is less chance of losing your confidential information.

Because our dialup PPP connection is established by hand, we have to have some sort of fallback delivery for normal mail when our Internet connection is down. We chose UUCP for this because it batches the mail and sends it out at regular intervals. Combining these techniques lets us send mail through SMTP when the connection is up, and through UUCP when the connection is down. This is all done transparently to the users.

Another reason for this combined setup is the emerging use of portable computers. By equipping a portable computer with some version of UNIX, we enable people to travel and carry their work with them. Travelers are not connected to any network, but with UUCP, they may still send electronic mail. UUCP batches and stores their mail until they can dial out and send the batch. Once back in the office, travelers can connect the portable to the network and send all their mail automatically using SMTP.

The Current Setup

The situation in the Netherlands regarding service providers is comparable to that in the United States. A number of providers handle the routing of TCP/IP packets and store-and-forward mail and news for you. Most of them offer some sort of dialup SLIP or PPP, but some also offer a UUCP service.

At our end, we established a mail/news gateway using software available on the net. We implemented our gateway using Linux, sendmail, Taylor UUCP, and other publicly available packages. This setup's advantage is source code availability. Whenever you need to adapt something, you can do it yourself. Bug fixes are also available quickly through the vast Internet community. Our experiences with this kind of software are very positive.

However the techniques described in this article are not limited to net-available, source code software. Anyone running UNIX with some sort of UUCP and dialup Internet connection can apply these techniques. The key factor in this setup is sendmail 8.6.9, which can be built for many UNIX platforms. By applying the different changes for sendmail, you can also use this setup on SunOS, System V, and other UNIX flavors.

How Does sendmail Work?

As explained in the sendmail sidebar, sendmail does not do any delivering. That task is delegated to one of the available delivery agents. sendmail determines what agent to select and calls it with the appropriate interface. It does this both for local delivery of incoming mail, and for remote delivery of outgoing mail.

sendmail's input derives from a user entering mail on the local system or from the outside world. A user runs a special mail program, such as ELM, to enter the mail message. The mail program supplies the necessary message headers without any intervention from the user other than entering the message body and the recipient's name or address. After completing the message, the mailer offers it to sendmail for further processing.

Remote mail is handled very much the same way. For instance, if a message is offered through SMTP, it is sent to the sendmail daemon running on the system. Through a special dialog the message is offered to the daemon, which then processes it. With UUCP there is no dialog, but the complete message is offered to sendmail through an intermediate mailer. This transforms the message into a digestible form.

Delivery Agents: SMTP vs UUCP

The bottom part of sendmail is the set of available delivery agents. sendmail itself contains a delivery agent for sending mail through SMTP. This delivery agent sends mail across TCP/IP networks. This agent is also used to receive mail when sendmail runs as a daemon. When running as a daemon, sendmail listens on TCP port 25 for incoming mail. If a foreign host wants to send mail, it connects to our machine's port 25. As soon as a connection is established, a dialog starts to exchange mail. sendmail uses this dialog to send outgoing mail, so sendmail must contain this delivery agent.

UUCP's delivery agent, uux, is not built-in: UUCP must call it with the appropriate parameters. uux invokes the rmail program, which communicates UUCP and sendmail.

SMTP's delivery agents deliver mail directly to the destination or to the destination's mail handling host. UUCP's delivery agent uses a store-and-forward mechanism to send the mail. First the mail is batched on the local host. At regular intervals, determined by the system administrator on the local host, the mail is sent to an upstream host, which might use SMTP or UUCP to forward the message. This method repeats until the message reaches its destination.

Specifying a delivery agent can be done from the master configuration file, which is the input for the M4 macro processor. Several mailers have been predefined and can be selected with the MAILER() function. You can also define your own delivery agent. You must then define the different fields of the mailer specification yourself. The example in Figure 1 uses the predefined SMTP and UUCP mailers. For local delivery the procmail system is used; this allows automatic mail processing depending on the contents of the message.

After processing the master configuration file, M4 generates the file. sendmail uses to specify the configuration. In Figure 2, the selected local delivery agent is procmail. The program delivery agent (Mprog) is a bonus generated by the MAILER(local) function. sendmail uses this mailer when it sends mail to a program. A well-known example would be delivering mail to a pipe specified in the .forward file in the user's $HOME directory.

Each mailer specification contains a number of fields. The M field specifies the name of the delivery agent. Each configuration should at least contain a local and a prog delivery agent. The P field specifies the path to the agent's executable. [IPC] refers to the built-in SMTP mailer. The F field specifies the capabilities of the agent, and sendmail uses this field to determine what the agent can do. The S= field defines the rule set used to rewrite the sender's address so the agent can handle it. The R= field defines the rule set used to rewrite the recipient's address.

These delivery agents are generic and should not be changed. The decision on how to deliver a message happens during another step of the delivery process.

Rule Sets, or, Which Way to Go?

A sendmail configuration file consists of many rule sets and subsets, but an intimate knowledge of every rule set is not necessary. The most important ones are rule sets 0, 1, 2, 3, and 4. These sets are interrelated, as shown in Figure 3.

Rule set 0 selects a delivery agent based on the recipient's address. This rule set produces three pieces of information:

  • The delivery agent's name.

  • The receiving host's name.

  • The recipient's name.

    The delivery agent's name must be one of the agents specified in the Magent rules (M field). The receiving host's name does not necessarily have to match the name of the host to which the message is sent. In UUCP, for instance, the receiving host's name is not the same as the name of the UUCP hub which will store-and-forward the message. This is the rule set I adapt to suit my site's needs.

    Rule sets 1, 2, and 4 rewrite the sender's and recipient's address so it can be handled by sendmail and the delivery agent. All addresses are pre-cooked by rule set 3. Rule 3 splits addresses into digestible chunks, strips all comments from the address specification, and puts the different parts in the proper place for processing by rules 1 and 2.

    Customizing Rule 0

    Figure 4 contains the customized settings for rule set 0. This customization is divided into two parts. The first one expands the local part of the rule set. This part is typically used for anything related to local delivery. The first three rules come directly from the sendmail configuration. They primarily detect special addressing types related to the local domain.

    I added a new fourth rule because, apart from our local domain,, we are part of another domain, is the domainname of one of our providers, and at the same time it is an alias of its dial-in host. We have therefore added the name of the host to our /etc/host table. That way we can always access it by this name, despite the state of our nameserver. The complication this presents is that sendmail is always able to resolve the name xs4all and will decide to contact this host using SMTP. This is often not the case, so mail to this host could get stuck in the mail queue for a long time. This fourth rule forces all mail going to the xs4all domain to instead go through our UUCP channel, thus guaranteeing its timely delivery. Using this method might not be ideal, but at least it always delivers the mail with a maximum delay of one hour, our UUCP polling interval.

    The second part of the customization applies to remote network delivery. It rewrites remote addresses and decides how to contact the remote host. All hosts on the local network are handled by the first two rules. If the address contains our local domain name, mail is delivered through SMTP to the host on the network. The same goes for mail addressed to the domain itself, which is sent to our mail gateway, also through SMTP.

    When mail is addressed to a nonlocal host, the last four rules activate. The decision whether we can contact this remote host or not is taken by the name resolver. Whenever we can resolve the MX (Mail eXchange) name for the destination, we decide it is also possible to contact the host through SMTP. The destination's MX name might be the destination itself, or the address of a host that handles all SMTP traffic for the destination. This setup has its implications for our nameserver and dialup connection.

    Exactly how do we use the nameserver for this? The trick lies in the third rule:

    R$* << @ $* $~P >> $*     $: $1 << @ $[ $2 $3 $: $2
    $3.NOTFOUND $] >> $4

    We try to make the destination host canonical through the special symbol $~P. This queries the nameserver. If the nameserver can resolve the hostname, $~P will be replaced by the $2 $3 expression before the $: within the [] expression on the right-hand side of the rule. If the nameserver cannot resolve the name, $~P will be replaced by the expression after the $: within the [] expression, which appends the nonexisting domain NOTFOUND to the address. To prevent this rule from looping, the $: that begins the right-hand side evaluates the rule only once.

    The next rule in this part is used as a safety net. It handles all mail addressed to unknown hosts within the local domain. This mail is rerouted to the local delivery agent, preventing any improperly addressed mail from getting lost.

    The last two rules select the appropriate delivery agent, based on the presence of the NOTFOUND pseudodomain. If NOTFOUND is present, the UUCP delivery agent is chosen and the mail is forwarded to the upstream UUCP relay. If the pseudodomain is not present, mail gets directly sent to the destination's MX address.

    Relationship between BIND and sendmail

    Using the nameserver to decide whether we can contact the destination directly or not has some implications for the nameserver's setup. A number of problems can occur and, according to Murphy, definitely will occur.

    The nameserver caches any information it has retrieved. This means that whenever mail is sent to an address still in the cache, sendmail would decide that it should use the SMTP delivery whether or not our Internet link is up. The nameserver supplies the address from the cache despite the state of the Internet link. If the link is down, sendmail times out on the delivery, and the mail sticks in the mail queue until the queue is rerun when the Internet link is up.

    A second problem relates to the nameserver query itself. If the link is down and the destination address is not present in the nameserver cache, a query for this address times out after about 30 seconds. While querying the nameserver, sendmail would not be able do anything else. This causes problems when we want to serve our mailing list. The mail gateway also serves our Dutch Linux mailing list, a list of about 100 addresses. If each addressee on the mailing list takes 30 seconds to process, processing the complete list takes almost one hour. To handle this, it would be necessary to reconfigure the nameserver so that it quickly times out when the Internet link is down and takes its normal time to resolve whenever the link is up.

    The first problem, starting and stopping the nameserver whenever the link goes up or down, is the more difficult. The second problem can be solved by using two different nameserver configurations: one for an established Internet link, and one for a standalone situation. This technique is described in the sidebar on BIND.

    But how can we start and stop the nameserver? This is where PPP comes to the rescue.

    Establishing and Tearing Down the Internet Link

    Our Internet link is based on PPP. We use an implementation of PPP that lets us execute a special script whenever the link is established. When we tear down the link, we execute another script. We use these two special scripts to reconfigure the nameserver.

    The first script, pppconnect (Listing 1), uses the pppchat program to talk to the modem. This pppchat program is very similar to the expect-send strings used to configure UUCP. A pppchat script for communication with the modem appears in Figure 6.

    The IP addresses of the local and remote hosts are dynamic and determined while establishing the connection. The script sets the default route to the remote host so all Internet traffic is sent to this host, then stores a few more options for the PPP link in the default options file (Figure 5). These options tell PPP that the modem should be locked to prevent UUCP from dialing out, and to use the hardware handshake signals.

    To establish the connection, I call pppconnect manually. pppconnect puts itself in the background and calls pppchat. Once the connection is established, the PPP daemon calls the ip-up script (Listing 2). This script is executed whenever the IP part of the PPP link is started.

    The lines related to mirroring are of no importance to this article, but the line

    /etc/ns start net

    is. This line restarts the nameserver in Internet mode (see the sidebar on BIND).

    To tear down the Internet link, the script sends a HUP signal to the PPP daemon. The daemon then executes the ip-down script (Listing 3) and hangs up the modem.

    The line

    /etc/ns start minimal

    restarts the nameserver in local (minimal) mode. Any query to the nameserver for a remote host quickly times out without delaying mailing list processing.

    Further Improvements

    Of course, there is room for further improvement. The question is whether a dial-on-demand PPP would solve the problem. Currently there is an experimental implementation of a dial-on-demand daemon for Linux. This daemon can be configured to dial the provider whenever a connection to the Internet is desired. The problem with this is that any nameserver query will then result in a call to the provider. This can mean that the connection is alive during the greater part of the day, resulting in a huge phone bill.

    Another improvement might be the requeueing of mail. If many messages are stored in the UUCP mail queue, it might be best to send these when the Internet connection is established.

    A last improvement might be another configuration of the nameserver. Restarting the nameserver each time a connection is established or torn down is not a very elegant solution.


    This setup works! For more than half a year, all mail has been sent either by SMTP or UUCP. By tweaking the sendmail configuration file, you can change the behavior of this program to suit your needs. Good documentation is essential in this process.

    About the Author

    Arthur Donkers graduated from the Delft Universiy of Technology with a degree in Electrical Engineering, with a major in Computer Architecture. He has since worked for a number of major software houses in the Netherlands, specializing in projects relating to data communications, especially the integration of multi-vendor network systems. The last four years he worked as an independent consultant for his own company, Le Reseau (The Network). He sees electronic communication as a means of connecting people quickly and reliably across hardware and software boundaries and, most important of all, across social boundaries.