Living without Windows!

by Jos Visser

Part 15: I am too smart (for my own good)

Go back to the index

Introduction

My life is a rather mobile one and, therefore, so is my laptop's. I move from network to network, plugging Jadzia (my laptop) in whatever local network I can find, and, when none is available, I use my PCMCIA modem to dial-in somewhere. To support my promiscuous networking habits I have written a number of scripts which I can use to configure my system for the network I connect to. So, when I hookup to a LAN somewhere I have to configure the local networking parameters only once and from then on I can use the "net" script to reconfigure my system. E.g.:
jadzia:/root# net flips
Setting networking parameters for Philips Nijmegen...
jadzia:/root# _
Ever since I took the time to investigate DHCP I can even connect to networks that use DHCP to dynamically assign networking parameters. The "net" script takes care of a lot of things: it sets the local IP address, the subnet mask, changes the routing table for any default gateway and even reconfigures the DNS resolver.

E-mail

Regarding electronic mail I use Netscape Messenger to send and read e-mail. Messenger can be configured for multiple e-mail servers (using the IMAP protocol), but when sending e-mail only one server can be specified. Messenger forwards all e-mail to that specific server (using SMTP) and then expects that server to take care of handling the message). Needless to say, depending on wherever I am at a particular moment, Messenger's outgoing e-mail server needs to be a different one.

For a while I just used the Edit->Preferences menu to change the outgoing e-mail server whenever it was appropriate. However, that started to annoy me after a while. Something smarter was called for.

The solution is of course obvious: Jadzia runs Linux and is therefore excellently equiped to be an e-mail server. It has run Sendmail ever since I installed it, but I did not take any special care configuring it. I decided to implement a scheme whereby Messenger would forward all e-mail to my local Sendmail, and then have Sendmail take care of things.

Setmailrelay

Sendmail is a truly excellent subsystem for handling e-mail. Just about anything you could possibly want can be configured through its "sendmail.cf" configuration file. Unfortunately, you need multiple years of experience in declarative programming before you can even hope to understand how Sendmail understands the statements in that configuration file. Fortunately however, the default configuration file that is shipped with most Sendmail installations is an all-singing-all-dancing version that has Sendmail do whatever most people want it to do.

In my case I wanted something different. Normally Sendmail is prepared to take full responsibility for the handling and delivery of e-mail messages. This means that it looks at any message's recipients, contacts each of their mail servers directly and sends them a copy of the message. This was not acceptable in my situation: when one of the recipient's mail servers was not available, the message would stay queued up on my system until it could finally be delivered. The problem with that is that I (and therefore  my laptop as well) might be somewhere else completely by that time. I would like Sendmail to forward messages to another mail server that would then become responsible for handling these messages.

The default Sendmail configuration file understands that concept; it is called the "Smart Relay Host". By defining the $S macro in the configuration file all outgoing e-mail will automatically be forwarded to the relay host:

# "Smart" relay host (may be null)
DSsmtp.nl.net
This example would tell Sendmail to forward all outgoing e-mail to "smtp.nl.net".

In itself this does not change the problem: instead of reconfiguring Messenger all the time I now have to reconfigure Sendmail all the time to tell it where to forward e-mail to. Surely, Sendmail's relay host is dependent of wherever I plug Jadzia into the network?

Rightly so; but, to counter this problem I created a script called "setmailrelay" that changes the Sendmail configuration file and restarts it:

jadzia:/root# setmailrelay smtp.nl.net
Setting mail relay host (smtp.nl.net)
jadzia:/root# _
The script uses "sed" to fill in the new mail relay server into a template Sendmail configuration file and write out the result to a new "/etc/sendmail.cf". Then, it restarts Sendmail with its new configuration. I extended the "net" script with appropriate calls to "setmailrelay" depending on the network I connected to or dialed into.

However, I was left with one problem; what to do when I was disconnected from any network and still wanted to send e-mail? I decided to give "setmailrelay" a special case: "setmailrelay none" would just terminate Sendmail and not restart it.

I get a better idea

As you might imagine, this was not very satisfying. If Messenger is sending all e-mail to the local Sendmail, and no Sendmail is running this just means that Messenger can not send e-mail! So much for offline processing. The Netscape solution for this is that you choose "File->Send Later" and then, once you are connected, use "File->Send Unsent Messages" to empty Messenger's out queue. Not very elegant, and not very handy either!

After some thinking (not too much :-), I decided to manipulate another Sendmail facility: the "DeliveryMode" option. With this option you can specify how Sendmail delivers messages. Normally it is set to "background" meaning that Sendmail forks itself into the background and takes care of message sending from there. Another option is "deferred": Sendmil just queues the message and proceeds. The message stays in the queue until a queue run is performed. The time intervals between the mail queue runs is specified using the "-q" option.

My solution would be as follows: when specifying a mail relay of "none", I would define $S as "none" and "DeliveryMode" as "deferred". Additionally I would not specify a queue run interval so that messages would stay in the queue until either Sendmail was restarted with another configuration (e.g. because I connected to a network) or I ran the queue manually (using "sendmail -v -q").

Ok, so said, so done.

I put theory to practice

Last week I thought a course in Brussels. From my hotel room, I dialed into the office network twice a day to download my e-mail. Hotel telephone prices being what they are, I immediately broke the connection as soon as possible and started reading and answering e-mail offline. Needless to say, "setmailrelay none" was effective so I could send e-mail only for it to be queued up by my local sendmail.

Once I had gone through all my e-mail I dialed into the Internet again and manually told Sendmail to run the queue: "sendmail -v -q". To my surprise, this went all rather quickly, but hey, This Is Unix, and I have a fast modem.

Things go horribly wrong!

However, the next day I started to feel a bit uneasy. Did things really go this fast? Hmmm, I decided to investigate..... I scan Sendmail log files, look in mail boxes, Hmmm.... Then it dawned on me that everyting had gone HORRIBLY WRONG!

Whenever I told Sendmail to process the queue, it would forward all the mail to the queue to the specified mail relay host. The "setmailrelay" script however generated a "DSnone", so Sendmail would try to relay all mail to "none.osp.nl". This server does not exist! When confronted with such a situation Sendmail tries to return the e-mail to its sender (josv@osp.nl). However, this also called for sending mail to an external mail server (gatekeeper.osp.nl), through relay "none.osp.nl". As you can image, by then Sendmail gives up completely and sends the e-mail to the local "postmaster", in my case "root@jadzia.osp.nl".

After this realisation I looked into root's mailbox, and there was all my outgoing e-mail of the last two days! Augmented with all kinds of Sendmail errors:

The original message was received at Wed, 21 Apr 1999 20:37:36 +0200
from josv@localhost [127.0.0.1]

   ----- The following addresses had permanent fatal errors -----
<wout@osp.nl>

   ----- Transcript of session follows -----
550 <wout@osp.nl>... Host unknown (Name server: none: host not found)

Reporting-MTA: dns; jadzia.osp.nl
Arrival-Date: Wed, 21 Apr 1999 20:37:36 +0200

Final-Recipient: RFC822; wout@osp.nl
Action: failed
Status: 5.1.2
Remote-MTA: DNS; none
Last-Attempt-Date: Thu, 22 Apr 1999 07:37:50 +0200

...........

What to do now?

First I thanked the Supreme Being that Sendmail is smart enough to try and keep as much of the e-mail as possible and that it does such a suprising job of trying to make sense of even the most confusing situation. First of all I corrected the "setmailrelay" script to generate a meaningful mail relay (gatekeeper.osp.nl) whenever "setmailrelay none" was executed. Then, I tried to salvage as much of the e-mail as possible. I made some half-hearted attempts to re-send all e-mail based on Sendmail's errors. Then I remembered that the Netscape Messenger saves all e-mail in the "Sent" folder and that you can re-send messages from there. So, some people got their e-mail belated, and then twice last Wednesday and Thursday....

Hopefully everyting is correct now! That's what you get for trying to be too smart for your own good!

Appendix: the setmailrelay script

Here is the "setmailrelay" script that I now use:
#!/bin/bash

RELAY="$1"

echo "Setting mail relay host ($RELAY)"

if [ -f /var/run/sendmail.pid ]; then
        pid=$(head -1 /var/run/sendmail.pid)
        kill $pid
        sleep 5
fi

if [ "$RELAY" = "none" ]; then
        MODE=deferred
        QUEUE_RUN=""
        RELAY="gatekeeper.osp.nl"
else
        MODE=background
        QUEUE_RUN="-q5m"
fi

sed     -e "s/__relay/$RELAY/" \
        -e "s/__deliverymode/$MODE/" \
        /etc/sendmail.cf.template >/etc/sendmail.cf

sendmail -bd $QUEUE_RUN
sleep 5
 

 


Last change: 25th april 1999 by me