DataMuseum.dk

Presents historical artifacts from the history of:

DKUUG/EUUG Conference tapes

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about DKUUG/EUUG Conference tapes

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - metrics - download
Index: S T

⟦0a25e7ced⟧ TextFile

    Length: 82915 (0x143e3)
    Types: TextFile
    Names: »Sendmail.mc«

Derivation

└─⟦9ae75bfbd⟧ Bits:30007242 EUUGD3: Starter Kit
    └─⟦bfebc70e2⟧ »EurOpenD3/mail/sendmail-5.65b+IDA-1.4.3.tar.Z« 
        └─⟦f9e35cd84⟧ 
            └─⟦this⟧ »sendmail/ida/cf/Sendmail.mc« 

TextFile

changequote({,})dnl
ifdef({M4COMMENTS},{dnl
##########################################################################
###	The IDA-NIU Sendmail Master Configuration File	##################
##########################################################################
},{dnl ### M4COMMENTS Not defined ###
##########################################################################
###	The IDA-NIU Sendmail Configuration File		##################
##########################################################################
###	The documentation in this file is deliberately minimal.  For   ###
###	more complete documentation, look at the Master file	       ###
###	(Sendmail.mc), or - define(M4COMMENTS)    in your m4 source    ###
###	file and recreate the file.				       ###
})dnl ### End of M4COMMENTS ###
##########################################################################
###	Lennart_Lovstrand.EuroPARC@Xerox.COM			       ###
###	Rank Xerox EuroPARC, 61 Regent St, Cambridge, England	       ###
###	Copyright (c) 1984-88 -- Use it, abuse it, but don't sell it   ###
##########################################################################
###	Greatly modified, with changed internal canonical forms	       ###
###	by Neil Rickert <rickert@cs.niu.edu>			       ###
###	Northern Illinois University, DeKalb IL 60115		       ###
##########################################################################
# Current version
DVIDA-1.4.3

ifdef({M4COMMENTS},{dnl
####### INTRODUCTION #####################################################
#
#	This is The IDA Sendmail Master Configuration File--a completely
#	independent development having nothing to do with the version
#	distributed by Berkeley.  In order to work properly, it requires
#	a set of new functions implemented by the IDA Sendmail Enhancement
#	Kit, available from your nearest comp.sources.unix archive.
#
#	Get it today, tomorrow they might have a disk crash!
#
#	IDA is an abbreviation of "Institutionen for Datavetenskap",
#	which is Swedish for "The Department of Computer and Information
#	Science".  Under no circumstance should it be confused with the
#	IDA that stands for the Institute for Defense Analysis, with
#	which the author has no relationship to nor wish to become
#	associated with.

})dnl ### End of M4COMMENTS ###
####### REWRITING STRATEGIES #############################################
#
#	Ruleset 3 completely canonicalizes addresses to an internal
#	format, which looks like a modified RFC822 source route.
#	The internal canonical form is documented in the comments
#	preceding Ruleset #7 which is called internally by Ruleset #3.
#
#	The "domain" will be mapped to its full, official domain name
#	using the TCP/IP name server and a dbm domaintable.  !- and
#	::-style paths are rewritten into RFC822 routes internally.
#	Resonable mixtures of !-, %-, and RFC822 routes are resolved,
#	either using straight domain preference, or using heuristics.
#	Some effort is made to repair malformed addresses.
#
#	This format is used in all internal rulesets until finally
#	rewritten by the mailer dependent rules or by ruleset #4,
#	where they are fully transformed into the mailer's preferred
#	address syntax.  Three
#	kinds of mailers currently exist:
#
#	[1]  Domain based mailers, for which the official domain names
#	     are used and routes are given in the %-format for header
#	     addresses and envelope recipient addresses, while
#	     envelope return paths are kept in RFC822 route syntax.
#	     Typical examples of this type are the TCP/IP and LOCAL
#	     mailers.
#
#	[2]  Domain based mailers with flat node name mappings.  These
#	     use full domain names in header addresses but translate
#	     envelope domains to names relative the actual network's
#	     name space.  Two mailers fit into this category: The DECnet
#	     mailer, which map domain names to DECnet names, and the
#	     UUCP-A/B mailers, which map domains to UUCP node names.
#	     Both the DECnet and the UUCP worlds use flat namespaces.
#	     The DECnet and the UUCP-B mailers essentially uses type I
#	     routes while the UUCP-A mailer uses type III routes (ie,
#	     !-paths).
#
#	[3]  UUCP !-path based mailers.  This mailer type rewrites all
#	     addresses into !-paths, both header and envelope addresses.
#	     Header addresses are made relative the remote node by
#	     removing "remote!" from them or prefixing "localhost!" to
#	     them. UUCP nodes with domain names are translated to their
#	     UUCP equivlanents.


####### SENDMAIL CONFIGURATION EXTENSIONS ################################
#
#	This is a short table describing extensions to the configuration
#	language.  See the reference guide for a detailed definition.
#
#	Option "/" will turn on general envelope/header specific
#	rewriting.  Mailer specific e/h rulesets are given as in
#	"R=14/15", where ruleset 14 is used for envelope recipient
#	addresses and ruleset 15 for header recipients.
#
#	The M_FROMPATH (p) flag will work for mailers that use "From_"
#	line envelopes as well as SMTP mailers.
#
#	The M_RELATIVIZE (V) flag has been added, which make all header
#	lines relative the recipient host by removing "remote!" or
#	adding "localhost!".
#
#	TCP/IP nameserver lookups are extended with a default argument,
#	as in "$[ hostname $: default $]".  The "default" string will be
#	returned if the host isn't known to gethostname(3).
#
#	General dbm database functions have been added.  The option "K"
#	will declare a dbm database and associate it with a letter,
#	which later on is used in constructs like:
#		"$(x key $@ arg $: default $)"
#	The "x" is the one-letter name of the database, the "key" is the
#	lookup string; the optional "arg" is then sprintf(3)'ed through
#	the result, if found.  The whole expression evaluates to
#	"default", or "key" if "$: default" is not present, if the "key"
#	can't be found in the database.  The "@" database is
#	automatically connected to the aliases(5) file.


ifdef({M4COMMENTS},{dnl
####### M4 IDENTIFIERS ###################################################
#
#	NOTE: Be aware that this is an m4 source where curly braces are
#	used as quote characters.  You will lose heavily if you care-
#	lessly mention reserved m4 words or use curly braces where you
#	shouldn't.
#
#	The following is a list of all m4 identifiers used in this file.
#	All of them are optional.
#
#	ALIASES
#		Name of the aliases file, defaults to sendmail's default.
#	ALWAYSADDDOMAIN
#		If defined, local mail will always have the full domain
#		attached to the address.  The default is to retain the
#		domain if already present, but not add it to local addresses
#		without domains.  This only effects the local mailer.
#	ALTERNATENAMES
#		A list of alternate names for which mail is handled on
#		this machine.  This differs from PSEUDONYMS in that
#		mail to a PSEUDONYM is equivalent to mail to the main
#		name of this machine.  But we may also handle final
#		delivery of mail to other names, either with special
#		mailers defined in the mailer table, or with use
#		of the extended aliasing facility.  Used only in
#		ruleset #29 for stripping source routes through us
#		based on both pseudonyms and alternate names.
#	BANGIMPLIESUUCP
#		If defined, will assume that all !-paths with leading,
#		unqualified nodes resides in the UUCP pseudo-domain.
#		Will otherwise try to qualify node using the name server
#		and domaintable, retreating to .UUCP if unknown by them.
#	BANGONLYUUCP
#		If defined, a .UUCP qualification will only be added
#		to an unqualified domain if the domain is delimited
#		with a !.
#	DECNETNAME
#		This node's DECnet name as printed by the nodename command.
#		Define if this host is a DECnet/Internet gateway.  Routes
#		mail sent to host::user and user@host.dnet via mail11v3.
#		Will also route user@host.hepnet, user@host.decnet, and
#		user@host.span if UIUC is defined.  Sendmail must be compiled
#		with #define MAIL11V3 in src/conf.h .
#	DECNETNODES
#		A file containing DECnet host names.  Used in combination
#		with DECNETXTABLE to determine delivery through the DECnet
#		mailer and when to expand flatspaced DECnet host names into
#		domains.  DECNETNODES may be a list of domains, an absolute
#		file path (first char /) or a program (first char |).
#	DECNETXTABLE
#		The DECnet translation table.  Returns a node's DECnet
#		host name if given its domain name.  (Dbm file, see
#		ruleset 24 for more info).
#	DEFAULT_HOST
#		Explicit host name, replaces automatic definition of $w.
#	DEFAULT_DOMAIN
#		The string that (+ ".") will be attached to $w to
#		form $j, this node's official domain name.  Only define
#		this if $w doesn't already include your full domain
#		(ie, as returned by gethostbyname(<yourhost>)).
#	DOMAINMASTER
#		Obsolescent.  Use ALTERNATENAMES (which see) and a mailer
#		table entry.  Was intended to allow handling mail for a parent
#		domain for which there is no machine.  For example, at
#		uiuc, machine uxc.cso.uiuc.edu can handle mail for uiuc.edu.
#		by sending them to the PH mailer.  But with the extensions to
#		the mailertable, the same effect is achieved by defining an
#		entry:  PH!uxc.cso.uiuc.edu  uiuc.edu
#		in the mailertable source.  An entry for uiuc.edu would still
#		be needed in ALTERNATENAMES to strip source routes.
#	DOMAINTABLE
#		Dbm database used for hostname canonicalization, ie.
#		to find the official domain name for local or otherwise
#		unqualified hosts.
})dnl ### End of M4COMMENTS ###
ifdef({M4COMMENTS},{dnl  -Divided this to avoid overflowing m4 buffer.
#	FORCE_NAMED
#		Set the I flag to force host name lookups to go through the
#		domain name server.  Otherwise if the nameserver isn't
#		running, sendmail will assume that /etc/hosts is complete.
#		You want to use this if you're doing MX forwarding.  You
#		DON'T want to use this if you're not running the nameserver.
#	GENERICFROM
#		A database mapping actual user names to generic user
#		names.  Used instead of HIDDENNET in a heterogenous
#		environment.
#	HIDDENNET
#		Points to a file containing a list of host names, one
#		per line.  Mail from users on any of these hosts will
#		have the host name substituted for our host, $w.
#		HIDDENNET may be a list of domains, an absolute
#		file path (first char /) or a program (first char |).
#	HIDDENNETHOST
#		The fully qualified domain name to use instead of $w with
#		HIDDENNET.
#	LIBDIR	
#		The directory that will hold most data files, including
#		sendmail.{hf,st}; defaults to /usr/lib/mail.
#	LIUIDA
#		Site specific parts for the CIS Dept, U of Linkoping.
#	LOADAVEQUEUE
#		The load average at which messages will be queued.  Defaults
#		to 11.  Define as 0 to disable the facility.
#	LOADAVEREJ
#		The load average at which connections will be refused.
#		Defaults to 7.  Disable by defining as 0.
})dnl ### End of M4COMMENTS ###
ifdef({M4COMMENTS},{dnl  -Divided this to avoid overflowing m4 buffer.
#	M4COMMENTS
#		Not intended to be defined.  If not defined, comments
#		which only make sense in the M4 source are excluded from
#		the generated .cf file.
#	MAILNAME
#		The domain name to be used on outbound mail, in place of
#		$w.  This is mostly useful when it is desired to hide all
#		host names in a network, with a common MX name to be on
#		outbound mail.  If most hosts in the network do not run
#		SMTP daemons it is better to not use the real hostname.
#		MAILNAME is only used for local names for which no domain
#		is explicitely specified.  If you wish to hide host names
#		that are explicitely specified, you should also use
#		HIDDENNET.  When MAILNAME is defined it becomes the
#		default value for HIDDENNETHOST.
#	MAILERTABLE
#		A dbm table mapping node names to "mailer:host" pairs.
#		It is used for special cases when the resolving heuristics
#		of ruleset 26 aren't enough.
#		The key may be of the form .subdomain for matching complete
#		subdomain families.  The value mapped to may be of the
#		forms - mailer,host  or  mailer:host  or  mailer!host
#		The standard should be mailer,host .  With mailer!host the
#		destination domain is removed from the recipient address before
#		mailing.  With mailer:host the recipient domain is removed if
#		multi-level routing is present.  An optional form ':' (i.e.
#		missing mailer and host) may be specified to cause mailer
#		selection to fail, and force a PATHTABLE lookup.
#		In the host portion of mailer,host there may be a %s provided
#		that the search key begins with a '.' - the effect is that when
#		a match occurs, the component of the actual domain name which
#		precedes the '.' in the key will replace the %s.
})dnl ### End of M4COMMENTS ###
ifdef({M4COMMENTS},{dnl  -Divided this to avoid overflowing m4 buffer.
#	MAILSERVER
#		The name of a host on which local mail should be delivered.
#		If the mailbox directory is mounted from a remote file server
#		you may wish to specify that local mail be sent to the remote
#		server for local delivery there.  Alternatives are to use
#		the RSH_SERVER.
#		Important note:  If you use the MAILSERVER option, any
#		programmatic aliases should be specified with the '|'
#		outside the quotes.  For example, use
#		msgs:	|"/usr/ucb/msgs -s"
#		Note that the local aliases file is still consulted before
#		a decision is made to forward the mail to the MAILSERVER.
#		It is not currently possible, however, to consult the
#		user's '.forward' file.  Hopefully the MAILSERVER will
#		mount the same home directories, and will itself consult
#		the .forward file.
#		If the aliases file is a YP/NIS alias map, the alias processing
#		is slightly different.  In this case local names are mailed to
#		the MAILSERVER for expansion, unless they are qualified with
#		a domain recognized as local.  Here are some examples.
#		list:	addr1, addr2, addr3 # Lists ALWAYS sent to MAILSERVER.
#		me:	you		    # Sent to server for expansion.
#		me:	you@client1.dom.ain # Expanded locally if client1.
#		nobody: /dev/null@localhost # Expanded locally on all clients.
#		  (This assumes that 'localhost' is defined as a PSEUDONYM).
#		recnews: recnews-client1@client1.dom.ain
#		recnews-client1: |"recnews"@client1.dom.ain
#		 Mail to 'recnews' should be expanded locally on client1,
#		but all other clients will send to MAILSERVER, which will
#		forward to client1 readdressed to recnews-client1, and in
#		turn it will be expanded on client1.
#	NEWALIASES
#		This option is obsolete.  A better method now exists.
#		See below, at the end of the description for this option.
#
#		New approach:  If you want a non-local alias for
#		'user@host', list it in the aliases file as
#		'user%host@localhost'.  This will result in a correct
#		alias entry, since addresses routed through 'localhost'
#		are now automatically sent to the local mailer.
#
#		The script 'xalparse.sh' generates the correct format
#		aliases file from xaliases.
#	NIS_MAILHOST
#		Used in conjunction with NIS_MAILALIASES described below.
#		Note that the NIS_MAILHOST *** MUST NOT *** be this
#		local host, *** NOR *** an MX address for which this local
#		host is the best preference handler.
})dnl ### End of M4COMMENTS ###
ifdef({M4COMMENTS},{dnl  -Divided this to avoid overflowing m4 buffer.
#	NIS_MAILALIASES
#		Use the NIS mail aliases before attempting local
#   	    	delivery.  If a local address is not in the local
#		aliases file, the NIS/YP aliases file is consulted.
#		If an alias exists and specifies a single mailbox
#		address local to this host (domain matches $=w)
#		it is delivered to that alias locally.  Otherwise
#		the mail is forwarded to NIS_MAILHOST via the
#		TCPMAILER for alias expansion and delivery.
#		*** NOTICE *** In order to not interfere with
#		construction of the local alias database rebuilding,
#		this option is implemented in such a way that it
#		only affects addresses used for actual delivery
#		of mail.  Test mode ('sendmail -bt') will usually
#		not reveal how this is processed.  To test this
#		option under test mode, specify:
#			/usr/lib/sendmail -bt -oMfnobody
#	ISOLATED_DOMAINS
#		A list of domains which may use TCP/IP delivery. Any
#		domain not in this list is assumed to need to be sent
#		using RELAY_HOST/RELAY_MAILER. This is useful if a
#		site is using the DNS, but has a policy which does not
#		allow IP connectivity between internal networks and
#		the Internet.
#	PATHTABLE
#		The heart & soul of this sendmail configuration--the
#		pathalias routing table in dbm format, as produced by
#		the pathalias program.  Either you define this or rel(a)y
#		on RELAY_HOST/RELAY_MAILER.
#	POSTMASTERBOUNCE
#		If defined the postmaster gets a copy of bounced mail.
#		Can alternatively be defined to a mailbox name, in which
#		case the copy of bounced mail is sent to this mailbox instead
#		of to the postmaster.
#	PSEUDODOMAINS
#		A list of well-known top level pseudo domains such as
#		BITNET, CSNET, UUCP, etc.  Addresses ending with a top
#		level domain in this class won't be canonicalized using
#		the resolver to reduce load on the root name servers.
#		Note that this variable is independent of the T class
#		below.  Any "well-known" top level domain that is not
#		part of NIC's registered domains may be put here.
#		PSEUDODOMAINS may be a list of domains, an absolute
#		file path (first char /) or a program (first char |).
#	PSEUDONYMS
#		Additional names that we are known under (in addition
#		to those returned by gethostbyname()).
#		PSEUDONYMS may be a list of domains, an absolute
#		file path (first char /) or a program (first char |).
})dnl ### End of M4COMMENTS ###
ifdef({M4COMMENTS},{dnl  -Divided this to avoid overflowing m4 buffer.
#	RELATIVIZE
#		This option has been removed.  It is incompatible with
#		the use of MX addresses.  The SMTP host still needs the
#		full domain name (which may be an MX address) to make its
#		forwarding decisions.  Relativization for specific domains
#		is still possible via mailertable.
#	RELAY_HOST & RELAY_MAILER
#		Name of the host and mailer to ship unknown recipient
#		addresses to.
#	RSH_SERVER
#		If defined, do local deliveries by rsh'ing /bin/mail
#		on the RSH_SERVER host.  Make sure that root is allowed
#		to remotely login to the server.
#	SPOOLDIR
#		Directory for sendmail queue files; defaults to
#		/usr/spool/mqueue.
#	STRICTLY822
#		This is obsolete, and is replaced by a changed UUCPPRECEDENCE
#		(which you should read).  It was used to identify the
#		precedence of !/@.  It former function is now the default
#		except for UUCP nodes identified in UUCPPRECEDENCE.
#	TCPMAILER
#		The default TCP mailer to use for SMTP/TCP deliveries.
#		Defaults to TCP (as opposed to TCP-D or TCP-U, qv).
#	TIMEOUT
#		By default the timeout, the length of time the mail sits
#		in the queue before being returned to the sender, is
#		two days.  By defining TIMEOUT to some other value, you
#		can change this.  For example: define(TIMEOUT, 3d)
#		in your 'm4' source would give a three day timeout before
#		mail is returned as undeliverable.
#	TRUSTEDUSERS
#		Trusted users to be added to users root daemon uucp.
#	UIUC
#		Site specific parts for the University of Illinois at
#		Urbana-Champaign.  Replaces UUCP mailer with one one that
#		accumulates statistics.
#	UUCPMAILER
#		The default UUCP mailer to use for UUCP deliveries.
#		Defaults to UUCP (as opposed to UUCP-A or UUCP-B, qv).
#	UUCPNAME
#		This node's UUCP host name.
#	UUCPNODES
#		A file containing names of directly connectable UUCP nodes.
#		UUCPNODES may be a list of domains, an absolute
#		file path (first char /) or a program (first char |).
#	UUCPPRECEDENCE
#		A file containing names of UUCP nodes which generate
#		hybrid !/@ addresses for which the '!' should be given
#		precedence.  Normally 'u!x@d' is parsed as '@d,@u!x' but
#		if 'u' is in the UUCPPRECEDENCE list, and if the
#		mail originates at 'u.UUCP' (must be the same 'u'),
#		then 'u!x@d' is parsed as '@u!@d,x'.
#		UUCPPRECEDENCE may be a list of nodes, an absolute
#		file path (first char /) or a program (first char |).
#		Please note that this functionality is only available
#		if your 'rmail' invokes 'sendmail' with the flags
#		-oMrUUCP -oMsnodename.UUCP
#	UUCPRELAYS
#		Name of file containing names of known (UUCP) relays.
#		Header addresses containing paths through any of these
#		will be shortened by having the path to the relay removed.
#		(It is assumed that paths to each of these are known to
#		everybody)  UUCPRELAYS may be a list of domains, an absolute
#		file path (first char /) or a program (first char |).
#	UUCPXTABLE
#		A table mapping domain node names to UUCP node names.
#		Used in envelope addresses sent using UUCP/rmail.
#
#  The following are still experimental:
#	XEROXGV & XEROXNS
#		Default gateways for unspecified Xerox Grapevine and XNS
#		addresses.
#	XNSDOMAIN
#		The name of the XNS Gateway domain {from the XNS side}.
#	XNSMAIL
#		The name of your XNS Mail Gateway program.


})dnl ### End of M4COMMENTS ###
####### CLASSES, DEFINITIONS, and DATABASES ##############################
#
#	The following classes, macro definitions and keyed databases are
#	being used:
#
#	CA	An atsign (@), used in class membership negations
ifdef({DECNETNODES},{dnl
#	CD	Known DECnet host names
})dnl
ifdef({UUCPPRECEDENCE},{dnl
#	CE	UUCP nodes which add 'node!' in front of 'u@d' addresses.
})dnl
ifdef({HIDDENNET},{dnl
#	CH	Node names that should be hidden by $w
})dnl
ifdef({ISOLATED_DOMAINS},{dnl
#	CI	Isolated net names
})dnl
ifdef({ALTERNATENAMES},{dnl
#	CM	A list of alternate mail names for which we make final delivery.
})dnl
ifdef({PSEUDODOMAINS},{dnl
#	CP	Known top level pseudo domains
})dnl
ifdef({UUCPRELAYS},{dnl
#	CR	Paths to these relays removable from headers.
})dnl
#	CT	Known top level domains (global + local)
#	CU	Directly connectable UUCP nodes
#	CX	A set of chars that delimit the LHS of a domain (@ %)
#	CY	A set of chars that delimit the RHS of a domain (, : !)
#	CZ	RFC822 Source Route punctuation chars (, :)
#
#	DV	Configuration version number
#
#	OK@	The aliases database (automatically defined)
ifdef({NIS_MAILALIASES},{dnl
#	OK%	The NIS aliases database
})dnl
ifdef({DECNETXTABLE},{dnl
#	OKD	DECnet domain translation table
})dnl
ifdef({GENERICFROM},{dnl
#	OKG	Generic usernames
})dnl
ifdef({MAILERTABLE},{dnl
#	OKM	Special domain => mailer:host table
})dnl
ifdef({DOMAINTABLE},{dnl
#	OKN	Official name lookup table
})dnl
ifdef({PATHTABLE},{dnl
#	OKP	Pathalias routing database
})dnl
ifdef({UUCPXTABLE},{dnl
#	OKU	UUCP domain translation table
})dnl


##########################################################################
## Default Definitions ###################################################
##########################################################################
ifdef({LIBDIR},,{define(LIBDIR, /usr/lib/mail)})dnl
ifdef({SPOOLDIR},,{define(SPOOLDIR, /usr/spool/mqueue)})dnl
ifdef({TCPMAILER},,{define(TCPMAILER, TCP)})dnl
ifdef({UUCPMAILER},,{define(UUCPMAILER, UUCP)})dnl
ifdef({DOMAINMASTER},
	{errprint({Note: DOMAINMASTER is obsolescent, see Sendmail.mc})})dnl
ifdef({FACSIMILE},
	{errprint({Note: FACSIMILE is obsolescent, see Sendmail.mc})})dnl
ifdef({NEWALIASES},
	{errprint({Note: NEWALIASES is obsolete, see Sendmail.mc})})dnl
ifdef({RELATIVIZE},
	{errprint({Note: RELATIVIZE is obsolete, see Sendmail.mc})})dnl
ifdef({STRICTLY822},
	{errprint({Note: STRICTLY822 is obsolete, please see Sendmail.mc})})
ifelse(len(UUCPPRECEDENCE),0,
	{errprint({Note: UUCPPRECEDENCE requires a list. See Sendmail.mc})
	undefine({UUCPPRECEDENCE})})dnl
define(CLASS_TYPE,{ifelse(index($1,|),0,{F},index($1,/),0,{F},{C})})
define(SET_CLASS,{CLASS_TYPE($2)}{$1$2})

#
##########################################################################
## Domain Definitions ####################################################
##########################################################################

##########################################################################
#	Universally known top-level domains

#					Organizational domains
CTarpa com edu gov int mil nato net org
#					National domains
CTar at au be br ca ch cl cn cr cs de dk ec eg es fi fr gr hk hu ie il in is
CTit jp kr lk mx my ni nl no nz ph pl pr pt se sg su th tr tw uk us uy yu za
#					Network based domains
# NS records don't exist for these
CTbitnet csnet
#CTbitnet csnet uucp
# Removed UUCP.  The address shortening in ruleset 23 should not apply to
# UUCP addresses since the addresses are relative - not absolute.

##########################################################################
#	Well-known pseudo domains
#	(that the resolver shouldn't be bothered with)
ifdef({PSEUDODOMAINS},{dnl
SET_CLASS({P},PSEUDODOMAINS)
},{dnl ### Not PSEUDODOMAINS ###
# CPbitnet uucp
})dnl ### End PSEUDDOMAINS ###

##########################################################################
## Misc Definitions ######################################################
##########################################################################

ifdef({ISOLATED_DOMAINS},{dnl
# This is the list of nets which may use TCP/IP delivery directly.
SET_CLASS({I},ISOLATED_DOMAINS)})

ifdef({UUCPPRECEDENCE},{dnl
# The list of UUCP nodes which erroneously change 'u@d' to 'uuhost!u@d'
# instead of to 'uuhost!d!u'
SET_CLASS({E},UUCPPRECEDENCE)})

# This node's local host name
ifdef({DEFAULT_HOST},{dnl
{Dw}DEFAULT_HOST
{Cw}DEFAULT_HOST
},{dnl ### Not DEFAULT_HOST
# DwYourDefaultHostName if not correctly determined by sendmail.
# CwYourDefaultHostName if not correctly determined by sendmail.
})dnl

ifdef({PSEUDONYMS},{
# Other names for this node - localhost.your.domain may be needed among these.
SET_CLASS({w},PSEUDONYMS)})
# We always want localhost to be considered local.
Cwlocalhost

# This node's official domain name
ifdef({DEFAULT_DOMAIN},
{Dj$w.}DEFAULT_DOMAIN,
Dj$w)

ifdef({ALTERNATENAMES},{
# Other domains through which we must strip all routing.
{CM}ALTERNATENAMES
},{dnl
ifdef({DOMAINMASTER},{dnl
define({ALTERNATENAMES})
{CM}DOMAINMASTER})
ifdef({FACSIMILE},{
{CM}FACSIMILE
})})dnl

# Define a quote macro.  This is the only way to put '"' into an address.
# and even then we must use $&Q, not $Q  (Use with caution).
DQ\"

# my name
DnMAILER-DAEMON

# UNIX header format
DlFrom $g $d

# delimiter (operator) characters
Do".:;%@!=/[]?#^,<>"

# Characters that mark the left (X) & right (Y) hand side of a domain
CX@ %
CY, : !

# Pure RFC822 route punctuation characters
CZ, :

# The atsign-in-a-class
CA@

# Format of a total name: Personal Name <user@domain>
# - now uses $f in place of the usual $g, to avoid envelope rewriting rules.
Dq$?x$!x <$f>$|$f$.

# SMTP login message
De$j $v/$V Sendmail is ready at $b


##########################################################################
#	Options

#				set default alias file
ifdef({ALIASES},{OA}ALIASES)
#				time to look for "@:@" in alias file
Oa15
#				substitution for blank character
OB.
#				don't connect to "expensive" mailers
Oc
#				delivery mode
Odb
#				rebuild alias database as needed
# OD
#				set error processing mode
# Oe
#				temporary file mode
OF0600
#				save Unix-style From lines on front
# Of
#				default gid
Og1
#				help file
{OH}LIBDIR/sendmail.hf
#				force use of name server
ifdef({FORCE_NAMED},{OI},{# OI})
#				ignore dot lines in message
# Oi
#				database files
ifdef({NIS_MAILALIASES},{dnl
ifdef({NIS_MAILHOST},{OK%%mail.aliases}
,{dnl ### Not NIS_MAILHOST ###
errprint({**** NIS_MAILALIASES requires that NIS_MAILHOST be defined})dnl
undefine({NIS_MAILALIASES})dnl
})})dnl ### End Not NIS_MAILHOST, NIS_MAILALIASES ###
ifdef({DECNETXTABLE},{OKD}DECNETXTABLE)
ifdef({GENERICFROM},{OKG}GENERICFROM)
ifdef({MAILERTABLE},{OKM}MAILERTABLE)
ifdef({DOMAINTABLE},{OKN}DOMAINTABLE)
ifdef({PATHTABLE},{OKP}PATHTABLE)
ifdef({UUCPXTABLE},{OKU}UUCPXTABLE)
#				log level
OL9
#				define macro
# OM
#				send to me too
Om
#				local network name
ifdef({DEFAULT_DOMAIN},{ON}DEFAULT_DOMAIN,{# ONdefault_domain_name})
#				assume old style headers
Oo
#				postmaster copy of returned messages
ifdef({POSTMASTERBOUNCE},{dnl ### Postmaster gets copy of bounced mail
ifelse(len(POSTMASTERBOUNCE),0,{OPPostmaster},{OP}POSTMASTERBOUNCE)
},{# OPPostmaster
})dnl ### End POSTMASTERBOUNCE
#				queue directory
{OQ}SPOOLDIR
#				read timeout -- violates protocols
Or30m
#				status file
{OS}LIBDIR/sendmail.st
#				be super safe, even if expensive
Os
#				queue timeout
ifdef({TIMEOUT},{OT}TIMEOUT,{OT}2d)
#				time zone name
# OtMET,MET DST
#				set default uid
Ou1
#				run in verbose mode
# Ov
#				wizard's password
OW*
#				load avg at which to auto-queue msgs
ifdef({LOADAVEQUEUE},,{define(LOADAVEQUEUE, 11)})dnl
ifelse(LOADAVEQUEUE,0,{# Ox11},{Ox}LOADAVEQUEUE)
#				load avg to auto-reject connections
ifdef({LOADAVEREJ},,{define(LOADAVEREJ, 7)})dnl
ifelse(LOADAVEREJ,0,{# OX7},{OX}LOADAVEREJ)
#				fork when running the queue
# OY
#				use separate envelope/header rewriting rulesets
O/

##########################################################################
#	Message precedences

Pfirst-class=0
Pspecial-delivery=100
Pbulk=-100
Pjunk=-100

##########################################################################
#	Trusted users

Troot
Tdaemon
Tuucp
ifdef({TRUSTEDUSERS},{T}TRUSTEDUSERS)

##########################################################################
#	Header Formats

#HReceived: $?sfrom $s $.by $j; $b
HReceived: $?sfrom $s $.by $j$?r with $r$. id $i
  ($v/$V$?u for $u$.); $b
H?P?Return-Path: <$g>
H?D?Date: $a
H?F?From: $q
H?x?Full-Name: $x
H?M?Message-ID: <$t.$i@$j>


#\f


##########################################################################
## Mailer Specifications #################################################
##########################################################################

##########################################################################
#
#	Local & Prog mailer definitions

ifdef({HIDDENNET},{
# List of nodes that should be hidden by our name (header senders)
SET_CLASS({H},HIDDENNET)
ifdef({HIDDENNETHOST},,{ifdef({MAILNAME},{define(HIDDENNETHOST, MAILNAME)})})dnl
})dnl

ifdef({RSH_SERVER}, {dnl
Mlocal,	P=/usr/ucb/rsh, F=DFMlmns, R=25/10, S=10, A=RSH_SERVER /bin/mail -d $u
}, {dnl
Mlocal,	P=/bin/mail, F=DFMlrmns,	R=25/10, S=10, A=mail -d $u
})dnl
Mprog,	P=/bin/sh,  F=DFMhlsu, R=10, S=10, A=sh -c $u
# Add -p flag to phquery to copy postmaster on error bounces
MPH,	P=LIBDIR/phquery, F=DFMhnmur,	A=phquery $u
MPHF,	P=LIBDIR/phquery, F=DFMhnmur,	A=phquery -R $u
MFAX,	P=LIBDIR/phquery, F=DFMhnmur,	A=phquery -x fax $u
MNOVAM,	P=LIBDIR/novamailer, F=DFMhnmur, A=novamailer $u

##########################################################################
#
#	TCP/IP mailer specification
#
#	The TCP mailer is the normal choice for SMTP/TCP delivery, but a
#	couple of variations exist for compatibility with mailers that
#	need special address formatting for indirect UUCP and DECnet
#	addresses.  Both have to be explicitly mentioned in the mailertable
#	to be chosen as all normal mail will use the standard TCP mailer.
#
#	TCP-A -- make sure address ends with a registered domain, ie.
#	strictly legal within the ARPA Internet.  If it isn't, we'll
#	turn it into a path through ourselves.
#
#	TCP-D -- will flatten envelope recipient DECnet domains for
#	messages destinated to our DECnet gateway.   Unfortunately, our
#	(Linkoping) DECnet gateway is too dumb to do this itself.
#
#	TCP-U -- is available for hosts which require hybrid addresses
#	for deliveries to UUCP destinations.  Eg. "bar!foo@dest.host"
#	will be formatted as bar!foo@dest.host in the output mail,
#	whereas the regular TCP mailer will preserve the address in a
#	format more closely resembling the address it received.
#
#	Both of the above only touch envelope addresses; header
#	addresses are still kept in our preferred format.  Change the
#	R/S settings below if you don't like that.

MTCP,   P=[IPC], F=CDFMXhnmu, E=\r\n, R=10/11, S=11, A=IPC $h
MTCP-A, P=[IPC], F=CDFMXhnmu, E=\r\n, R=12, S=12, A=IPC $h
MTCP-D, P=[IPC], F=CDFMXhnmu, E=\r\n, R=24/25, S=0/25, A=IPC $h
MTCP-U, P=[IPC], F=CDFMXhnmu, E=\r\n, R=17/11, S=17/11, A=IPC $h

#########################################################################
#									#
#	Rule set #10:  For local mailers (headers only).		#
#									#
#	Local recipients without attached domains have the		#
#	default domain stripped off.  Superfluous routing is		#
#	removed.  Otherwise there is an attempt to preserve as		#
#	much of the original formatting as possible, provided		#
#	that the resultant address will be correctly recognized		#
#	if processed again by this mailer configuration.		#
#									#
#	Also useful for envelope recipients of mailers such as		#
#	the TCP mailer, where the address will not be local		#
#	anyway.								#
#									#
#########################################################################
S10

ifdef({ALWAYSADDDOMAIN},,{dnl ### Don't add local domain to local users.
R<>,$=X$+$=Y$+		<>,$4			Remove default host.
})dnl ### End ALWAYSADDDOMAIN
R<$+>$*$=Y$~A$*		$:<$1>$2$3?$4$5		Mark user portion.
R<$+>$*!$+,$*?$+	<$1>$2!$3!$4?$5		! is inferior to @
R<$+>$+,$*?$+		<$1>$2:$3?$4		Change src rte to % path
R<$+>:$+		<$1>,$2			Change % to @ for immed. domain
R<$=X$-.UUCP>!?$+	$@<$1$2.UUCP>!$3	Return UUCP
R<$=X$->!?$+		$@<$1$2>!$3		Return unqualified
R<$+>$+?$+		<$1>$2$3		Remove '?'
R<$+.$+>$=Y$+		$@<$1.$2>,$4		Change do user@domain

#########################################################################
#									#
#	Rule set #11:  General purpose output formatting.		#
#									#
#	Uses a heuristic approach based on the input format of the	#
#	address.  A simple address is always formatted as		#
#	user@dom.ain, unless the domain is a UUCP domain.  For		#
#	multi-level paths, uses either a ! path or a % path, or		#
#	perhaps even a hybrid @/! path, depending on the format		#
#	in which the original address is presented.			#
#									#
#########################################################################
S11

R<$+>$+			$:$>21<$1>$2		Provide route to neighbors
R<$+>$*$=Y$~A$*		$:<$1>$2$3?$4$5		Mark user portion.
R<$+>$*!$+,$*?$+	<$1>$2!$3!$4?$5		! is inferior to @
R<$+>$+,$*?$+		<$1>$2:$3?$4		Change src rte to % path
R<$+>:$+		<$1>,$2			Change % to @ for immed. domain
R<$+>$+?$+		$:<$1>$2$3		Remove mark
R<$=X$-.UUCP>!$+	$@<$1$2.UUCP>!$3	Return UUCP
R<$=X$->!$+		$@<$1$2>!$3		Return unqualified
R<$+>$=Y$+		$:<$1>,$3		Else change do user@domain

#########################################################################
#									#
#	Rule Set #12:  Make sure all domains RFC822 valid.		#
#									#
#	This rule set is actually a compromize.  Recipient		#
#	addresses may not finish up being in a valid domain.		#
#	They may possibly be better known in the receiving		#
#	domain than in ours, so we should not hide them behind		#
#	our domain.  However if the recipients are local UUCP		#
#	links, etc, we do hide behind our name.  This presumes that	#
#	the mailer is never used for such local links, so that any	#
#	locally connected recipient is an alternate header recipient,	#
#	and not an envelope recipient.					#
#									#
#########################################################################
S12
# First change to source route format.
R<$+>$*$=Y$~A$*		$:<$1>$2$3?$4$5		Mark user portion.
R<$+>$=Y$+		$:<$1>,$3		Make first specifier @.
R<$+>,@$+!$*?$+		<$1>,@$2,$3?$4		Change all others to @.
R<$+>,$+:$+,$*?$+	<$1>,$2:$3:$4?$5	 but only to first %.
R<$+>$+?$+		<$1>$2$3		Remove marker.
# Next try to force address to be official domain name.
R<@$+>$+		$@$>21<@$1>$2			Route local recipients.
R<%$+.$=P>$+		$@$>20<%$1.$2>$3		Hide pseudo domain
R<%$+>$+		$:<%$[ $1 $: $1? $]>$2		Valid by name server?
ifdef({DOMAINTABLE},{dnl
ifdef({M4COMMENTS},{dnl
# Try to validate with name table.  This might be a valid name for which
# we are the primary MX forwarder.  In this case the $[ .. $] lookup
# will fail.  By translating to itself in domain table, we can still
# validate.
})dnl ### End M4COMMENTS ###
R<%$+?>$+		$:<%$(N $1 $: $1? $)>$2	Valid in domain tbl?
ifdef({M4COMMENTS},{dnl
# The address should have been fully qualified before this ruleset is
# called.  Thus the domain should already be fully qualified, and will
# only be recognized by the domaintable if it translates to itself. But
# just in case, we check again for pseudo domains.
})dnl ### End M4COMMENTS ###
R<%$+.$=P>$+		$@$>20<%$1.$2>$3		Hide pseudo domain
})dnl ### End DOMAINTABLE ###
R<$+?>$+		$@$>20<$1>$2			Invalid - hide.

# Produce hybrid (brr) recipient addresses for unqualified or .UUCP hosts
S17
R<$+>$+			$:$>19 <$1>$2			bangify.
# Possibly produce addresses such as b!c!x@foo.bar.edu
R<$=X$-.$+>!$+		$:<$1$2.$3>,$4		Use @ for qualified.
R<$=X$-.UUCP>,$+	$:<$1$2.UUCP>!$3	but not for .UUCP
R<%$+>$+		$:$>21<%$1>$2		Add route for local sender

##########################################################################
#
#	(Pseudo)DECnet mailer specification
#
#	Send all envelope recipients thru DECnet domain name flattener.

ifdef({DECNETNODES},{
# List of DECnet nodes
SET_CLASS({D},DECNETNODES)})


ifdef({LIUIDA},{dnl
# Since we don't have any Unix boxes with DECnet yet, we cheat...
MDECnet,  P=[IPC], F=CDFMXhnmpu, R=24/25, S=0/25, E=\r\n, A=IPC lisbet.liu.se
})dnl
ifdef({DECNETNAME},{
# Our DECnet name
{DB}DECNETNAME
{Cw}DECNETNAME{.dnet}

# We are a DECnet gateway.  Don't supply $u as mail11v3 speaks SMTP.
MDmail,	P=/usr/bin/mail11v3, F=CmnXNH, S=14, R=14, A=mail11 $f $x $h

############################################################
#
#	Mail-11 Mailer
#


S14
R<$=X$=w>$+			$:<$1$B.dnet>$3		Locals get DECNET name
R<>,$=X$+$=Y$+			<@$B.dnet>$3$4		Unqualifed locals.
R$*<$=X$+.dnet>$=Y@$+$=Y$+	$1$3::<@$5>$6$7		Reformat .dnet.
R$*<$=X$+.dnet>$=Y$+		$:$1$3::$5		Reformat .dnet.
R<$+>$+				$B::<$1>$2		Route non-dnet thru us
R$+::<$+>$+			$:$1::?$>4$>25<$2>$3	Format domain addresses
R$+::?$+			$:$1::?$2?$(@$&Q$2$&Q$)	Quote if any @ or %
R$+::?$+?$-			$@$1::$3		Success - return.
R$+::?$+?$*			$1::$2			Else don't quote.
R$+::$+@$+			$1::$2%$3		but change '@' to '%'.
})dnl

##########################################################################
#
#	UUCP mailer definitions

ifdef({M4COMMENTS},{dnl ### M4COMMENTS defined ###
# The contorted M4 code that follows has the following explanation:
#
# There may be a desire for the same 'newaliases.cf' to be used on
# many hosts at a site.  Consequently a stripped down M4 source is used,
# which does not include a UUCPNAME definition.  Hence we should not
# complain about the missing definition.
})dnl ### End of M4COMMENTS ###
# Our UUCP name
ifdef({UUCPNAME},{dnl
{Dk}UUCPNAME
{CU}UUCPNAME
{Cw}UUCPNAME{.UUCP}
},{dnl ### Not UUCPNAME ###
errprint({Warning: UUCPNAME is not defined.})dnl
# DkYourUUCP-Name if not correctly determined by sendmail.
# CUYourUUCP-Name
# CwYourUUCP-Name.UUCP
})dnl ### End - Not UUCPNAME ###

# List of known UUCP nodes
ifdef({UUCPNODES},{
SET_CLASS({U},UUCPNODES)})

# Header paths to the following well known UUCP relays should be trimmed.
ifdef({UUCPRELAYS},{
SET_CLASS({R},UUCPRELAYS)})

MUUCP, P=/usr/bin/uux, F=DFMUVpu, S=13, R=19/13, A=uux - -z -r $h!rmail ($u)
MUUCP-A, P=/usr/bin/uux, F=DFMmu, S=15/11, R=15/11, A=uux - -z -r $h!rmail ($u)
MUUCP-B, P=/usr/bin/uux, F=BDFMXmpu, S=0/11,  R=15/11, A=uux - -z -r $h!bsmtp

#########################################################################
#									#
#	Rule Set #13:	UUCP Mailer header rules			#
#									#
#	UUCP addresses are passed to ruleset 19.  But domain		#
#	addresses are retained in domain format where possible.		#
#									#
#	Since the V flag in the mailer definition will always		#
#	add or remove a 'host!' in front of the address, we ourselves	#
#	add a 'destination!' in front, which should then be removed.	#
#	If it is not removed, no great harm is usually done, since	#
#	it is the correct host name for the recipient domain, and	#
#	should be properly dealt with there.  If we do not do this	#
#	then user@dom.ain becomes ourselves!dom.ain!user which is	#
#	unnecessarily superfluous.  dom.ain!user should suffice.	#
#									#
#########################################################################
S13
R<$*>$+			$:$>19<$1>$2			Bangify address.
R<>,$=X$+!$+		$@<>,$1$k!$3			Our uuname for locals
R<$=X$=w>$+		$@<$1$k>$3			Our uuname on locals
R<@$-.UUCP>$+		$@<@$1.UUCP>$2			Return UUCP host.
ifdef({UUCPXTABLE},{dnl
R<@$+>$+		$:<@$1>$2?$(U$1$:$)		Is it in uucpxtable.
R<@$+>$+?$+		$@<@$1>$2			Yes - return.
R<@$+>$+?		$:<@$1>$2?$&h			Add recipient host.
},{dnl ### Not UUCPXTABLE ###
R<@$+>$+		$:<@$1>$2?$&h			Add recipient host.
})dnl ### End UUCPXTABLE ###
R<@$+.$=T>$+?$-		$@<@$4>!@$1.$2$3		Add route to domain.
R<@$+>$+?$*		<@$1>$2				Remove mark.

#########################################################################
#									#
#	Rule Set #15:	UUCP-A Mailer envelope rules.			#
#									#
#	This UUCP-A mailer is designed to give address formats as	#
#	close to Internet formats as possible.  However robustness	#
#	requirements, in the face of UUCP transport, place some		#
#	limitations.							#
#									#
#	Sender addresses are always formatted with !, but where the	#
#	domain has both a fully qualified name and a UUCP name, we	#
#	use the fully qualified name in the address.			#
#									#
#	Recipient addresses of the form 'user@fully.qual.domain' are	#
#	left in that form, but recipient addresses with UUCP origins	#
#	or with multiple hosts are converted to a '!' path, again	#
#	preserving the full domain name of the primary host where	#
#	possible.							#
#									#
#########################################################################
S15
R<%$+>$+		$:$>21<%$1>$2		Route UUCP senders thru us.
R<$=X$-.UUCP>$+		$@$>19<$1$2.UUCP>$3	If UUCP, bangify path.
R<$=X$->$+		$@$>19<$1$2>$3		Bangify unqualified.
R<>,$=X$+$=Y$+		<$1$2>$3$4		Show local domain.
R<$+>:$+		<$1>,$2			Change u%d to u@d
R<@$+>,$~A$*		$@<@$1>,$2$3		Return u@d recipient address.
# Bangify anything else.
R<$+>$+			$:$>19<$1>$2
ifdef({UUCPXTABLE},{dnl
### A domain with a fully qualified name may be converted back to its
### UUCP name by the UUCPXTABLE lookup.  To avoid this, we first format
### the address as 'bang!path@host' then convert the '@' back to a '!'.
R<$+>!$+		$:?$>4<$1>,$2		Convert to b!c@a and format.
R?$+@$+			$@$2!$1			Change '@' back to '!'
})dnl ### End UUCPXTABLE ###

##########################################################################
#
#	XNS Mailer -- this is still experimental.
#

MXNS,  {P=}XNSMAIL, F=CDFMXhnmprsu, R=16/0, S=16/0, A=xnsmail -q -O $u

# Convert address to XNS Object Name.
S16
R<$*>$+			$:$>4$>25<$1>$2		first externalize
R{$+@}XEROXNS		$@ $1			this is already an XNS addrs
R$+			$@ {$1:}XNSDOMAIN	add XNS domain for others


##########################################################################
## Standard Rewriting Rules ##############################################
##########################################################################

#########################################################################
#									#
#	Rule Set #0:	Mailer Resolving Ruleset			#
#									#
#	This is rather straightforward.  The code should say it all.	#
#									#
#	We do make two special cases.  Mail to 'user@localhost'		#
#	is delivered directly.  This is a way of bypassing the		#
#	forwarding to a mail server (if that option is in use).		#
#									#
#	If '$f' is not defined, mail routed through 'localhost' is	#
#	also sent to the local mailer.  This allows building of an	#
#	alias file with non-local aliasing, simply by routing the	#
#	address through 'localhost'.					#
#									#
#########################################################################
S0

# Force any routing thru localhost to be local.  Used for alias building,
# and to avoid sending to MAILSERVER.
ifdef({M4COMMENTS},{dnl
# NOTE:  If you are stuck with an old version of sendmail+IDA - one which
#	does not recognize $&x on the LHS of rewrite rules - change the
#	first rule below to:
# R<@localhost>,@$+$=Y$+	?$>29$>8<@$1>$2$3	Relativize
})dnl ### End of M4COMMENTS ###
R$&f<@localhost>,@$+$=Y$+	?$>29$>8<@$2>$3$4	Relativize
R?<@$=w>$=Y$+		?<>,$3				Remove local host
R?<$*>$+		$#LOCAL$@$w$:<$1>$2		and deliver.
R<@localhost>,$~A$*	$#LOCAL$@$w$:$1$2		Deliver forced local

R$+			$:$>8$1				Fully qualify.
# Digest routes through ourselves
R<@$+>$+		$:$>29 <@$1>$2			remove routed self

# Try immediate delivery
R<$*>$+			$:$>26 <$1>$2			try to find mailer
R$#$+			$# $1				found one, return it

ifdef({PATHTABLE},{# Unknown domain, try to find a pathalias route
R<@$+.$+>$+		$:$>22 <@$1.$2>$3		go get route
R<@$+>$+		$:$>29 <@$1>$2			remove routed self
R<$*>$+			$:$>26 <$1>$2			now look for mailer
R$#$+			$# $1				success, return it
})dnl ### End of PATHTABLE ###

ifdef({RELAY_HOST}, {# If we have a RELAY_HOST/RELAY_MAILER, use it
R<@$+>$+		${#}RELAY_MAILER $@RELAY_HOST $:<@$1>$2
})dnl

# Try TCP/IP otherwise, there might be an MX record for it
# (I wish I had a $[..$] for MX records)
R<@$+.$~P>$+		{$#}TCPMAILER $@$1.$2 $:<@$1.$2>$3

# Undeliverable recipients--complain loudly & return to sender
R$*<@>		$1			Remove unparseability marker.
R<@$->$+	$#ERROR $:Host $1 not known--please specify domain
R<@$-.$*$=T>$+	$#ERROR $:Host $1 not known within the $2$3 domain
R<@$-.$*$=P>$+	$#ERROR $:Host $1 not known within the $2$3 domain
R<@$+.$->$+	$#ERROR $:Domain $2 not known--please try to route manually
R@$+		$#ERROR $:"Incomplete Source Route--use <...> format"
R$*		$#ERROR $:Could not parse $1

#########################################################################
#									#
#	Rule Set #1:	[Envelope] Sender Specific Rewriting		#
#									#
#	There is an assumption by some software which may be used	#
#	as a local mailer, that for a local sender '$f' is the		#
#	actual sender login name.  Ruleset 1 thus hides the domain	#
#	of all local senders so that a mailer can easily recognize it	#
#	as local, and if in the phase of determining a value for '$f'	#
#	(as determined by '$f' being undefined), the hidden domain	#
#	is then stripped off.						#
#									#
#########################################################################
S1

R<@$+>$+		$:<%$1>$2		Indicate a sender address.
R$+			$:$>8$1			Fully qualify domain.
ifdef({FORCE_NAMED},{dnl
R<%$+>$+		$:$>23<%$1>$2		Simplify envelope senders.
})dnl ### End FORCE_NAMED ###
R<>,@$+			$:<>,%$1		Indicate sender for locals
R<%$=w>$=Y$~A$*		<>,%$1$2$3$4		Make locals recognizable
R$&f<>,%$+$=Y$+		$4			No domain on setting local $f

#########################################################################
#									#
#	Rule Set #2:	[Envelope] Receiver Specific Rewriting		#
#									#
#	Currently nothing.						#
#									#
#########################################################################
S2

#########################################################################
#									#
#	Rule Set #3:	Address Canonicalization			#
#									#
#	Turns the address into the (internally) canonical format.	#
#	See the documentation on ruleset #7 for a description of	#
#	the internal canonical format.					#
#									#
#	Input formats include the standard "mailbox@domain" format,	#
#	RFC822 Source Routes, RFC822 Group Names, ARPAnet %-Kludges,	#
#	UUCP !-Paths, the Berknet "host:user" format, the VAX/VMS	#
#	"host::user" format and resonable mixtures of the above.	#
#									#
#	The code even tries to clean up after various mistakes that	#
#	other nodes has done when reformatting the addresses, such	#
#	as mangled Xerox distribution lists or malformatted RFC822	#
#	Group Specifications.						#
#									#
#########################################################################
S3

# The first (experimental) rules deal with addresses processed in code
# because of the C-mailer flag, and recycled into ruleset 3.
R<>,$~A$*@$+		$1$2@$3			Clean up recycled address

# The next four rules come from nahaj@cc.utah.edu.  They are intended
# to transform "Name" <mailbox> "Phone number" into just mailbox
# But they must deal with extra level of <brackets> that are sometimes
# incorrectly added.  They must also deal with the fact that sendmail
# processes left to right, and becomes unhappy with anything not having
# <balanced brackets>.
R$*<$*>$*<$*>$*		<$2>$3$4$5		Remove right branches.
R$*<$*<$*>$*>$*		<$3>$5			Trim left branches.
R$*<>$*			Postmaster		default user
R$*<$*>$*		$2			Last level

# These are not for us
#R:{include}:$*@$*	$@<@$2>,:{include}:$1	indirect address
#R:{include}:$*		$@<@$w>,:{include}:$1	indirect address
# Above commented out.  Should be covered by the filename handling.
R$*/$*@$*		$@<@$3>,$1/$2		file name
R$*/$*			$@<@$w>,$1/$2		file name

# Fix group names and return them
R$+:;@$+		$:$1:;			remove host info
R$+:			$:$1:;			missing semicolon
R$+!;			$:$1:;			UUCP-style mangled group
R$+!$+:;		$2:;			remove UUCP host info
R$+:;			$@$1:;<@>		Finally return group

# Miscellaneous cleanup (sigh)
R$+!.$+			$1^.$2			fix mangled Xerox dList
ifdef({DECNETNAME}, {dnl ### Our DECNETNAME is defined ###
R$+::$B::$+		$B::$2			Shorten decnet route thru us
})dnl ### End DECNETNAME ###
R$-::$-			$1::$2?$(@$&Q$2$&Q$)	Is this decnet quoted 822?
R$-::$-?""$+@$+""	@$1.dnet:$3@$4		Convert quoted to source route.
R$-::$-?$+		$1::$2			Else restore
R$+::$+			$1.dnet!$2		Convert DECNET to bang path.
R$+!:$+@$+		$1!$3!$2		scrambled source route
R$+!:$+			$1!$2			mangled VAX/VMS address
ifdef({XEROXNS},,{
R$-:$-			$1!$2			Berknet style address
})
R$+:@$+			$1,@$2			slightly malformed src route
R$*$~Z@$+@$+		$1$2%$3@$4		fix user@host@relay
ifdef({LIUIDA},{
Renea!$+!!$+,!$+	enea!$1!!$2,@$3		brutally beaten src route
Renea!$+!!$+:$+!$+	$: enea!$1!$2!$4!$3	seriously smashed src route
Renea!$+!!$+		$: enea!@$2@$1		maddenly messy src route
})
R$+@$+.$=T.UUCP		$1@$2.$3		strip UUCP off foo@bar.EDU.UUCP
R$+@$+.$=P.UUCP		$1@$2.$3		strip UUCP off foo@bar.DNET.UUCP

# Fix %-kludgified RFC822 source routes (double sigh)
R$+!%$+:$+%$+		$1!%$2:$3@$4		change all %'s into @'s
R$+!%$+,%$+		$1!%$2,@$3
R$+!%$+			$1!@$2

R$+			$:$>7$1			Canonicalize address.

# The address should now be in the format <@domain>,...,user
# or, if there is no domain, in the format <>,@localhost,user

# Automatically route Grapevine and XNS addresses via resp gateways.
# Note that this assumes that there won't be any local users with dots
# or colons in their names; nor any such names in aliases.
ifdef({XEROXGV},{dnl
R<>,$-.$*		$:{<@}XEROXGV{>,$1.$2}	GW for Grapvine User.registry
})dnl
ifdef({XEROXNS},{dnl
R<>,$+:$*		$:{<@}XEROXNS{>,$1:$2}	XNS User:Domain:Organization
})dnl

#########################################################################
#									#
#	Rule Set #4:	Address PrettyPrinter				#
#									#
#	Does the final prettyprinting before the address is included	#
#	in the message.  (This is essentially a reformatting		#
#	from internal to external format)				#
#									#
ifdef({M4COMMENTS},{dnl
#	This rule set passes unchanged any valid address which is	#
#	full bracketed <address> or any valid address not containing	#
#	angle brackets.  This is important, as it allows a		#
#	mailer-specific ruleset to output format the address itself	#
#	and be sure that S4 does not further alter it.			#
#									#
#	Addresses resulting from S4 are NEVER enclosed in angle		#
#	brackets.  DO NOT CHANGE this, as a some mailer-specific	#
#	rule sets may call S4 internally, and depend on this.		#
#									#
#	This rule set will output any combination of @/!/%		#
#	including combinations which do not make sense.  It		#
#	assumes that the address has been reasonably formatted		#
#	in previous rule sets.						#
#									#
#	The basic algorithm is to first enclose everything in		#
#	<angle brackets>.  Then each domain is moved out, leaving	#
#	the unprocessed part treated as the "user" portion still	#
#	in brackets.  This approach permits a simple recursive		#
#	definition which is modified somewhat to allow iterative	#
#	processing where possible, and to handle the complexities	#
#	of the RFC822 source route format.				#
#									#
#	WARNING: Make sure the input to S4 presents different		#
#	formats of address in a reasonable order.  Otherwise S4		#
#	is quite capable of outputting addresses which are		#
#	hopelessly ambiguous.						#
},{dnl ### Not M4COMMENTS ###
#	More detailed documentation in the master configuration		#
#	file.								#
})dnl ### End M4COMMENTS ###
#									#
#	DO NOT ATTEMPT TO CHANGE S4 unless you fully understand it,	#
#	as it is a critical part of the whole configuration setup.	#
#									#
#########################################################################
S4

R$*<@>			$@$1			Return unparseables.
# If missing domain, attach local.
R<>,$=X$+$=Y$+		<@$2>$3$4		No host, add default.
R<>,$+			$@$1			Plain name, without domain.

R<$=X$+>$=Y$+		?<@$2?$3$4>		Insert marker
# We start with source routes; they are somewhat tricky.
R?$*<$+?,@$+$=Y$+>$*	$1<?:@$3?$4$5?$2?>$6	Insert several markers
R$+?:$+?,@$+$=Y$+?$+?$+	$1,$6?:@$3?$4$5?$2?$7	Process source rte
R$+?:$+?,$+?$+?$+	$:$1,$4?:$3??$2?$5	Process user (no @)
R$+?:$+?$*?$+?$+	?$1:?$2$3?$4$5		Remove extra marks
R?$*<$=Y$*?$+?$+>$*	$:?$1$3<$4>$5$6		Remove extra , or :
# The separator after "<@domain" cannot now be a comma, except in one case.
R?$*<$+?,$+>$*		$@$1$3$2$4		Return user@host
# The <..> part may (no src rte) or may not contain a "?".  Make it consistent.
R?$+?$+			?$1$2			Remove extra marks
R?$*<@$+$=Y$+>$*	$:?$1<@$2?$3$4>$5	Add mark for next step
# Next process ! paths.  These are more straight forward.
R?$*<@$+?!$+>$*		$:?$1?!<@$2?!$3>$4	Add mark for later use.
ifdef({UUCPXTABLE},{dnl
R?$+<@$+?!@$+$=Y$+>$*	?$1$(U$2$)!<@$3?$4$5>$6	Move UUCP host out
R?$+<@$+?!$+>$*		$:?$1$(U$2$)!<$3>$4	host!user
},{dnl ### Not UUCPXTABLE ###
R?$+<@$+?!@$+$=Y$+>$*	?$1$2!<@$3?$4$5>$6	Move UUCP host out
R?$+<@$+?!$+>$*		$:?$1$2!<$3>$4		host!user
})dnl ### End UUCPXTABLE ###
R?$*?$*!$-.UUCP!$+	?$1?$2!$3!$4		Remove unneeded .UUCP
R?$*?!$*<$+>$*		?$1$2<$3>$4		Remove extra markers.
# The % paths are the easiest.
R?$*<@$+?:@$+$=Y$+>$*	?$1<@$3?$4$5>%$2$6	Move %domain out
R?$*<@$+?:$+>$*		$@$1$3%$2$4		Return user%host
# There might be more left.
R?$*<@$+?$=Y$+>$*	$@$>4?$1<@$2?$3$4>$5	Recurse for more
# Finally, clean up
R?$+?$+			?$1$2			Remove extra marks
R?$*<$+>$*		$:$1$2$3		Remove <brackets>

#########################################################################
#									#
#	Rule Set #5:	[Header] Sender Specific Rewriting		#
#									#
#	Set a flag to indicate that this is a sender address.		#
ifdef({HIDDENNET},{dnl
#									#
#	Hide the host of local hidden net users.			#
})dnl ### End HIDDENNET ###
ifdef({GENERICFROM},{dnl
#									#
#	Translate local sender addresses to their generic		#
#	equivalents.							#
})dnl ### End of GENERICFROM ###
#									#
#	There is an assumption by some mailers (notably ucbMail)	#
#	that the 'From:' header will not have a domain for		#
#	local senders.  The sender domain, if local, is therefore	#
#	squirreled away where the mailer specific ruleset can		#
#	easily recognize and remove it if desired.			#
#									#
#########################################################################
S5

R$+			$:$>6$1				Qualify and simplify
ifdef({GENERICFROM},{dnl
# Use (canonicalized) generic names for local senders
R<$*>$=Y$+		$:<$1>$2$3?$>4<$1>,$3		Duplicate.
R<$*>$+?$+@$+		$:<$1>$2?$3@$4?			Add end marker.
R<@$=w>$=Y$+?$+?	$:$3<@$1>$2$3?$4?		Save userid of local
R<>,@$+$=Y$+?$+?	$:$3<>,@$1$2$3?$4?		Save userid of local
R$+?$+@$+.$-?		$1?$(G $2@$3.$4 $:$2@$3? $)	Search for each dom.
R$+?$+@$-?		$:$1?$(G $2@$3 $:? $)		Search for last dom.
R$+<$*>$+?$*?		$:$1<$2>$3?$(G $1 $:? $)	Search for locals.
R$*<$*>$+?$*?		<$2>$3				Not found-remove marks
R$*<$*>$+?$+		$:$>6$>3$4			Found - canonicalize
})dnl ### End of GENERICFROM ###
R<@$=w>$=Y$~A$*		<>,@$1$2$3$4			Make local recognizable
R<>,@$+			<>,%$1				Flag address as sender.
R<@$+>$+		<%$1>$2				Flag address as sender.

#########################################################################
#									#
#	Rule Set #6:	[Header] Receiver Specific Rewriting		#
#									#
ifdef({HIDDENNET},{dnl
#	Route domains which should be hidden through the hiding		#
#	host.  Useful in a network of work stations, where all		#
#	should use a common mail host address.				#
#	This applies only to users.  It does not apply to addresses	#
#	routed through a host on the hidden net.  (Possibly there	#
#	are different UUCP links on each host).				#
#	It might seem, at first, that only sender addresses should	#
#	be hidden.  But the Header recipient's may include many		#
#	alternate local recipients on the machine which should be	#
#	hidden on outbound mail.					#
},{dnl ### Not HIDDENNET ###
#	Currently nothing.						#
})dnl ### End HIDDENNET ###
#									#
#	To maximize flexibility, the basic rulesets do very little,	#
#	leaving most changes as options to the mailer specific		#
#	rulesets.							#
#									#
#########################################################################
S6

R<@$+>$+		<%$1>$2				Change mark to '%'.
R$+			$:$>8$1				Fully qualify domains.
R<%$+>$+		$:$>23<@$1>$2			Remove unneeded routing
ifdef({HIDDENNET},{dnl
ifdef({HIDDENNETHOST},{dnl
R<$=X$=H>$=Y$~A$*	?<$1$2>$3$4$5			Mark for hiding.
R?<$=X$=w>$+		{$@<>,$1}HIDDENNETHOST{$3}	Hide but mark as local
R?<$=X$+>$+		{$@<$1}HIDDENNETHOST{>$3}	Hide this domain.
R<>,$=X$=H$=Y$+		{$@<>,$1}HIDDENNETHOST{$3$4}	Hide default.
},{ifdef({DOMAINTABLE},{dnl ### Not HIDDENNETHOST, but DOMAINTABLE ###
R<$=X$=H>$=Y$~A$*	$@<$1$(N $w $)>$3$4$5		Hide this domain.
R<>,$=X$=H$=Y$+		$@<>,$1$(N $w $)$3$4		Hide default.
},{dnl ### Neither HIDDENNETHOST nor DOMAINTABLE ###
R<$=X$=H>$=Y$~A$*	$@<$1$w>$3$4$5			Hide this domain.
R<>,$=X$=H$=Y$+		$@<>,$1$w$3$4			Hide default.
})})})dnl ### End HIDDENNET ###

##########################################################################
## General rewriting subroutines #########################################
##########################################################################

#########################################################################
#									#
#	Rule Set #7: Canonicalize address.				#
#									#
#	This is a subroutine to S3.  After S3 has done basic		#
#	repairing of addresses it calls S7 to canonicalize.		#
#	S7 may also be called to canonicalize internal addresses.	#
#	DO NOT pass already canonical addresses to S7.  However		#
#	a semi-canonical address, beginning with @ (NOT %) may		#
#	be totally enclosed in <> angle brackets and passed to		#
#	S7 for re-canonicalization, although this should not		#
#	normally be needed.  Addresses canonicalized by S7		#
#	are not necessarily fully qualified (see rule set #8).		#
#									#
#	The general internal form of an address is a modified		#
#	RFC822 source route.  An address will be converted first	#
#	to the form:							#
#	  @host1,@host2,...@hostn,user    (Note the ',' not ':'		#
#					   which precedes user).	#
#	However, the ',' may not really be a ','.  It could also be	#
#	a ':' or a '!'.  The choice of ',',':', or '!' serves to define	#
#	how the host domain was delimited.  A ',' represents an '@',	#
#	a ':' represents a '%', and a '!' represents a '!'.		#
#									#
#	Note also that the modified form ends with just 'user', not	#
#	with 'user@domain'.  This format is easier to use internally.	#
#	After turning into a modified route, the immediate host is	#
#	single out with angle brackets.  This leaves an address of	#
#	the form <@host1>,@host,....,@hostn,user.			#
#									#
#	Finally ruleset's 1 and 5 convert the initial '@' into a	#
#	'%'.  This enables rewriting rules to more easily		#
#	distinguish between sender addresses (with a %) or		#
#	recipient addresses (with an @).				#
#									#
#	Ruleset #7 calls ruleset #9 to isolate the user portion		#
#	of an address.  Most of #7 deals with addresses for which	#
#	the user portion is enclosed in <>, and is already		#
#	canonicalized.  However it is possible to call #7 with the	#
#	user portion already isolated and canonicalized.		#
ifdef({PATHTABLE},{dnl ### PATHTABLE is defined ###
#	This is done in the PATHTABLE routing, where it is necessary	#
#	to merge two routes.						#
})dnl ### End PATHTABLE ###
#									#
#	When processing an address with the user portion enclosed,	#
#	ruleset #7 supports the following types of address:		#
#		<x>%b@a							#
#		a!b!<x>%c						#
#		@a,@b:<x>%d@c						#
#		a!b!@c,@d:<x>%f@e					#
#		b!c!<x>%d@a						#
#	However it does not support an address of the form		#
#		@a,@b:d!e!<x>@c						#
#									#
#	It should be pointed out that for a complete address with	#
#	the user portion not yet isolated, there is no such		#
#	restriction.  In that case, ruleset #9 will convert		#
#		@a,@b:d!e!x%f@c						#
#	into								#
#		@a,@b:<d!e!x%f>@c  (except that <d!e!x%f>		#
#			will be canonicalized.				#
#	This is now in a form ruleset #7 can handle.			#
#									#
#########################################################################
S7

# We first isolate the user portion of the address.
R$+			$:$>9$1			Isolate the user part.
R$*<>$*			$@$1$2<@>		Missing user? give up.
# Now we must canonicalize the address portion.  Start with some checking.
R$*%$*<$+>$*		$@$1%$2$3$4<@>		Should be no percent. give up.
R$*<$+>$*$=Y$*		$@$1$2$3$4$5<@>		No ,:! in domain of user@domain
R$*$~Y<$+>$*		$@$1$2$3$4<@>		Separator or nothing precede <.
# Take care of a!b!<user> or even a!b!@c,@d:<user>@domain
R$~A$*!@$*<$+>$*	@$1$2!@$3<$4>$5		a!source-rte -> @a!source-rte
R$~A$*!$*<$+>$*@$+	@$6,@$1$2!$3<$4>$5	b!<x>%c@a -> @a,@b!<x>%c
R$~A$*!$*<$+>$*		@$1$2!$3<$4>$5		domain!<user> -> @domain!<user>
R$+!$~A$*!$*<$+>$*	$1!@$2$3!$4<$5>$6	@a!b!<u> -> @a!@b!<u>
R$~A$*<$+>$*		$@$1$2$3$4<@>		Route must begin with @.
R$+:<$+>$*		$1,<$2>$3		Use , not : for routes
R$*<$+>$=X$+		$:?$1<$2>$3$4		Add marker.
R$*?$*<$+>%$+$=X$+	@$4:$1?$2<$3>$5$6	Convert %path to source rte
R$*?$*<$+>%$+		$:$2@$4:$1<$3>		Convert last '%'.
R$*?$*<$+>@$+		$:$2@$4,$1<$3>		Convert last '@'.
R$*<$+>$*		$1$2$3			Remove brackets.
# We should now have a modified route.  Pick out immediate host.
R@$+$=Y$+		$@<@$1>$2$3		If a host, select it.
R$+			$@<>,$1			Else null host.

#########################################################################
#									#
#	Rule Set #8: Qualify primary domain.				#
#									#
#	This rule set is called to fully qualify the domain of		#
#	the immediate host.						#
#									#
#########################################################################
S8

# For local users, add a default domain.
R<>,$~A$*		$@$>20<>,$1$2			Add default domain.
ifdef({BANGIMPLIESUUCP},{dnl
R<$=X$->!$+		$:<$1$2.UUCP>!$3		If !, add .UUCP
})dnl ### End of BANGIMPLIESUUCP ###
R<$+>$+			$:<$1?>$2			Add marker.
R<$=X[$+.$+]?>$+	<$1[$2.$3]>$4			[1.2.3.4] is ok.
ifdef({DOMAINTABLE},{dnl
R<$=X$*$~P?>$+		$:<$1$[ $2$3 $:$2$3? $]?>$4	First try resolver
R<$=X$+?$*>$+		$:<$1$(N $2 $:$2$3 $)>$4	Next domain table
},{dnl ### Not DOMAINTABLE ###
R<$=X$*$~P?>$+		$:<$1$[ $2$3 $:$2$3? $]>$4	First try resolver
})dnl ### End of Not DOMAINTABLE ###
ifdef({M4COMMENTS},{dnl
# The next three rules are intended to deal with those improperly configured
# workstations, which send out addresses of the form <user@unqualified>
# for sender addresses.  The idea is to check if $s is defined (the sending
# domain), and route these addresses through that domain.  The assumption is
# that this address format is understood by the sending domain.
# 
})dnl ### End M4COMMENTS ###
# Caution - next 3 rules MUST NOT apply to envelope recipients (mailing loops).
R<$=X$-?>$+		$:<$1$2?$&r?$&s>$3		What is sender domain?
# The $[ $] in next line is a crude fix for the fact that $&s is not tokenized.
R<%$-?SMTP?$+>$=Y$+	<%$[$2$]>,@$1:$4		Route unqualified.
R$&f<@$-?SMTP?$+>$=Y$+	<@$2>$4$5			Remove markers.
R<$=X$-?$+>$+		<$1$2?>$4			Remove extraneous data.
ifdef({BANGONLYUUCP},{dnl
ifdef({BANGIMPLIESUUCP},{dnl ### BANGONLYUUCP and BANGIMPLIESUUCP ###
ifdef({M4COMMENTS},{dnl
# Only qualify with .UUCP if the domain is delimited with !.
# But since BANGIMPLIESUUCP is in effect this has already been done.
# Therefore no extra qualification is required.
})dnl ### End M4COMMENTS ###
},{dnl ### BANGONLYUUCP but Not BANGIMPLIESUUCP ###
R<$=X$=U?>!$+		<$1$2.UUCP>!$3			Local UUCP host?
ifdef({PATHTABLE},{dnl ### PATHTABLE ###
R<$=X$-?>!$+		$:<$1$2?$(P $2 $: $)>!$3	Known in pathtable?
})ifdef({MAILERTABLE},{dnl ### MAILERTABLE ###
R<$=X$-?>!$+		$:<$1$2?$(M $2.UUCP $: $)>!$3	Known in mailertable?
R<$+?$+>$+		<$1.UUCP>$3			Add .UUCP if known
},{ifdef({PATHTABLE},{dnl ### PATHTABLE and MAILERTABLE ###
R<$+?$+>$+		<$1.UUCP>$3			Add .UUCP if known
})})dnl ### End of PATHTABLE/MAILERTABLE ###
})dnl ### End BANGONLYUUCP and Not BANGIMPLIESUUCP ###
},{dnl ### Not BANGONLYUUCP ###
R<$=X$=U?>$+		<$1$2.UUCP>$3			Local UUCP host?
ifdef({PATHTABLE},{dnl ### PATHTABLE ###
R<$=X$-?>$+		$:<$1$2?$(P $2 $: $)>$3		Known in pathtable?
})ifdef({MAILERTABLE},{dnl ### MAILERTABLE ###
R<$=X$-?>$+		$:<$1$2?$(M $2.UUCP $: $)>$3	Known in mailertable?
R<$+?$+>$+		<$1.UUCP>$3			Add .UUCP if known
},{ifdef({PATHTABLE},{dnl ### PATHTABLE and MAILERTABLE ###
R<$+?$+>$+		<$1.UUCP>$3			Add .UUCP if known
})})dnl ### End of PATHTABLE/MAILERTABLE ###
})dnl ### End Not BANGONLYUUCP ###
R<$*?$*>$*		<$1$2>$3			Remove marker

#########################################################################
#									#
#	Rule Set #9:    Isolate the user portion of an address		#
#									#
#	Given an address like a@b return <a>@b.  For a route address	#
#	of the form @a,@b,@c:x@d  return  @a,@b,@c:<x>@d .  The user	#
#	portion may contain % and !, but will not contain any @ symbol.	#
#	An address like a!b!x@c is ambiguous.				#
ifdef({UUCPPRECEDENCE},{dnl
#	By default, it is resolved as <a!b!x>@c giving the @		#
#	priority over the !.  This is the interpretation required	#
#	by RFC822.  However some UUCP nodes automatically add		#
#	'nodename!' to every address, even to addresses containing	#
#	an '@'.  Such nodes are identified by UUCPPRECEDENCE, and	#
#	these addresses are resolved as a!b!<x@c> giving		#
#	the ! priority over the @.					#
},{dnl ### UUCPPRECEDENCE Not Defined ###
#	Here it is resolved as <a!b!x>@c giving the @ priority		#
#	over the !, as required by RFC822.				#
})dnl ### End of Not UUCPPRECEDENCE ###
#	After isolating the user portion, that portion is finally	#
#	converted to internal route form.  Thus				#
#	 x%a%b@c becomes first <x%a%b>@c, and then is reformatted to	#
#	<@b:@a:x>@c.							#
#									#
#########################################################################
S9

R$*<$*>$*		$@$1<$2>$3		Already isolated: return
R$+			$:<$1>			First try user only.
R$*<$*@$+$=Y$*>		$1$2@$3$4<$5>		Skip past routing.
R$*<$*$~Y@$+>		$1<$2$3>@$4		user@domain
R$*<$+>@$+$=X$+		$@$>9$1$2%$3@$5		Fix badly mixed @ and %.
R$*<$*@$*>$*		$@$1$2@$3$4<>		Shouldn't happen. I give up.
R$*<$*%$*!$*>$*		$@$1$2%$3!$4$5<>	This shouldn't happen either.
ifdef({UUCPPRECEDENCE},{dnl
# Handle bad !/@ mixtures.
R<$=E!$+>@$+		$:<$1!$2>@$3?$1.UUCP?$&r	Add domain and protocol
R<$+!$+>@$+?$&s?UUCP	<$1!$2@$3>??		If matched move @domain into <>
R$*<$+!$+@$+>??		$1$2!<$3@$4>??		 and move bang path out.
R$*<$+>$*?$*		$1<$2>$3		Remove markers.
})dnl ### End of UUCPPRECEDENCE ###
# Uncomment the next line to give % higher precedence that ! in c!x%b@a
#R$*<$+!$+%$+>$+	$1<$2!$3>%$4$5		If @ has precedence, move % out
R$*<$+>$*		$:$1<?$2?>$3		Add markers to convert %, !
R$*<?$+@$+?>$*		$:$1<@$3,?$2?>$4	Convert u@d to @d,u
R$*<$*?$+!$+>$*		$1<$2@$3!?$4>$5		Convert a!b to @a!b.
R$+?$+%$+?$+		$:$1@?$3?:$2$4		Convert a%b to @b:a
R$+@?$+%$+?$+		$1@?$3?:@$2$4		Completely convert % path
R$+?$+			$1$2			Remove markers.

#########################################################################
#									#
#	Rule Set #19:	Translate domain addresses to UUCP !-paths	#
#									#
#	Takes an domain style address as input and transforms this	#
#	into a !-path.  There will be no atsign left in the address	#
#	after this, but there may(?) still be a percent sign.		#
#									#
#########################################################################
S19

R<$+>$=Y$+		$:<$1>!$3			Force bang formatting.
R<>,$=X$+$=Y$+		$:<>,$1$2!$4			Bang format for locals
R<$+>$*$=Y$~A$*		$:<$1>$2$3?$4$5			Mark user.
R<$+>$+@$-.UUCP:$*?$+	<$1>$2@$3.UUCP!$4?$5		Change % to ! for .UUCP
R<$+>$+@$-:$*?$+	<$1>$2@$3!$4?$5			Change to ! for unqual
R<$+>$+@$+,$*?$+	<$1>$2@$3!$4?$5			Use ! for real domains
R<$+>$+?$+		<$1>$2$3			Remove user mark.

#########################################################################
#									#
#	Rule Set #20:	Route addresses through us.			#
#									#
#	Route the address through us.  Done where it is necessary	#
#	for the address to use a registered domain.			#
#									#
#########################################################################
S20

ifdef({MAILNAME},{dnl ### Use MAILNAME in place of our host name ###
R<$=X$=w>$=Y$+		$@<$1{}MAILNAME{}>,$4		Use preferred name
R<$=X$+>$+		$@<$1{}MAILNAME{}>,@$2$3	Route through us
R<>,$~A$*		$@<>,@{}MAILNAME{},$1$2		We are default domain
},{dnl ### MAILNAME not defined
ifdef({DOMAINTABLE},{dnl
R<$=X$=w>$=Y$+		$@<$1$(N $w $)>,$4		If us, use default name
R<$=X$+>$+		$@<$1$(N $w $)>,@$2$3		Route through us
R<>,$~A$*		$@<>,@$(N $w $),$1$2		We are default domain
},{dnl ### Not DOMAINTABLE ###
R<$=X$=w>$=Y$+		$@<$1$w>,$4			If us, use default name
R<$=X$+>$+		$@<$1$w>,@$2$3			Route through us
R<>,$~A$*		$@<>,@$w,$1$2			We are default domain
})dnl ### End Not DOMAINTABLE
})dnl ### End not MAILNAME

#########################################################################
#									#
#	Rule Set #21:  Route local UUCP links, etc through us.		#
#									#
#	Extend this rule set as needed for locally connected		#
#	nodes which do not have internet addresses.			#
#									#
#########################################################################
S21

R<$=X$&h.UUCP>$+	$@<$1$2.UUCP>$3		Don't hide destination host
R<$=X$=U.UUCP>$=Y$+	$@$>20<$1$2.UUCP>!$4	Route local UUCP node thru us
ifdef({DECNETNODES},{dnl
R<$=X$=D>$+		$@$>20<$1$2>$3		Route local DecNET node thru us
})dnl ### End DECNETNODES ###
ifdef({UIUC},{dnl
# Provide an explicit gateway for hepnet
R<$=X$-.hepnet>$=Y$+	$@<$1garcon.cso.uiuc.edu>,@$2.hepnet:$4
})dnl

ifdef({PATHTABLE},{dnl
#########################################################################
#									#
#	Rule Set #22:	General Pathalias Router			#
#									#
#	Tries to find a route for an address using the pathalias	#
#	database.  It will return the complete (canonicalized)		#
#	route if found, or the same address otherwise.			#
#									#
#	See the comments in ruleset #7 for the types of addresses	#
#	that may appear in the pathalias database.			#
#									#
#########################################################################
S22

R<@$+>$+		?<@$1>$2				Insert marker.
# Search pathalias database
R?<@$-.UUCP>$=Y$+	$(P$1$@<$3>$:<@?$1.UUCP>$2$3$)		0th: UUCP host.
R?<@$+>$=Y$+		$(P$1$@<$3>$:<@?$1>$2$3$)		1st: Domain.
R<@$*?$-.$+>$+	$(P.$2.$3$@<@$1$2.$3$4>$:<@$1$2.?$3>$4$)	2nd: Subdomain
R<@$+?$->$+		$(P.$2$@<@$1$2$3>$:<@$1$2?>$3$)		nth: Top domain
# Check the results of our search.
R$*?$+			$@$1$2				Failed.  Return.
R$-!$+			$1.UUCP!$2			Qualify !-path w. UUCP
# We must now merge two possible routes, and canonical the result.
R$*<$+>$*		$@$>7$1<$2>$3			Canonicalize a!b!<user>
})dnl ### End PATHTABLE ###

#########################################################################
#									#
#	Rule Set #23:	Route prettyprinter & compressor.		#
#									#
#	This code comresses "obvious" routes whenever considered	#
#	necessary -- mostly just for aesthetical reasons, though.	#
#	If you don't like this, feel free to disable it.  Sendmail	#
#	shouldn't break, anyway.  (But there will probably be		#
#	others...)							#
#									#
ifdef({FORCE_NAMED},{dnl
#	If invoked with an address of the form <%domain>,xxx		#
#	the address is presumed to be that of an envelope sender	#
#	so the route stripping is less drastic than for header		#
#	addresses.  Consistent with RFC1123, superfluous routing is	#
#	removed from an RFC 822 source route.  UUCP routes through	#
#	a valid domain address are also eliminated.  This allows a	#
#	uucp neighbor whose mail leaves with a sender address of	#
#	'uunode!full.domain.name!user' to leave with a sender address	#
#	of 'user@full.domain.name' instead of the more complex and	#
#	unnecessary 'uunode!full.domain.name!user@our.domain.name'	#
#	The route stripping only occurs if the resulting domain		#
#	name can be validated either with the name server or		#
#	with our DOMAINTABLE.						#
#									#
})dnl ### End FORCE_NAMED ###
#########################################################################
S23

R<$+>$*$=Y$~A$*		$:<$1?>$2$3?$4$5	Mark user portion of address
ifdef({FORCE_NAMED},{dnl
R<%$+>$*:$*?$+		$:<%$1>$2?:$3$4		Move mark back past arpa kludge
})dnl ### End FORCE_NAMED ###
R<$+?>$+.$=T$=Y$*?$+	<$1$2.$3?>$4$5?$6	Find last top level domain
ifdef({UUCPRELAYS},{dnl
R<@$+?>$+@$=R!$*?$+	<@$1$2@$3?>!$4?$5	Last well known UUCP relay
})dnl ### End UUCPRELAYS ###
R$*<$+$=Y@$+>$+		$1$2$3<@$4>$5		Find begin of domain
R@$+<$+?>$*?$+		$@$>29$>8<$2>$3$4	Success - simplify.
ifdef({FORCE_NAMED},{dnl
R<%$+?>$*?$+		$@<%$1>$2$3		Failure - return.
R$+<@$+.$~P?>$+		$:$1<@$[$2.$3$:$2.$3?$]>$4	Known to name server?
ifdef({DOMAINTABLE},{dnl
R$+<@$+.$~P?>$+		$:$1<@$(N$2.$3$:$2.$3?$)>$4	Known in domain table?
})dnl ### End DOMAINTABLE ###
R$+$=Y$*<$+?>$*?$+	$@<$1>$2$3$4$5$6	Failure - reformat and return
R%$+<@$+>$*?$+		<%$2>$3$4		Success - simplify and return
})dnl ### End FORCE_NAMED ###
R<$+?>$*?$+		$@$>29<$1>$2$3		Failure - strip local routing.

ifdef({LIUIDA},{ifdef({DOMAINTABLE},{dnl
# LOCAL FIX: Strip header %-routes that paranoid instances of MM produce
R<@majestix.liu.se>$+$=Y@aida$=Y$+	$@<@$(N aida $)>$3$4	AIDA does this
R<@majestix.liu.se>$+$=Y@carmen$=Y$+	$@<@$(N carmen $)>$3$4	CARMEN too.

})})dnl ### End LIUIDA and DOMAINTABLE ###
ifdef({DECNETXTABLE},{dnl
#########################################################################
#									#
#	Rule Set #24:	Unqualify domains for DECnet nodes		#
#									#
#	This is needed since DECnet has a flat namespace.  All DECnet	#
#	nodes that are [externally] known to have a certain domain	#
#	name are unqualified to their corresponding DECnet host name.	#
#									#
#########################################################################
S24

R<$=X$+>$=Y$+		$:<$1$(D $2 $)>,?$4	Translate first.
R<$+>$+?@$+$=Y$+	<$1>$2@$(D $3 $):?$5	Translate other domains.
R<$+>$+?$+		<$1>$2$3		Remove marker.
ifdef({LIUIDA},{
# LOCAL FIX: The SUNET.SE domain only consists of DECnet nodes.
R<$+>$+@$-.SUNET.SE:$+		<$1>$2@$3:$4		*.SUNET.SE are on DECnet
R<$=X$-.SUNET.SE>$+		<$1$2>$3			ditto.
})})dnl ### End LIUIDA and DECNETXTABLE ###

#########################################################################
#									#
#	Rule Set #25:	Translate RFC822 Source Routes into %-Paths	#
#									#
#	This ruleset converts an address into a % route.		#
#									#
#########################################################################
S25

R<$+>$*$=Y$~A$*		$:<$1>$2$3?$4$5		Mark start of user field
R<$+>$=Y$+		$:<$1>,$3		No pure % paths please.
R<$+>,$+,$*?$+		<$1>,$2:$3?$4		Change source rte to %.
R<$+>,$+!$*?$+		<$1>,$2:$3?$4		Change ! format to %.
R<$+>$+?$+		<$1>$2$3		Remove mark.

#########################################################################
#									#
#	Rule Set #26:	Determine Mailer for Address			#
#									#
#	Takes an address in canonical format as input and returns	#
#	a complete mailer specification if a mailer is known for	#
#	the supplied domain.  Just returns the address otherwise.	#
#									#
#########################################################################
S26

# Reformat local addresses so easily recognized.
R<@$=w>$+		<>,@$1$2			Reformat locals
R<>,@$+$=Y$+		<>,$3				for easy recognition

# Search for possible global alias
R<$+>$=Y$~A$*		$:<$1>$2$3$4?$>4$>2<$1>,$3$4	externalize
R<$+>$+?$+		$:<$1>$2?$3?$(@ $3 $: $)	search aliases
R<$+>$+?$+?$+		<>,$3				Found, format as local
ifdef({NIS_MAILALIASES},{
# Not found, search for possible global alias in NIS mail.aliases map
R<$+>$+?$+?		$:<$1>$2?$3?$(% $3 $: $)	search NIS map
R<$+>$+?$+?$+		<>,$3				Found, format as local
})dnl ### End NIS_MAILALIASES ###
R$+?$*			$1				not found, remove marks

ifdef({NIS_MAILALIASES},{dnl
# We must not look up the aliases file while rebuilding it.  Hence the test
# on whether '$f' is defined.  If not just directly choose the local mailer.
# To test NIS mail.aliases expansion, use 'sendmail -bt -oMfnobody'
R$&f<>,$+		$#LOCAL $@$w $:$2		Build aliases locally.
# This local delivery may not really be local. Check the NIS mail.aliases map
R<>,$+			$:<>,$1?$(@ $1 $: ?$1 $)	See if in local aliases.
R<>,$+??$+		$:<>,$1??$(% $2 $:$)		Not local, check NIS map
R<>$+??$*,$*		{$#}TCPMAILER{$@}NIS_MAILHOST{$:<>$1}	Forward list.
R<>$+??$+@$=w		<>,$2				Handle as local.
R<>$+??$+		{$#}TCPMAILER{$@}NIS_MAILHOST{$:<>$1}	Else forward.
R<>,$+?$*		$:<>,$1				Not found, remove mark
})dnl ### End NIS_MAILALIASES

# Deliver to locals right away
ifdef({MAILSERVER},{dnl ### Send local mail to a server
# We must not look up the aliases file while rebuilding it.  Hence the test
# on whether '$f' is defined.  If not just directly choose the local mailer.
# To test MAILSERVER expansion, use 'sendmail -bt -oMfnobody'
R$&f<>,$+		$#LOCAL $@$w $:$2		Build aliases locally.
R<>,$*/$*		$#LOCAL $@$w $:$1/$2		File alias expansion.
R<>,|$*			$#LOCAL $@$w $:|$1		Program alias expansion.
R<>,$+			$:<>,$1?$(@ $1 $: $)		See if in local aliases.
ifelse(index(ALIASES,%),0,{dnl ### YP aliases in use.
R<>,$+?$*,$*		$:<>,$1?			Expand list on server.
R<>,$+?$+@$=w		$#LOCAL $@$w $:$1		Expand locals locally.
},{dnl ### Local alias file
R<>,$+?$+		$#LOCAL $@$w $:$1		Yes - deliver locally.
})dnl ### End YP aliases check.
R<>,$+?$*		{$#}TCPMAILER{$@}MAILSERVER{$:<@}MAILSERVER{>,$1}
})dnl ### End MAILSERVER ###
R<>,$+			$#LOCAL $@$w $:$1		local user

ifdef({MAILERTABLE},{dnl
###
###	Determine delivery over specific media
###
R<@$-$*>$+		$:<@$1?$2>$3?$(M$1$2$:$)	search mailer table
ifdef({M4COMMENTS},{dnl
#	This way of specifying domains is slightly incompatible with
#	the method used in the PATHTABLE code in ruleset #22.  Basically
#	an entry in the mailertable for .niu.edu would define a mailer
#	for cs.niu.edu, for whatever.cs.niu.edu, etc but it would not
#	define a mailer for niu.edu.  A separate entry in the 
#	mailer table would be needed for that.
#	This approach is chosen because (a) it is more flexible, and
#	(b) it is consistent with the way wildcard MX records are
#	interpreted in the domain name server database.
#
#	The pathtable code in ruleset #22 interprets an entry for .niu.edu
#	as also aliasing mail destined for niu.edu.  We have not tried to
#	change the pathtable code, as it must be consistent with output of
#	the 'pathalias' command as applied to the uucp map.
#
})dnl ### End M4COMMENTS ###
R<@$+?.$-$*>$+?		<@$1.$2?$3>$4?$(M.$2$3$@$1$:$)	Try partial domains.
R<@$+?$*>$+?$-:$+	$#$4 $@$5 $:$>28 <@$1$2>$3	relativize & return
R<@$+?$*>$+?$-,$+	$#$4 $@$5 $:<@$1$2>$3		return no-relativize
R<$+>$=Y$+?$-!$+	$#$4 $@$5 $:$>7 <$3>		relativize UUCP style
R<@$+?$*>$+?:$*		$@<@$1$2>$3			Null mailer, return.
# Hint. Selecting Null mailer from mailertable forces pathalias lookup
#	even if there is a valid TCP or UUCP route.
R<@$+?$*>$+?$+		$#ERROR $:$4			Bad entry - error.
# Hint. Above rule can bounce mail to specific hosts or domains.
R<@$+?$*>$+?$*		$:<@$1$2>$3			no match, remove mark

})dnl ### End of MAILERTABLE ###
###
###	Determine delivery over TCP/IP
###
R<@[$+.$+]>$=Y$+	$#TCP $@[$1.$2] $:$>7 <$4>	Handle numeric IN addr.
ifdef({ISOLATED_DOMAINS},{
R<@$*$=I>$+		$:<@$1$2>$3?$[ $1$2 $: $]	ask nameserver
R<@$+>$+?$+		{$#}TCPMAILER $@$3 $:<@$1>$2	found, return it
R<@$+>$+?$*		$:<@$1>$2			no match, remove mark
},{dnl ### Not ISOLATED_DOMAINS ###
R<@$*$~P>$+		$:<@$1$2>$3?$[ $1$2 $: $]	ask nameserver
R<@$+>$+?$+		{$#}TCPMAILER $@$3 $:<@$1>$2	found, return it
R<@$+>$+?$*		$:<@$1>$2			no match, remove mark
})dnl ### End Not ISOLATED_DOMAINS ###

ifdef({XNSDOMAIN},{dnl
###
###	Determine delivery over XNS
###
R<@}XEROXNS{>$+		$#XNS $@xnsmail $:<@}XEROXNS{>$1
})ifdef({DECNETXTABLE},{dnl
###
###	Determine delivery over DECnet
###	(Kludge: Should relativize too if we had a real DECnet connection)
###
R<@$+>$+		$:<@$1>$2?$(D $1 $: $)		check DECnet table
R<@$+>$+?$=D		$#DECnet $@$3 $:<@$1>$2		only return real ones
R<@$+>$+?$*		$: <@$1>$2			not found, remove mark
})dnl
ifdef({DECNETNAME},{dnl
# handle dnet stuff
R<@$+.dnet>$+		$#Dmail $@$1 $:<@$1.dnet>$2	dnet user
ifdef({UIUC},{dnl
R<@$+.decnet>$+		$#Dmail $@$1 $:<@$1.dnet>$2	dnet user
R<@$+.hepnet>$+		$#Dmail $@$1 $:<@$1.dnet>$2	dnet user
R<@$+.span>$+		$#Dmail $@$1 $:<@$1.dnet>$2	dnet user
})dnl ### End UIUC ###

})dnl ### End DECNETNAME ###
###
###	Determine delivery over UUCP
###	(Can't use ruleset 28 since we need to relativize immediate users)
###
ifdef({UUCPXTABLE},{# First try to translate full domain to uucp connection.
R<@$+>$+		$:<@$1>$2?$(U $1 $: $)		check UUCP table
R<@$+>$+?$=U		$:<@$3.UUCP>$2			replace if found real
R<@$+>$+?$*		$:<@$1>$2			not found, remove mark
})dnl ### End UUCPXTABLE ###
R<@$=U.UUCP>$=Y$+	{$#}UUCPMAILER $@$1 $:$>7<$3>	relativize & send.

#########################################################################
#									#
#	Rule Set #28:	One-level route stripper			#
#									#
#	Remove immediate host for routed addresses.  Typically used	#
#	in ruleset 26 to produce a recipient relative to the immediate	#
#	host.  Only to be used for routed full domains.			#
#									#
#########################################################################
S28

R<$=X$+>$=Y@$+$=Y$+		$:<$1$4>$5$6		relativize & return

#########################################################################
#									#
#	Rule Set #29:	Multi-level self route stripper			#
#									#
#	Remove immediate host for routed addresses if it is self.	#
#	Typically used in ruleset 0 to remove superfluous routing	#
#	info and produce a path relative to this host.			#
#									#
#########################################################################
S29

R$*/$*			$@$1/$2				Don't touch file name.
R<$=X$=w>$=Y@$+$=Y$+	$>8<$1$4>$5$6			Strip this host.
ifdef({ALTERNATENAMES},{# Remove superfluous routing through other of our names.
R<$=X$=M>$=Y@$+$=Y$+	$@$>29$>8 <$1$4>$5$6		Strip domain.
})dnl
# Might be us as numeric internet [...] address.  We only consider recipients.
R<@[$+.$+]>$+		$:<@[$1.$2]>$3?$[ [$1.$2] $]	Might be us numerically
R<@$+>$=Y@$+$=Y$+?$=w	$@$>29$>8 <@$3>$4$5		Remove routed [self]
R<@$+>$=Y$+?$=w		$:<>,@$1$2$3			move unrouted [self]
R<$+>$+?$*		<$1>$2				remove marker.