Postfix Trick to Force Secondary MX to Deliver Locally

Wednesday 9 January 2008 by Bradley M. Kuhn

Suppose you have a domain name,, that has a primary MX host ( that does most of the delivery. However, one of the users, who works at, actually gets delivery of <> at work (from the primary MX for, Of course, a simple .forward or /etc/aliases entry would work, but this would pointlessly push email back and forth between the two mail servers — in some cases, up to three pointless passes before the final destination! That's particularly an issue in today's SPAM-laden world. Here's how to solve this waste of bandwidth using Postfix.

This tutorial here assumes you have a some reasonable background knowledge of Postfix MTA administration. If you don't, this might go a bit fast for you.

To begin, first note that this setup assumes that you have something like this with regard to your MX setup:

            $ host -t mx
   mail is handled by 10
   mail is handled by 20
            $ host -t mx
   mail is handled by 10

Our first task is to avoid SPAM backscatter on To do that, we make a file with all the valid accounts for and put it in (For more information, read the Postfix docs or various tutorials about this.) After that, we have something like this in

            relay_domains =
            relay_recipient_maps = hash:/etc/postfix/relay_recipients
And this in /etc/postfix/transport:

This will give proper delivery for our friend <> (assuming is forwarding that address properly to <>), but mail will push mail back and forth unnecessarily when gets a message for <>. What we actually want is to wise up so it “knows” that mail for <> is ultimately going to be delivered locally on that server.

To do this, we add <> to the virtual_alias_maps, with an entry like:

so that the key resolves to the local username user. Fortunately, Postfix is smart enough to look at the virtual table first before performing a relay.

Now, what about aliases like <>, that actually forwards to <>? That will have the same pointless forwarding from server-to-server unless we address it specifically. To do so, we use the transport file. of course, we should already have that catch-all entry there to do the relaying:


But, we can also add email address specific entries for certain addresses in the domain. Fortunately, email address matches in the transport table take precedence over whole domain match entries (see the transport man page for details.). Therefore, we simply add entries to that transport file like this for each of user's aliases:

(Note: that assumes you have a delivery method in called local. Use whatever transport you typically use to force local delivery.)

And there you have it! If you have (those albeit rare) friendly and appreciative users, user will thank you for the slightly quicker mail delivery, and you'll be glad that you aren't pointlessly shipping SPAM back and forth between MX's unnecessarily.

Posted on Wednesday 9 January 2008 at 12:01 by Bradley M. Kuhn.

Submit comments on this post to <>.

Creative Commons License This website and all documents on it are licensed under a Creative Commons Attribution-Share Alike 3.0 United States License .

#include <std/disclaimer.h>
use Standard::Disclaimer;
from standard import disclaimer
SELECT full_text FROM standard WHERE type = 'disclaimer';

Both previously and presently, I have been employed by and/or done work for various organizations that also have views on Free, Libre, and Open Source Software. As should be blatantly obvious, this is my website, not theirs, so please do not assume views and opinions here belong to any such organization. Since I do co-own with my wife, it may not be so obvious that these aren't her views and opinions, either.

— bkuhn

ebb is a service mark of Bradley M. Kuhn.

Bradley M. Kuhn <>