Setting Up an HP-UX Mail Hub
I had two sendmail(1M) problems to solve on a network
systems. First, the site name needed to be hidden. Mail
an HP system got stamped as coming from user@localsystem
of user@centralsystem, and since local systems weren't
outside the company's network, replies never arrived.
HP system effectively stood alone, although they could
talk with each
other across the network. There was little centralization
or directories across the systems. However, making mail
was only one small part of this problem. Users logging
in on one system
were deposited in a home directory local to that system.
If a user
sent mail from any HP system while logged in on that
system, the mail
would go to the receiver's account on that same local
eight HP systems, each collecting mail for every user
I faced a mess.
A network of Sun systems had been set up with greater
If mail was sent to any user on a Sun, smail(8) forwarded
it to the user's Sun mail account. But smail, although
with sendmail, wasn't set up on the HPs. With a limited
of time to finish this problem and move on to the next,
it would be faster to fix the HPs' sendmail.cf files
to hunt for a version of smail that would work on HPs.
HP-UX uses /usr/lib instead of /etc, as its holding
directory for sendmail. No HP system would serve mail
plan. The mail hub, which happened to be a Sun, would
do that. First,
I had to make sure that none of the slave systems was
sendmail daemon. I checked the boot script, /etc/netbsdsrc
on HP-UX, to be sure that sendmail would not restart
next reboot. HP uses many scripts for booting that don't
with Sun's single rc.local or with System V's rc directory
organization. If you aren't sure which boot script starts
you can discover it with the following command:
egrep sendmail `file /etc/* | egrep text | cut -d: -f1`
This makes the system search through all files identified
as text files to find out which script contains sendmail.
If booting has already started the sendmail daemon,
I kill it on every
system except the hub. Only systems that expect to receive
an outside source need to run the daemon. Because none
of the HP systems
will receive -- they'll only send -- none needs the
When new mail goes out, the mailer will run sendmail
My next step is to arrange for every /usr/lib/sendmail.cf
to be identical. The following command line shows the
between two files across two systems (assuming a user
in to system1):
remsh system2 cat /usr/lib/sendmail.cf | diff /usr/lib/sendmail.cf -
This command logs onto another system (system2)
to deliver that other system's sendmail.cf file to diff.
remsh(1), HP-UX's version of rsh(1C on Sun), runs the
side of a pipeline on the local system, not the remote
you must run the entire pipeline on the remote system,
pipeline argument with quotation marks. Assuming that
the system you're
currently logged onto contains the sendmail.cf you want
make central, you could put this command inside a loop
the system name following remsh. Then, if any differences
show up, you can decide whether to incorporate them
into the central
file. When you've finished with all modifications, including
outlined in this article, you'll rcp(1) the central
all the other systems.
Arranging site hiding was the simplest part of my task.
already provides a macro for site hiding: DY. By default,
DY is not set. The SMTP (Simple Mail Transfer Protocol)
delivery agent uses the Y definition when it sends mail
(to see this use, search for the regular expression
in HP's sendmail.cf). Two rulesets, S11 and
S21, associate with the tcp delivery agent via the flags
and R=21. S11 rewrites the sender's address and S21
rewrites the receiver's address. In S11, the last rule,
R$+, uses $Y to add the local domain name defined
by DY. With DY defined as
this rule changes mail sent from larryr@system1
into firstname.lastname@example.org. People receiving such messages
now simply reply to get their response back to me, no
system I'm really logged onto -- once all the mail is
centrally, that is.
To put the mail files in a central location, create
on the mail hub system. Combine all the mail files from
systems into one file on the hub system. Check with
your users and
throw the old mail files out if you can. When in doubt,
the files together on the hub system and notify the
users with /etc/motd
or news that all users should clean out their mail files.
Once all the files are combined on the hub, mount the
hub's mail directory
or add it to the automount list.
Routing to the Hub
Routing mail to the mail hub turned out to be the tedious
the job. Essentially, I chose to disable local mailing
on every HP.
I didn't want to embed the hub system's name in every
alias: I thought
that would cause more trouble with respect to future
fixing sendmail. Instead, I decided to route all mail
would have been local through the tcp delivery agent
the sendmail.cf file. Once in the tcp agent, sendmail
rulesets will route the mail to the mail hub. That plan
until I found that the rulesets didn't want to go to
the remote mail
I wanted to route the mail to mailhost, the common host
for the mail hub as defined in the NIS hosts map. By
using the mailhost
alias, I could ensure that if the system hosting mail
in the future, the sendmail.cf files wouldn't need changing.
Instead, I could just change whichever system in the
map was aliased
as mailhost, push the new map, and sendmail would
get it. Everybody's happy.
No such luck. Referring to mailhost works in the rule
calls the tcp agent. Once in the tcp agent's rule,
the @host part of the address must have a primary host
not a host alias. Give that tcp agent rule a host alias,
as mailhost, and the mailer bounces it as an unknown
Not everything in HP-UX's mail system uses host aliases.
Implementing Hub Routing
HP's sendmail.cf defines a macro for SMTP relay: DS.
You can set the S macro to your hub's host name -- for
where hostname is the first name in the hosts
map for the mail host. Don't use a host alias here,
such as mailhost:
it won't work. Macro S gets used in ruleset 0, which
out what delivery agent to use based on the address.
By default, any address containing a domain not resolved
rules in ruleset 0 get resolved by a rule that looks
R$+<@$+> $#tcp$@$2$:$1<@$2> user@domain
This confusing-looking mess divides into three fields
separated by tabs. The first field is the incoming address,
in a notation
similar to regular expressions. The second field contains
for translating the incoming address. Comments go in
the third field.
The first field begins with R, which identifies it as
$+ matches one or more tokens up to a less-than (<)
followed by an "at" sign (@). After the "at"
expect one or more tokens followed by a greater-than
(>) symbol. Each
$+ match from the first field can be referred to by
field, by means of a positional notation. $1 is the
match (everything up to the less-than symbol in this
rule), and $2
is the second (everything between the "at"
sign and the greater-than
symbol for this rule).
Previous rules have already turned a simple address,
for instance, into a tcp-ready format like larryr<@system1>
and sent the address on to other rules. Rules like this
route the address to the delivery agent using the second
$# specifies the delivery agent, tcp in this
rule. sendmail must now find Mtcp and use its S= or
R= rules, depending on whether it is resolving the sender
address or the receiver address. $# is the first part
of a three-part rule. The second part uses $@ to tell
the name of the receiving host. The third part begins
to identify the receiving user. Assume that the matching
by the rule's first field is name<@host>. This
the delivery agent tcp, makes the host host, and makes
the user name<@host>.
Consider that host is the name of the local system.
contains nothing to force mail delivery to the hub system.
agent tcp happily delivers to the local host just as
as it delivers to any host. Look two rules further down
and you'll find another rule with an identical first
but it's commented out. This rule's comment in the third
that the rule relays to SMTP. Without the comment, the
R$+<@$+> $#tcp$@$S$:$1<@$2> user@domain to SMTP relay
Look carefully at the second field. It differs from
previous rule in only one way: it uses $S instead of
as the receiving host. That's the S macro. With the
macro's value set to the mail hub's host name, tcp will
it to that hub system. The local system will have nothing
do with it.
To set this up, comment out the local routing rule containing
and uncomment the SMTP routing rule containing $@$S
So far so good, but local routing hasn't been eliminated.
No More Local Routing
At the end of ruleset 0 is the catchall rule that nothing
R$+ $#local$:$1 name
The first field contains only $+, to match any
incoming address that has at least one token. Every
address has at
least one token, except an error address typically caught
sendmail processing by another rule. If some earlier
hasn't intercepted and modified the address by now,
rule gets it.
According to the catchall rule's second field, an incoming
is submitted to the local delivery agent ($#). No
host ($@) is specified, only a user ($:),
composed of the entire matching incoming address, is
can find the local delivery agent's handler if you search
regular expression "^Mlocal" in sendmail.cf.
You'll need to comment out this local rule by starting
this rule line
with a # sign. If a plain name comes along, it could
be a user name
or a mail alias. Either way, the mail hub must receive
it and figure
that out, not the local system. This ultimate, catchall
submit the address to the tcp delivery agent. Add the
R$+ $#tcp$@$R$:$1 Forward to mail hub
This new catchall rule uses an R macro, defined
where mailhost is literally the alias name of
the mail hub host. I recommend placing this definition
near the S
Strictly, I could have used the S macro in this rule,
Initially, I tried setting S to mailhost and using
$S throughout the changes outlined in this article.
sendmail didn't cooperate. While this catchall tcp rule
work with mailhost, other rules wouldn't accept that
alias. While debugging the problem, I defined the R
macro to use mailhost and set the S macro to the host's
primary name. This worked. Not wanting to challenge
Murphy any further,
I kept it this way. If you're uncomfortable with yet
substitute $S for $R. If anyone knows a rule combination
that uses the mailhost alias throughout, please write.
The tcp delivery agent will receive all that previously
to the local delivery agent. With a receiving host specified
tcp will route the address to the mailhost. Local systems
using these rules will not attempt any further processing
of the address
except according to the tcp agent's rules.
There's no need to modify or comment out the local delivery
or its rules. Some X.400 rules still use the local agent,
HPs I administer aren't using those.
Fixing the tcp Delivery Agent
Find the tcp delivery agent line (search for regular
"^Mtcp"). The receiver rule, which modifies
address, is identified with R=21 in my HP sendmail.cf
file. Ruleset 21 (search for regular expression "^S21")
be several lines below the tcp delivery agent line.
Ruleset 21 consists of only two rules. The first rule
already containing a domain name. Such addresses didn't
come to the
tcp delivery agent from the catchall rule that sends
to the local agent. The second rule is important for
routing to the
mail hub. Any addresses that used to go to the local
agent get caught
by this second rule. Before my modification, this rule
R$+ $:$1<@$w> add local domain
As before, the first field ($+) acts
as a catchall. The $: at the beginning of the second
doesn't have the same interpretation as it has in the
set. Here, $: means "Rewrite Once." Typically,
are applied repeatedly, as the input data needs. Using
prevents more than one application of the same rule.
Once this $:
rule finishes rewriting the address, sendmail must go
A sendmail intrinsic macro, $w, is set to the local
system's host name. If larryr is the matched token,
turns it into larryr<@localhost>, where localhost
refers to the local system's host name. When a sender
logged in on
system1 mails to larryr, this rule changes larryr
to larryr<@system1>. This is definitely wrong
for mail hub
routing. This rule must refer to the mail host, not
the local host.
To fix this, comment out the existing rule that uses
add the following new rule:
R$+ $:$1<@$S> add mailhost
The only difference in this rule is its use of $S.
Again, I would have liked to use mailhost in $R but
that didn't work here.
Once I had finished and tested all sendmail.cf modifications,
I rcp'd /usr/lib/sendmail.cf to all the other HP systems
that will route to the mail hub. With these changes
in place, both
mail addressing problems were solved.
All sender addresses appear to originate from the company's
name server. Replies go back to that name server, which
to get to the mail hub for proper routing to the user's
All receiver addresses, whether including domain references,
simple user names, or using mail aliases, are routed
to the mail hub.
As a side effect, local systems don't have to know the
Any alias is routed to the mail hub. That mail hub resolves
and routes the mail. When given an unknown alias, the
hub system has
a proper sender address to return the mail.
I strongly recommend the book sendmail, by Bryan Costales,
published by O'Reilly and Associates, 1993, ISBN: 1-56592-056-2.
book was indispensable. Documentation on sendmail is
to find and sometimes virtually unreadable. HP-UX's
has extensive comments that help, but often each answer
Costales' book gives detailed instructions on how sendmail
explains the meanings of sendmail's macros, rules, and
definitions, identifies debugging methods, and includes
throughout. The index is thorough, with every intrinsic
expression symbol identified. At times, the index acted
as a quick
reference list for me.
Finally, sendmail doesn't suffer from the SunOS bias
O'Reilly books have. As much as I like Suns, there are
out there and I work on a variety of them. Costales'
variations in sendmail across many versions. Without
this book, I couldn't have solved the problems outlined
in this article
About the Author
Larry Reznick has been programming professionally since
1978. He is currently
working on systems programming in UNIX, MS-DOS, and
He teaches C, C++, and UNIX language courses
at American River College and at the University of California,