Here are a few examples of how a randmap(8) pseudo-delivery agent
could be used to distribute inbound or outbound mail across multiple
gateways.

(begin flash-back)
    Yesterday I introduced a design for a randmap lookup table,
    which randomly selects lookup results from a file with one
    result per line, like this:
         something = randmap:/file/name

    Small tables can be specified "in-line", like this:
         something = randmap:!result1!result2...
    where text to the right of ":" is split into lookup results,
    using the first character of that text as the separator.
(end flash-back)

The randmap(8) pseudo-delivery agent works as follows: it gets a
mail delivery request, and uses a randmap lookup to determine how
and where to deliver that mail.

First, two examples of outbound mail via one gateway with one or
more A records:

    relayhost = [out-gw.example]
    default_transport = smtp:[out-gw.example]
 
Next, using a randmap(8) pseudo-delivery agent to do the same via
multiple gateways, 1:1 weights:

    relay_transport = randmap:!smtp:[out-gw1.example]!smtp:[out-gw2.example]

Inbound mail via one gateway with multiple A records:

    /etc/postfix/main.cf:
        transport_maps = hash:/etc/postfix/transport

    /etc/postfix/transport:
        example.com   smtp:[in-gw.example]
 
Inbound mail via multiple gateways, 1:1 weights:

    /etc/postfix/main.cf:
        transport_maps = hash:/etc/postfix/transport

    /etc/postfix/transport:
        example.com   randmap:!smtp:[in-gw1.example]!smtp:[in-gw2.example]

Finally, an example with 1:2 weights, for outbound mail via multiple
gateways:

    relay_transport = 
        randmap:
            !smtp:[out-gw1.example]
            !smtp:[out-gw2.example]
            !smtp:[out-gw2.example]

(randmap ignores leading and trailing whitespace).

If we build the randmap(8) pseudo-delivery agent into trivial-rewrite(8),
then it can be done with very little code, and it plays nice with the
queue manager's concurrency policy.

The downside of building randmap(8) into trivial-rewrite(8) is that
the trivial-rewrite daemon returns only one next-hop destination
to the queue manager.  If that next-hop destination is dead, mail
will be deferred even though other randmap destinations are working.

Instead one could move randmap lookups into the SMTP client:

    /etc/postfix/main.cf:
        transport_maps = hash:/etc/postfix/transport

    /etc/postfix/transport:
        example.com   smtp:randmap:![in-gw1.example]![in-gw2.example]

The downside of moving randmap lookups into the SMTP client is that
it does not play nice with the queue manager's concurrency policy,
just like specifying multiple hostnames as the SMTP next-hop
destination did not play nice (and therefore was not implemented).

    /etc/postfix/transport:
        example.com   smtp:[in-gw1.example],[in-gw2.example]

Note that none of the above multi-nexthop solutions for inbound
mail take advantage of SMTP connection caching, which can avoid
severe performance degradation when some of several inbound relays
are down.  To fix that, the SMTP client would need built-in awareness
of multiple next-hop destinations, randmap lookups, or equivalent.

        Wietse

Reply via email to