Receiving mail from other domains using Sendmail

Posted by: Andrew Smith
Poster contact info: andrew-smith at mail ru
Author: same as 'Posted by'
Software: Sendmail 8.13.6

Scenario

John had his own email server in his house (Postfix on SuSE i think, but doesn't matter which kind). One day John's ISP messed up, leaving him not only without an internet connection but without a phoneline also. We want to give John a temporary solution to his email server down problem.

This article describes how to set up DNS and Sendmail to accept email from a second domain. It's not pretty but very easy to set up and starts working as soon as the DNS gets updated.

Let's say John's dead server is john.ca and mine is andrew.ca Obviously my server has to keep running as it used to.

DNS

First things first. Before you can receive mail on andrew.ca that's supposed to go to john.ca you need to update the global DNS entries for john.ca to point to the IP address used by andrew.ca

If you're running a server at home you are probably at least somewhat familiar with DNS setup. If you are a dynamic DNS client, this is easy. John used to have a static IP so it was harder.

We logged in to his domain name registrar's (the one he paid for the domain name) website and updated the A records for www and @ to point to the IP address of andrew.ca

I believe it was possible to update only the MX entry so just the mail is sent somewhere else and the rest of the servers (web, ssh, etc) are still unreachable. But we were in a hurry and didn't feel like experimenting.

That was all the setup required. Unfortunately there is no way to force the DNS entries to update ahead of schedule on every server on the planet, so it can take on average 1-2 days for the redirect to start working. See the end of the article for my solution to go around My ISP's DNS server cache.

To check that the DNS got updated ping john.ca and see if the IP address it's trying to ping is actually andrew.ca It's not a problem to have more than one domain name for one IP address.

Users

Mail going to john.ca has to end up in a user's mailbox on andrew.ca so we have to set up a user account. On my server mail users are local users so I just had to useradd john The username doesn't matter, see the next section for details.

Sendmail

I am running my own mail server also, but my ISP isn't giving me any trouble. The mail server of choice was Sendmail because it comes with Slackware 10.1. The server was updated, patched and recompiled to allow for SMTP authentication (Cyrus SASL) but I'm pretty sure that had nothing to do with this scenario. So let's say Sendmail is a default build of version 8.13.6

There are two sendmail config files we need to change. The first is /etc/mail/virtusertable which will redirect mail for anyone at john.ca to a local user on andrew.ca In my case I wanted mail for all john.ca users to go into the same mailbox, so I just had to add one line, the file now looks like this (note that is a tab not spaces in between):
@john.ca   john

That's saying all mail going to john.ca will end up in john@andrew.ca If you want multiple mailboxes for different john.ca users, you can have them though it may be overkill for a temporary solution. Let's say we want john@john.ca to go to john@andrew.ca and jane@john.ca to go to jane@andrew.ca and everyone else to pile@andrew.ca:
john@john.ca   john
jane@john.ca   jane
@john.ca       pile

Of course you have to first create the john, jane and pile users on andrew.ca

The second Sendmail config file we have to edit is /etc/mail/local-host-names I'm not sure why that's necessary, but Sendmail will refuse to accept mail for john.ca otherwise. Just add one line, so now that file will look like this:
john.ca

Don't forget to run make in /etc/mail/ so that the config files are recompiled into the respective .db files.

And that's it! Once the DNS for john.ca updates, all mail will arrive and if John's lucky none of it will be lost during the downtime. According to some sources you don't even have to restart Sendmail after updating those config files, but I restarted it anyway just to be sure.

Errors

I dug into my log files and extracted a bunch of errors from while I was trying to set this up.
I think this one was happening before the DNS was updated and john.ca was pointing to the old address:
Dec  1 18:13:59 andrew sm-mta[11909]: kB1NDsF7011907: to=<john@john.ca>,
ctladdr=<andrew@andrew.ca> (1000/100), delay=00:00:04, xdelay=00:00:04,
mailer=esmtp, pri=120347, relay=john.ca. [12.34.56.78], dsn=5.0.0, 
stat=Service unavailable
Dec  1 18:14:00 andrew sm-mta[11909]: kB1NDsF7011907: kB1NE0F6011909: DSN:
Service unavailable
This one I don't remember what was causing it:
Dec  1 18:39:05 andrew sm-mta[12047]: kB1Nd4R3012047: ruleset=check_rcpt,
arg1=<postmaster@john.ca>, relay=abc.net
[82.158.226.68], reject=550 5.7.1 <postmaster@john.ca>... Relaying denied.
Proper authentication required.
This one was happening before I updated /etc/mail/local-host-names
Dec  2 01:09:25 andrew sm-mta[19947]: kB269Oeb019945: SYSERR(root):
john.ca. config error: mail loops back to me (MX problem?)

Fancy DNS Solution

Before starting this work we made a mistake and pinged john.ca from andrew.ca. This had an unfortunate consequence: the DNS server for andrew.ca's ISP cached the old IP address associated with john.ca so even though everything was set up properly and people from around the world could send mail to john.ca my server andrew.ca thought john.ca's IP address was the old one so it would stupidly try to forward mail to a non-existant server (despite the config file changes described above). What to do?

First I tried to find a way to force my ISP's DNS server to expire john.ca and get the new IP from the root server. Apparently there's no way to do that unless you want to call up your ISP and they are in a good mood. I didn't want to bother so I came up with a different solution.

I set up a default BIND server on my local network. All it had to do was proxy all DNS requests to the root servers, or to the ISP's server, doesn't matter. The default BIND package on Slackware (and other distros I suspect) does this. The neat thing is that when BIND gets a resolve request it first checks the /etc/hosts file and if it finds the host in there it doesn't bother the real DNS servers. So all I had to do was:
- add 12.34.56.78 john.ca to /etc/passwd on my local DNS server (where 12.34.56.78 is the public IP address for andrew.ca)
- add nameserver 10.0.0.1 as the first line in /etc/resolv.conf on andrew.ca where 10.0.0.1 is the address of my local DNS server

So now whenever andrew.ca needed to find out the IP of john.ca it would first ask my local DNS server which would look it up in the hosts file and return the proper address and I would no longer have to wait for my ISP's DNS entry to expire.

I hope this was useful to you, good luck with your setup.