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 sendmail.cf
file. sendmail uses sendmail.cf 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, reseau.nl,
we are part of another domain, xs4all.nl. xs4all.nl
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 xs4all.nl 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.
Conclusion
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.
|