[comp.mail.sendmail] Help with remote-mounted spool directory

msir@sulu.cc.rochester.edu (Mark Sirota) (09/20/90)

I realize that this is discussed all the time, but I've never paid attention
before because it was never an issue for me...  But now I want to start
remote-mounting /usr/spool/mail for a cluster of diskless Sun workstations
currently running SunOS 4.0.3.

Currently I use my own sendmail.cf, which is exactly the same for all
machines on our network.  It does all delivery itself, rather than
forwarding on to a central mailhost.  Now, for this new setup, I'm going to
want all local delivery to be done by the server, so that multiple machines
don't all go writing into the same file at the same time, right?

I'm told I need to use the 'R' option for this.  The manual is pretty
useless on this, it says "Remote mode.  Deliver through remote SMTP server.
Default is location of /var/spool/mail."

What does this *really* do?  (I don't have sources.)  Can I just add this
option with the name of the fileserver, or do I need to completely rework my
sendmail.cf to forward all local mail on to the server?

Thanks muchly in advance.
--
Mark Sirota - University of Rochester Computing Center, Rochester NY
 Internet: msir@cc.rochester.edu
 Bitnet:   msir@uordbv.bitnet
 UUCP:     {decvax,harvard,ames,rutgers}!rochester!ur-cc!msir

moore@betelgeuse.cs.utk.edu (Keith Moore) (09/21/90)

In article <9566@ur-cc.UUCP> Mark Sirota <msir@cc.rochester.edu> writes:
>I realize that this is discussed all the time, but I've never paid attention
>before because it was never an issue for me...  But now I want to start
>remote-mounting /usr/spool/mail for a cluster of diskless Sun workstations
>currently running SunOS 4.0.3.

Good idea.

>Currently I use my own sendmail.cf, which is exactly the same for all
>machines on our network.  It does all delivery itself, rather than
>forwarding on to a central mailhost.  Now, for this new setup, I'm going to
>want all local delivery to be done by the server, so that multiple machines
>don't all go writing into the same file at the same time, right?

Right.

>I'm told I need to use the 'R' option for this.  The manual is pretty
>useless on this, it says "Remote mode.  Deliver through remote SMTP server.
>Default is location of /var/spool/mail."
>
>What does this *really* do?  (I don't have sources.)  Can I just add this
>option with the name of the fileserver, or do I need to completely rework my
>sendmail.cf to forward all local mail on to the server?

If you were running a network of all Suns, with essentially unmodified
Sun-supplied sendmail config files, and had everything set up the way
they expect -- mail forwarding done by the aliases YP map, etc., then
you would probably do well to just enable the R option and let it go
at that.  But if you are maintaining your own config files, you might
well prefer to do without the R option, precisely because it's poorly
documented and will frustrate you.  You might not want it anyway, because
it bypasses all of the output channel processing (like mailer-specific
rewrite rules).  Basically, it's an ugly hack.  At any rate, it's not
necessary -- you can do this without lots of changes to your existing 
config file.  An added win is that this will work with other than Sun
machines.

Here's one way to do it: (based on diffs between my standalone config file 
and my client config file)

MODS TO MAIL CLIENT'S CONFIG FILE:

1.  Define a macro that evaluates to the domain name of your mail server,
    and another macro that evaluates to the domain name of your mail
    cluster.  The first one is an actual machine name (i.e. it must have
    an IP address and a name server A record); the second is the name of
    your domain (it may have an A record or one or more MX records).
    The two may be the same if that's the way you have it set up.

# NFS mail server (where /{usr,var}/spool/mail is mounted)
DSmail-server.cs.utk.edu

# mail cluster domain (common mail domain for all machines)
DRcs.utk.edu

2.  Typically, somewhere usually in ruleset 3 or ruleset 0, a config file
    has code recognize "local" domains and strip off the domain part.
    It might look something like this:

R$*<@$j>$*	$1<@>$2			strip off local domain

    Add a line here to recognize the "cluster" domain also, since they
    will end up at the same place.

R$*<@$R>$*	$1<@>$2			strip off cluster domain

3.  Now, change whatever code calls the "local" mailer to instead call
    a different mailer.  I use the name "server".  The name "local" has
    some special connotations to sendmail -- it does alias expansion
    on names sent to this mailer (via /etc/aliases or the YP map),
    processes .forward files, recognizes special kinds of addresses
    (those starting with "/" or "|" or ":include:"), handles errors
    differently (many "permanent" errors to the local mailer are
    treated as temporary), looks up the user's full name, saves failed
    mail in dead.letter, and bounces mail if the user's name isn't in
    /etc/passwd or the YP passwd database.  (Mostly because it fails
    trying to look at the user's .forward file -- else it would just
    let the delivery program return the error).  Whew!  Anyway, most
    of this processing is undesirable:  you don't want aliasing or
    forwarding to take place because of all of the additional failure
    modes that crop up -- e.g. sendmail often doesn't handle either YP or 
    NFS server failures correctly.   Also, think about the case where
    you have a heterogeneous network and a user has his .forward file
    piping mail to a program in his/her private bin directory, which
    is compiled for a particular architecture...but if you only do this
    processing on the mail server, behavior is more predictable.  Enough
    on why you shouldn't use the "local" mailer.  BTW, you still need
    to have a mailer named "local", even though it will never be used.

The last line in my ruleset zero looks like this:

R$+	$# server $@ $S $: $1

4.  I defined the "server" mailer as follows:

Mserver, P=[IPC], F=AmnDMuXI, S=10, R=10, A=IPC $h, E=\r\n

S10
# if the message is from root at the local domain, leave it alone
# (Actually class T is a list of "daemon" user names that send out
# logging messages -- it is helpful to be able to tell at a glance
# which machine is complaining about something.)
R$=T@$j		$@$1@$j
# if message from someone else is from local domain, change it to
# the cluster domain
R$*@$j		$@$1@$R
# otherwise, if it contains an '@' it's already fully qualified.
R$*@$*		$@$1@$2
# handle simple names (without '@') here
# if from root, append our local domain name (not cluster name)
R$=T		$@$1@$j
# otherwise, append cluster domain
R$*		$@$1@$R

S20
# if it contains '@' assume it's already qualified
R$*@$*		$@$1@$2
# if it's to root, append local domain (not cluster)
R$=T		$@$1@$j
# otherwise append cluster domain
R$*		$@$1@$R

    The main idea of the rewrite rules is to encourage everyone to 
    send all mail to the domain associated with the "cluster", not
    of any individual machine.  Otherwise you'll have to deal with 
    the problem of how to handle mail to a machine whose name no 
    longer exists.  So while we *accept* mail for user@specific.machine,
    we rewrite outgoing mail as from user@cluster.domain, and the
    same is true for recipient addresses in message headers.  Then
    replies will naturally be sent to the cluster domain, and people
    will get used to the idea that that's where your users get mail.
    On the other hand, if "root" on some machine sends a message to
    the sysadmin complaining about something that happened last night
    during a cron job, it's useful if the From: header tells you
    what machine it happened on.  So we don't do this kind of processing
    for users like "root", "daemon", and "uucp".

    The "server" mailer desription doesn't have the 'F' flag set, and
    therefore will not generate a From: header if one was not supplied
    by the user agent.  Fear not -- the mail server's sendmail will add
    one, and since it will recognize the mail as from a local user,
    it will do the passwd lookup and insert the user's full name.
    This produces headers like "From: Keith Moore <moore@cs.utk.edu>"
    instead of "From: moore@cs.utk.edu".  Many user agents do supply
    from headers, in which case the setting of the 'F' flag is irrelevant.

    I also left off the 'p' flag, because I want the envelope from address
    to be <moore@some.domain> and not <@client.machine:moore@some.domain>

    I used to just send bare usernames to the "server" mailer, rather
    than qualifying them on the client (I think the Sun sendmail 'R'
    option does this), but it turned out to be easier to get everything
    right when the client machine presents a fully-qualified address to
    the server.  

5.  I added similar code to rewrite local user names in the tcp mailer's
    rewrite rules (also in the mail client's config file).

MODS TO THE MAIL SERVER'S CONFIG FILE:

6.  Now, the server needs some way to recognize all incoming mail.
    At my site, all of our addresses are of the form something.cs.utk.edu,
    but not all possible something's are mail clients.  So I have a list
    of the something's in a file called /etc/MAIL-CLIENTS, and I define
    a class using that file:

Fw/etc/MAIL-CLIENTS

7.  Ruleset zero of the server config file has code to recognize mail
    to clients and treat it accordingly, along with mail to the server
    machine itself, and mail to the cluster domain:

R$*<@$=w.$D>$*		$1<@>$2		recognize mail to client domain
R$*<@$R>		$1<@>$2		recognize mail to cluster domain
R$*<@$j>		$1<@>$2		recognize mail to us
...
R$*<@>			$@$>0$1		retry after stripping @domain
R<@>:$*			$@$>0$1		retry after stripping @domain
...
R$*<@$*>$*		$# tcp $@ $2 $:$1$3 	mail to other domains
R$+			$# local $: $1		mail to local mailboxes

8.  The server's rewrite rules for outgoing mail also make sure to
    rewrite local addresses as being at the cluster domain, not that of
    the server machine's domain name.  (In our case, they are the same)

9.  If your mail server is also the NFS file server for all of your
    users' home directories, that's about all you need to do.  Otherwise
    you need to mount the home directories via either amd or automount,
    and replace your local, prog, and file mailers on the server with
    programs that can cope with unavailable file systems and return
    an exit status of EX_TEMPFAIL.  My local mailer is just a shell script
    that makes a few sanity checks before calling /bin/mail.  In practice
    it works quite well, but I will probably write a C version for the
    sake of efficiency.

I'll send the complete set of sendmail config files (client, server,
and standalone) along with the local mailer script, if you want them.
Beware:  they aren't as well commented as this message.


Good luck,


Keith Moore			Internet: moore@cs.utk.edu
University of Tenn. CS Dept.	BITNET: moore@utkvx
107 Ayres Hall, UT Campus	Telephone: +1 615 974 0822
Knoxville Tennessee 37996-1301	``Friends don't let friends use YP (or NIS)''

nowicki@legato (Bill Nowicki) (09/22/90)

In article <9566@ur-cc.UUCP> Mark Sirota <msir@cc.rochester.edu> writes:
>I'm told I need to use the 'R' option for this.  The manual is pretty
>useless on this, it says "Remote mode.  Deliver through remote SMTP server.
>Default is location of /var/spool/mail."
>

The idea is that you just need to put "OR" in the standard sendmail.cf
file. This is the way it is shipped from Sun, and Sun has the exact
same standard sendmail.cf file on thousands of systems.  The "OR" will
have no effect on the server that actually has the /var/spool/mail
mailboxes on its physical disk.  On machines that have /var/spool/mail
mounted across the network using NFS, the rest of the rules in
sendmail.cf will be ignored, and all mail will be delivered via the
SMTP protocol (i.e. TCP over the network) to the file server from
which /var/spool/mail is mounted.

P.S. Although I designed and implemented this feature, I would not
call the manual "useless". "Terse" perhaps.

-- Bill Nowicki
   Legato Systems
	

spike@world.std.com (Joe Ilacqua) (09/28/90)

>Currently I use my own sendmail.cf, which is exactly the same for all
<machines on our network.  It does all delivery itself, rather than
>forwarding on to a central mailhost.  Now, for this new setup, I'm going to
<want all local delivery to be done by the server, so that multiple machines
>don't all go writing into the same file at the same time, right?

	Here is a cf for the clients that does just that.  Works with
Sun's 4.x sendmails and with 5.61 + IDA (should work with 5.6x but is
untested) and probably other things too...

###########################################################
#
#	SENDMAIL CONFIGURATION FILE FOR NFS CLIENTS.
#
#	You should install this file as /etc/sendmail.cf
#	if want mail to appear to come from one central server
#	and not to be delivered localy.  For ease of use, you
#	should then NFS mount the servers /usr/spool/mail on
#	the local /usr/spool/mail.
#
#	All this cf does is change any reference to the local
#	hostname to the name of the server, and then send the
# 	mail to the server.  All other address parsing is handed 
#	off to the server.
#
#	I believe that this configuration functions correctly, however:
#	THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
#	IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
#	WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
#
#	Written by Spike (spike@world.std.com).  Also check out his cool
#	Server cf.

# my official hostname
Dj$w

# major relay mailer
DMTCP

# This is the name of the major relay so we can change our name.
# For example:
#DHcs.bu.edu
DH

#################################################
#
#	General configuration information

# local domain name
# For example:
#Dmstd.com
Dm

# Version number of configuration file
DVSpike-2.0


###   Standard macros

# name used for error messages
DnMailer-Daemon
# UNIX header format
DlFrom $g  $d
# delimiter (operator) characters
Do.:%@!^=/[]
# format of a total name
#Dq$g$?x ($x)$.
# This tends to get the Fullname added correctly
Dq<$g>
# SMTP login message
De$j Sendmail $v/$V ready at $b

###   Options

# location of alias file
OA/etc/aliases
# default delivery mode (deliver in background)
Odbackground
# rebuild the alias file automagically
OD
# temporary file mode -- 0600 for secure mail, 0644 for permissive
OF0600
# default GID
Og1
# location of help file
OH/usr/lib/sendmail.hf
# log level
OL9
# default messages to old style
Oo
# Cc my postmaster on error replies I generate
OPPostmaster
# queue directory
OQ/tmp
# read timeout for SMTP protocols
Or15m
# status file -- none
OS/etc/sendmail.st
# queue up everything before starting transmission, for safety
Os
# return queued mail after this long
OT3d
# default UID
Ou1

###   Message precedences
Pfirst-class=0
Pspecial-delivery=100
Pjunk=-100

###   Trusted users
T root daemon uucp

###   Format of headers 
H?P?Return-Path: <$g>
HReceived: $?sfrom $s $.by $j ($v/$V)
	id $i; $b
H?D?Resent-Date: $a
H?D?Date: $a
H?F?Resent-From: $q
H?F?From: $q
H?x?Full-Name: $x
HSubject:
H?M?Resent-Message-Id: <$t.$i@$j>
H?M?Message-Id: <$t.$i@$j>
HErrors-To:

###########################
###   Rewriting rules   ###
###########################


#  Sender Field Pre-rewriting
S1
# None needed.

#  Recipient Field Pre-rewriting
S2
# None needed.

# Name Canonicalization

# The magic to change the mail to make it look like it comes from the sever
# machine.  If the address contains no hostname or our hostname, we change it 
# to be the server hostname.  $H is the name of the server machine...

S3

R$*<$+>$*		$2			basic RFC822 parsing
R$-			$@$1@$H			user -> user@$H
R$+@$+			$:$1@$[$2$]		find real name (!CNAME)
R$+@$=w			$@$1@$H			user@local -> user@$H
R$+@$=w.$m		$@$1@$H			user@local.domain-> user@$H
R$=w!$+			$@$2@$H			local!user -> user@$H
R$=w.$m!$+		$@$2@$H			local.domain!user-> user@$H
R@$=w:$+		$@@$H:$2		@local:something
R@$=w.$m:$+		$@@$H:$2$3		@local.domain:something
R$+%$=w			$@$>3$1@$2		user%local
R$+%$=w.$m		$@$>3$1@$2		user%local.domain

# We never deliver mail locally, so these are unused.  How ever sendmail gets
# unhappy if we don't have them...
S4
# None needed

Mlocal, P=/bin/mail, F=rlsDFMmnP, S=10, R=20, A=mail -d $u
Mprog,  P=/bin/sh,   F=lsDFMeuP,  S=10, R=20, A=sh -c $u

S10
# None needed.

S20
# None needed.

############################################################
#####
#####		Ethernet Mailer specification
#####
#####	Messages processed by this configuration are assumed to remain
#####	in the same domain.  This really has nothing particular to do
#####   with Ethernet - the name is historical.

MTCP,	P=[IPC], F=msDFMuCX, S=11, R=21, A=IPC $h
S11
# None needed.

S21
# None needed.

#####		RULESET ZERO PREAMBLE

S0
# On entry, the address has been canonicalized and focused by ruleset 3.

# Punt to mail server
R$+			$#$M $@$H $:$1
-- 
"The World" - Public Access Unix - +1 617-739-9753  24hrs {3,12,24}00bps

rsalz@bbn.com (Rich Salz) (09/29/90)

>forwarding on to a central mailhost.  Now, for this new setup, I'm going to
>want all local delivery to be done by the server...

###
###  SENDMAIL CONFIGURATION FILE
###  This is the sendmail.cf for a client who can make a TCP connection to
###  a mail relay.  No local mail happens here.  Sendmail is not run in
###  daemon mode, either, just hourly out of cron to pick up anything
###  left when the server is not reachable.
###

##  HOSTNAME MACROS AND CLASSES

##  The name of our corporate domain.
DCbbn.com

##  The official name of this host (from gethostname(2)).
Dj$w

##  The relay host where everything gets forwarded to.
DRpineapple.bbn.com

##  GENERAL CONFIGURATION INFORMATION
##  Stuff here is required and reflects some policy decisions.

##  SMTP login message.
De$j Sendmail $v/$V ready at $b; how did you get here?
##  Format of the UNIX from line -- essentially a constant.
DlFrom $g $d
##  Name to use for returned mail -- essentially a constant.
DnMAILER-DAEMON
##  Token delimeters -- word separators in the rewrite rules below.
Do.:%@![]
##  Format of a sender's address; use full name.
Dq$x <$g>
##  Version of this .cf file.
DVrsalz-13-nov-89

##  Location of the alias file.
OA/usr/lib/aliases
##  Default delivery mode (one of background, foreground, queue).
Odbackground
##  Permissions for any temporary files we create.
OF0644
##  Default group id for mailers to run under.
Og1
##  Location of the SMTP help file.
OH/dev/null
##  Logging level.
OL9
##  Send to sender if an alias expansion includes her (a/k/a "me too")?
OmT
##  Allow headers to be in old style (i.e., spaces delimit names)?
OoT
##  Where to send important error messages.
OPpostmaster
##  Location of the queue directory.
OQ/usr/spool/mqueue
##  Give up on connections after this long a time period.
Or2h
##  Queue up everything before starting transmission?
OsT
##  How long message can sit in queue before it's bounced back?
OT3d
##  Default user id for mailers to run under.
Ou1
##  Password to enter wizard/debug mode.
OW*

##  Message precedences.
Pfirst-class=0
Pspecial-delivery=100
Pbulk=-50
Pjunk=-100

##  Trusted users -- these people can fake headers.
Troot

##  Format of headers.
HReceived: $?sfrom $s $.by $j id <$i@$j>; $b
HDate: $a
HFrom: $q
HMessage-Id: <$t.$i@$j>
HDResent-Date: $a
HFResent-From: $q
HMResent-Message-Id: <$t.$i@$j>

##  REWRITING RULES
##
##  These are the rules used for the following fields:
##	 From	3 -> 1 -> 4 -> 3 -> 1 -> S -> 4
##	 To	3 -> 0 -> 4
##	 From:	3 -> 1 -> 5 -> 4
##	 To:	3 -> 2 -> R -> 4
##  where S and R stand for the mailer-specific rewrite rules named in
##  the mailer definition.


##
##  RULESET  0 -- Pick a mailer.
S0
R$*<$*>$*		$1$2$3			defocus
R$+			$:$>3$1			make canonical
R$*<@[$+]>$*		$#relay$@[$2]$:$1@[$2]$3	numeric internet spec
R$*<$*.>$*		$1<$2>$3		drop trailing dot
R<@>:$*			$@$>0$1			retry after route strip
R$*<@>			$@$>0$1			strip null trash & retry
## Machine dependent part of ruleset 0.
## Here is where we actually find a mailer to invoke.
R$*			$#relay$@$R$:$1	forward everything


##
##  RULESET  1 -- From and From: fields.
S1


##
##  RULESET  2 -- To: field.
S2


##
##  RULESET  3 -- Basic name canonicalization.
S3
# Handle the SMTP "from:<>" as a special case.
R<>			$@@			turn into magic token
# Basic textual canonicalization.
R$*<$+>$*		$2			basic RFC821/822 parsing
R$*<$*>$*		$1$2$3			in case recursive
# Make sure <@a,@b,@c:u@d> syntax is easy to parse -- undone later.
R@$+,$+			@$1:$2			change all "," to ":"
# Localize and dispose of domain-based addresses.
R@$+:$+			$@$>6<@$1>:$2		handle <route-addr>
R$+:$*;@$+		$@$1:$2;@$3		list syntax
R$+@$+			$:$1<@$2>		focus on domain
R$+<$+@$+>		$1$2<@$3>		move gaze right
R$+<@$+>		$@$>6$1<@$2>		already canonical
# Convert old-style addresses to a domain-based address.
R$+%$+			$@$>6$1<@$2>		u%h
R$-!$+			$@$>6$2<@$1.UUCP>	resolve uucp names


##
##  RULESET  4 -- Final output rewriting.
S4
R@			$@			handle <> error addr
# Externalize local domain info.
R$*<$*LOCAL>$*		$1<$2$R>$3		change local info
R$*<$+>$*		$1$2$3			defocus
R@$+:$+:$+		$@@$1,$2:$3		<route-addr> canonical
R$+<@$w>		$1			remove our name
R$+@$-.UUCP		$2!$1			u@h.UUCP->h!u


##
##  RULESET  5 -- From: field post-processing (just before final).
S5


##
##  RULESET  6 -- Canonicalize hostname (called from ruleset 3).
S6
R$+<@$+.$+.UUCP>	$1<@$2.$3>		u@h.d.uucp->u@h.d


##
##  RULESET 14 -- All fields for all mailers
S14


##  MAILER SPECIFICATIONS
##

##  local; an error as we do no mail delivery here
Mlocal, P=/usr/lib/sendmail, F=DFILMmsuX, S=14, R=14, A=sendmail $n

##  prog; an error as we do no mail delivery here
Mprog,  P=/usr/lib/sendmail, F=DFILMmsuX, S=14, R=14, A=sendmail $n

##  relay; connect to Sendmail on relay host.
Mrelay, P=[IPC], F=DFLMmsuX, S=14, R=14, A=IPC $h, E=\r\n
-- 
Please send comp.sources.unix-related mail to rsalz@uunet.uu.net.
Use a domain-based address or give alternate paths, or you may lose out.