13.7 The User's ~/.forward File
The sendmail
program allows each user to have a :include:-style
list to customize the receipt of personal mail. That file (actually a
possible sequence of files) is defined by the
ForwardPath option (ForwardPath).
Traditionally, that file is located in a user's home
directory.
We use the C-shell notation ~ to indicate user
home directories, so we will compactly refer to this file as
~/.forward.
If a recipient address selects a delivery agent with the
F=w flag set (F=w), that
address is considered the address of a local user whose
~/.forward file can be processed. If the user
part of that address contains a backslash,
sendmail disallows further processing, and the
message is handed to the local delivery
agent's P= program for delivery
to the mail-spooling directory. If a backslash is absent,
sendmail tries to read that
user's ~/.forward file.
If all the .forward files listed in the
ForwardPath option (ForwardPath)
cannot be read, their absence is silently ignored. This is how
sendmail behaves when those files
don't exist. Users often choose not to have
~/.forward files. But problems can arise when
users' home directories are remotely mounted. If the
user's home directory is temporarily absent (as it
would be if an NFS server is down), or if a user has no home
directory, sendmail
syslog(3)s the following error message and falls
back to the other directories in its ForwardPath
option:
forward: no home
If there are no further directories to fall back to, the missing home
is considered a temporary error, and the message is queued for a
later delivery attempt.
V8 sendmail temporarily transforms itself into
the user before trying to read the
~/.forward file. This is done so that reads will
work across NFS. If sendmail cannot read the
~/.forward file (because it is not allowed to),
it silently ignores that file.
Before reading the ~/.forward file,
sendmail checks to see whether it is a
"safe" file—one that is owned
by the user or root, has the read permission bit
set for the owner, and is writable only by root
or the owner. If the ~/.forward file is not
safe, sendmail logs a warning and ignores the
file.
If sendmail can find and read the
~/.forward file and if that file is safe,
sendmail opens the file for reading and gathers
a list of recipients from it. Internally, the
~/.forward file is exactly the same as a
:include: file. Each line of text in it can
contain one or more recipient addresses. Recipient addresses can be
email addresses, the names of files onto which the message should be
appended, the names of programs through which to pipe the message, or
:include: files.
Beginning with V8 sendmail,
~/.forward files can contain comments (lines
that begin with a # character). Other versions of
sendmail treat comment lines as addresses and
bounce mail that is seemingly addressed to #.
13.7.1 Unscrambling Forwards
The traditional use of the ~/.forward file, as
its name implies, is to forward mail to another site. Unfortunately,
as users move from machine to machine, they can leave behind a series
of ~/.forward files, each of which points to the
next machine in a chain. As machine names change and as old machines
are retired, the links in this chain can be broken. One common
consequence is a bounced mail message ("host
unknown") with a dozen or so
Received: (Received:) header
lines.
As the mail administrator, you should beware of the
~/.forward files of users at your site. If any
contain offsite addresses, you should periodically use the SMTP
expn command to examine them. For example,
consider a local user whose ~/.forward contains
the following line:
user@remote.domain
This causes all local mail for the user to be forwarded to the host
remote.domain for delivery there. The validity of
that address can be checked with nslookup and
telnet(1) at port 25 and the SMTP
expn command:
% ns -q=mx remote.domain
Address: 123.45.67.89
remote.domain preference = 0, mail exchanger = mail.remote.domain
remote.domain preference = 10, mail exchanger = mx.another.domain
% telnet mail.remote.domain 25
Trying 123.45.123.45 ...
Connected to mail.remote.domain.
Escape character is '^]'.
220 mail.remote.domain Sendmail 8.6.13/8.6.13 ready at Sat, 18 Aug 2001 09:48:09 -
0600 (MDT)
220 ESMTP spoken here
expn user
250 <user@another.site>
quit
221 remote.domain closing connection
Connection closed by foreign host.
%
This shows that the user is known at remote.site
but also shows that mail will be forwarded (yet again) from there to
another.site. By repeating this process, you will
eventually find the site at which the user's mail
will be delivered. Depending on your site's
policies, you can either correct the user's
~/.forward file or have the user correct it. It
should contain the address of the host where that
user's mail will ultimately be delivered.
But beware that the world of email is becoming less friendly for the
well-intentioned administrator. Because EXPN can be used to harvest
addresses for spam lists, it is more and more frequently turned off.
If you connect to a site with EXPN turned off, you will see an error
such as the following, instead of the forwarding address you need:
502 5.7.0 Sorry, we do not allow this operation
If EXPN fails, try finger(1) in its place, which
also might fail (another illustration of the harm caused by spam
email).
13.7.2 Forwarding Loops
Because ~/.forward
files are under user control, the administrator occasionally needs to
break loops caused by improper use of those files. To illustrate,
consider a user who wishes to have mail delivered on two different
machines (call them machines A and B). On machine A the user creates
a ~/.forward file such as this:
\user, user@B
Then, on machine B the user creates this
~/.forward file:
\user, user@A
The intention is that the backslashed name (\user)
will cause local delivery and the second address in each will forward
a copy of the message to the other machine. Unfortunately, this
causes mail to go back and forth between the two machines (delivering
and forwarding at each) until the mail is finally bounced with the
error message "too many hops."
On the machine that the administrator controls, a fix to this looping
is to temporarily edit the aliases database and
insert an alias for the offending user, such as this:
user: \user
This causes mail for user to be delivered locally
and that user's ~/.forward file
to be ignored. After the user has corrected the offending
~/.forward files, this alias can be removed.
13.7.3 Appending to Files
The ~/.forward file
can contain the names of files onto which mail is to be appended.
Such filenames must begin with a slash character that cannot be
quoted. For example, if a user wishes to keep a backup copy of
incoming mail:
\user
/home/user/mail/in.backup
the first line (\user) tells
sendmail to deliver directly to the
user's mail spool file using the
local delivery agent. The second line tells
sendmail to append a copy of the mail message to
the file specified (in.backup).
Note that, prior to V8, sendmail did no file
locking, so writing files by way of the
~/.forward file was not recommended. Beginning
with V8, however, sendmail locks those files
during writing, so such use of the ~/.forward
file is now OK.
If the SafeFileEnvironment option (SafeFileEnvironment) is set, the user should be advised to specify
the path of that safe directory:
\user
/arch/bob.backup here /arch was specified by the SafeFileEnvironment option
When the SafeFileEnvironment option is used, the
cooperation of the system administration might be needed if users are
to have the capability of saving mail to files via the
~/.forward file.
13.7.4 Piping Through Programs
The ~/.forward file can contain the names of
programs to
run. A program name is indicated by a leading pipe
(|) character, which
might or might not be quoted (Section 12.2.3). For
example, a user might be away on a trip and want mail to be handled
by the vacation(1) program:
\user, "|/usr/ucb/vacation user"
Recall that prefixing a local address with a backslash tells
sendmail to skip additional alias
transformations. For \user this causes
sendmail to deliver the message (via the
local delivery agent) directly to the
user's spool mail box.
The quotes around the vacation program are
necessary to prevent the program and its single argument
(user) from being viewed as two separate
addresses. The vacation program is run with the
command-line argument user, and the mail message
is given to it via its standard input.
Beginning with V8 sendmail, a user must have a
valid shell to run programs from the ~/.forward
file and to write files via the ~/.forward file.
See _PATH... for a description of this process
and for methods to circumvent it at the system level.
Because sendmail sorts all addresses and deletes
duplicates before delivering to any of them, it is important that
programs in ~/.forward files be unique. Consider
a program that doesn't take an argument and suppose
that two users both specified that program in their
~/.forward files:
user 1 \user1, "|/bin/notify"
user 2 \user2, "|/bin/notify"
Prior to V8 sendmail, when mail was sent to both
user1 and user2, the address
/bin/notify appeared twice in the list of
addresses. The sendmail program eliminated what
seems to be a duplicate, and one of the two users did not
have the program run.
If a program requires no arguments (as opposed
to ignoring them), the ~/.forward program
specifications can be made unique by including a shell comment:
user 1 \user1, "|/bin/notify #user1"
user 2 \user2, "|/bin/notify #user2"
13.7.5 Specialty Programs for Use with ~/.forward
Rather than expecting users to write home-grown programs for use in
~/.forward files,
offer them any or all of the publicly available alternatives. The
most common are listed below.
13.7.5.1 The procmail program
The
procmail(1) program, originally written by
Stephen R. van den Berg and currently maintained by Philip Guenther,
is purported to be the most reliable of the delivery programs. It can
sort incoming mail into separate folders and files, run programs,
preprocess mail (filtering out unwanted mail), and selectively
forward mail elsewhere. It can function as a substitute for the
local delivery agent or handle mail delivery for
the individual user. The procmail program (as
recommended in its manual) is typically used in the
~/.forward file like this:
"|exec /usr/local/bin/procmail #user"
Note that procmail does not accept a username as
a command-line argument. Because of this, a dummy shell comment is
needed for pre-V8 versions of sendmail to make
the address unique. The procmail program is
available from http://www.procmail.org/.
13.7.5.2 The slocal program
The
slocal program, distributed with the
mh distribution, is useful for sorting incoming
mail into separate files and folders. It can be used with both
Unix-style mail files and with mh-style mail
directory folders. The slocal program (as
recommended in its manual) is typically used in the
~/.forward file like this:
"| /usr/local/lib/mh/slocal -user user"
The disposition of mail is controlled using a companion file called
~/.maildelivery.
13.7.6 Force Requeue on Error
Normally, a program in the
user's ~/.forward file is
executed with the Bourne shell:
Mprog, P=/bin/sh, F=lsDFMeuP, S=10, R=20, A=sh -c $u
the Bourne shell
One drawback to using the Bourne shell to run programs is that it
exits with a value of 1 when the program cannot be executed. When
sendmail sees the exit value 1, it bounces the
mail message.
There will be times when bouncing a mail message because the program
could not execute is not desirable. For example, consider the
following ~/.forward file:
"| /usr/local/lib/slocal -user george"
If the directory /usr/local/lib is unavailable
(perhaps because a file server is down or because an automounter
failed), the mail message should be queued rather than bounced. To
arrange for requeuing of the message on failure, users should be
encouraged to construct their ~/.forward files
like this:
"| /usr/local/lib/slocal -user george || exit 75"
Here, the || tells the Bourne shell to perform
what follows (the exit 75) if the preceding
program could not be executed or if the program exited because of an
error. The exit value 75 is special, in that it tells
sendmail to queue the message for later delivery
rather than to bounce it.
|