As is sometimes the case, this has turned a bit into going down a rabbit hole. 
I find the case now that it would be "really nice" to be able to also throw 
from addresses in the loop here. So basically, if the from address is 
a...@somewhere.com, then I want to relay X% of traffic to one relay as I've got 
working below. I looked at the pgsql_table man page, but it looks like it only 
takes in the to address for the %s for the transport map. I'm assuming there is 
other maps I can do for the from address, but I'm not sure if it's possible to 
create something that chains them together. I'm going to dive into the 
postfix.org docs to see if anything pops for me, but I figured I'd throw this 
out there in the hopes that better minds then I might have some ideas.

-----Original Message-----
From: owner-postfix-us...@postfix.org <owner-postfix-us...@postfix.org> On 
Behalf Of Sean Hennessey
Sent: Wednesday, November 30, 2022 11:38 PM
To: postfix-users@postfix.org
Subject: RE: Is there an easy way to "warm up" a new sending IP w/ Postfix

Viktor,

I want to thank you a million for this. I finally read up on the docs and got 
this working. I'm still going to do some more in depth testing, but my quick 
little testing seems to be doing exactly what I wanted.

-----Original Message-----
From: owner-postfix-us...@postfix.org <owner-postfix-us...@postfix.org> On 
Behalf Of Viktor Dukhovni
Sent: Tuesday, November 29, 2022 3:44 AM
To: postfix-users@postfix.org
Subject: Re: Is there an easy way to "warm up" a new sending IP w/ Postfix

On Mon, Nov 28, 2022 at 08:57:37PM +0000, Sean Hennessey wrote:

> I searched the list archives and saw the thread of gradual shift of 
> traffic from back in February of this year. That gives me some ideas, 
> but that seems to be for all traffic, not a subset.
> 
> I'd really like a way to send X% of gmail.com traffic to one relay and 
> the rest to another relay. Ditto for a couple of other major ESP's 
> like Yahoo, MS, etc...

If you're willing to spin up a small Postgres database (modulo typos on my part 
that should be easy to correct):

    query = SELECT U."transport"
            FROM (
                SELECT CASE WHEN floor(random()*100) <= T."weight"
                       THEN T."transport"
                       END AS "transport"
                FROM "transports" AS T
                WHERE T."domain" = '%s'
            ) AS U
            WHERE U."transport" IS NOT NULL;

Just populate a table:

    CREATE TABLE IF NOT EXISTS "transports" (
        "domain" TEXT PRIMARY KEY,
        "transport" TEXT NOT NULL,
        "weight" INTEGER NOT NULL
        );
    INSERT INTO "transports" ("domain", "transport", "weight")
    VALUES ( "gmail.com", "relay:[gmail-relay.example]", 99),
           ( "yahoo.com", "relay:[yahoo-relay.example]", 50),
           ... ;

And gradually lower the weights until, at weight 0, 99% of the traffic is 
direct to MX and just 1% of the traffic goes to the bypass relay and after that 
the row can be deleted.  Initially, at weight 99, all the traffic goes to the 
bypass relay.

If you want to specify a custom transport even after removing the relay, add a 
fourth (nullable) column and use that value in an ELSE clause of the CASE 
statement, in which case that value will be used when the bypass is not 
selected.

Keeping the Postgres database local to the MTA will improve performance and 
reliability.  I'd resist the temptation to centralise it, but that is an option 
if you're willing to have Postfix stall when a remote DB server is unreachable 
or slow, or can somehow avoid that.

It is not obvious to me, just at the moment, how to do this with the built-in 
Postfix randmap, pipemap, uniomap, ...

-- 
    Viktor.

Reply via email to