That's the basic idea behind MX records and mail exchangers, but there are a few more wrinkles you should know about. To avoid routing loops, mailers need to use a slightly more complicated algorithm than what we've described when they determine where to send mail.[2]
[2] This algorithm is based on RFC 974, which describes how Internet mail routing works.
Imagine what would happen if mailers didn't check for routing loops. Let's say you send mail from your workstation to [email protected], raving (or raging) about the quality of this book. Unfortunately, ora.ora.com is down at the moment. No problem! Recall ora.com's MX records:
ora.com. IN MX 0 ora.ora.com. ora.com. IN MX 10 ruby.ora.com. ora.com. IN MX 10 opal.ora.com.
Your mailer falls back and sends your message to ruby.ora.com, which is up. ruby's mailer then tries to forward the mail on to ora.ora.com, but can't, because ora.ora.com is down. Now what? Unless ruby checks the sanity of what she is doing, she'll try to forward the message to opal.ora.com, or maybe even to herself. That's certainly not going to help get the mail delivered. If ruby sends the message to herself, we have a mail routing loop. If ruby sends the message to opal, opal will either send it back to ruby or send it to herself, and we again have a mail routing loop.
To prevent this from happening, mailers discard certain MX records before they decide where to send a message. A mailer sorts the list of MX records by preference value and looks in the list for the canonical domain name of the host it's running on. If the local host appears as a mail exchanger, the mailer discards that MX record and all MX records in which the preference value is higher (that is, less preferred mail exchangers). That prevents the mailer from sending messages to itself or to mailers "farther" from the eventual destination.
Let's think about this in the context of our airport analogy. This time, imagine you're an airline passenger (a message), and you're trying to get to Greeley, Colorado. You can't get a direct flight to Greeley, but you can fly to either Fort Collins or Denver (the two next highest mail exchangers). Since Fort Collins is closer to Greeley, you opt to fly to Fort Collins.
Now, once you've arrived in Fort Collins, there's no sense in flying to Denver, away from your destination (a lower preference mail exchanger). (And flying from Fort Collins to Fort Collins would be silly, too.) So the only acceptable flight to get you to your destination is now a Fort Collins-Greeley flight. You eliminate flights to less preferred destinations to prevent frequent flyer looping and wasteful travel time.
One caveat: most mailers will only look for their local host's canonical domain name in the list of MX records. They don't check for aliases (domain names on the left side of CNAME records). Unless you always use canonical names in your MX records, there's no guarantee a mailer will be able to find itself in the MX list, and you'll run the risk of having your mail loop. If you send mail addressed to a particular domain name to a mailer that isn't configured to accept mail for that domain name, and it finds itself as the most preferred mail exchanger, it may bounce the mail with the error:
554 MX list for movie.edu points back to relay.isp.com 554 <[email protected]>... Local configuration error
This replaces the quainter "I refuse to talk to myself" error in newer versions of sendmail. The moral: in an MX record, always use the mail exchanger's canonical name.
One more caveat: the hosts you list as mail exchangers must have address records. A mailer needs to find an address for each mail exchanger you name, or else it can't attempt delivery there.
To go back to our ora.com example, when ruby received the message from your workstation, her mailer would have checked the list of MX records:
ora.com. IN MX 0 ora.ora.com. ora.com. IN MX 10 ruby.ora.com. ora.com. IN MX 10 opal.ora.com.
Finding the local host's domain name in the list at preference value 10, ruby's mailer would discard all the records at preference value 10 or higher (the records in bold):
ora.com. IN MX 0 ora.ora.com. ora.com. IN MX 10 ruby.ora.com. ora.com. IN MX 10 opal.ora.com.
leaving only:
ora.com. IN MX 0 ora.ora.com.
Since ora.ora.com is down, ruby would defer delivery until later, and queue the message.
What happens if a mailer finds itself at the highest preference (lowest preference value), and has to discard the whole MX list? Some mailers attempt delivery directly to the destination host's IP address, as a last-ditch effort. In most mailers, however, it's an error. It may indicate that DNS thinks the mailer should be processing (not just forwarding) mail for the destination, but the mailer hasn't been configured to know that. Or it may indicate that the administrator has ordered the MX records incorrectly by using the wrong preference values.
Say, for example, the folks who run acme.com add a mail exchanger record to direct mail addressed to acme.com to a mailer at their Internet Service Provider:
acme.com. IN MX 10 mail.isp.net.
Many mailers need to be configured to identify their aliases and the names of other hosts they process mail for. Unless the mailer on mail.isp.net is configured to recognize email addressed to acme.com as local mail, it will assume it's being asked to relay the mail and attempt to forward the mail to a mail exchanger closer to the final destination.[3] When it looks up the MX records for acme.com, it'll find itself as the most preferred mail exchanger, and return the mail to the sender. Then it will bounce the mail with the familiar error:
[3] Unless, of course, mail.isp.net's mailer is configured not to relay mail for unknown domains.
554 MX list for acme.com points back to mail.isp.com 554 <[email protected]>... Local configuration error
Many versions of sendmail use class w or fileclass w as the list of "local" destinations. Depending on your sendmail.cf file, adding an alias can be as easy as adding the line
Cw acme.com
to sendmail.cf. If your mailer uses another mail transport, such as UUCP, to deliver mail to the hosts it acts as a mail exchanger for, this will probably require more involved configuration.[4]
[4] Configuring UUCP, while beyond the scope of this book, is covered in Using & Managing uucp, by Ed Ravin, published by O'Reilly & Associates (1996).
You may have noticed that we tend to use multiples of ten for our preference values. Ten is convenient because it allows you to insert other MX records temporarily at intermediate values without changing the other weights, but otherwise there's nothing magical about it.