From b9b963f87bdff41e208859253f1b5a2411765452 Mon Sep 17 00:00:00 2001 From: justin Date: Sun, 14 Jun 2026 21:35:58 -0500 Subject: [PATCH] trucking: extend big-operator exclusion to day 30 (reputation recovery) Main pool is calendar-day 12 but reputation is wrecked (54% delivery, Gmail+ Outlook blocks) -- NOT warmed. MX tagging confirmed the cause: 702k carriers on Google + 135k on Microsoft = the warmup was hammering exactly the two operators blocking us. Hold Google/MS/Proofpoint/etc. OUT entirely until day 30 (configurable), sending only to the long-tail operators (yahoo/comcast/charter/centurylink/etc.) that don't bot-throttle, so reputation can recover; then re-introduce big operators gradually via mx_daily_caps. 1.24M/1.49M carriers now tagged. --- scripts/build_trucking_campaigns.py | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/scripts/build_trucking_campaigns.py b/scripts/build_trucking_campaigns.py index 148f202..3dd896e 100644 --- a/scripts/build_trucking_campaigns.py +++ b/scripts/build_trucking_campaigns.py @@ -175,12 +175,17 @@ _COUPON_ALPHABET = "ABCDEFGHJKLMNPQRSTUVWXYZ" # no I/O to avoid confusion # EXCLUDE those big operators entirely (send to the long tail of small/self-hosted # mail systems that don't bot-throttle), then cap per-operator once reputation is # established. mx_provider is populated by mx_tag_carriers.py. -# Set MAIN_SKIP_BIG_MX=0 to stop excluding once warmed up. +# Set MAIN_SKIP_BIG_MX=0 to stop excluding once truly warmed up. MAIN_SKIP_BIG_MX = os.getenv("MAIN_SKIP_BIG_MX", "1") not in ("0", "false", "") # Operators to hold out during warmup (they aggressively throttle/blocklist). BIG_MX_OPERATORS = ("google", "microsoft", "proofpoint", "mimecast", "barracuda", "cisco", "broadcom") MAIN_WARMUP_START_FILE = os.getenv("MTA_WARMUP_START_FILE", "/etc/postfix/pw-warmup-start") +# How many days to EXCLUDE the big operators entirely. The Jun 13-14 block storm +# means reputation is NOT yet established despite a high calendar day count, so we +# hold Google/Microsoft/etc. out until day 30 to let reputation recover on the +# long-tail operators first, then re-introduce them gradually via mx_daily_caps. +MAIN_BIG_MX_EXCLUDE_UNTIL_DAY = int(os.getenv("MAIN_BIG_MX_EXCLUDE_UNTIL_DAY", "30")) def main_warmup_day() -> int: @@ -192,13 +197,17 @@ def main_warmup_day() -> int: def mx_daily_caps(day: int) -> dict: - """Per-operator daily NEW-recipient caps, ramping with the warmup day. Big - operators are EXCLUDED during early warmup (see MAIN_SKIP_BIG_MX); these caps - apply once they're re-enabled.""" - if day <= 6: big, default = 0, 40 # big operators OFF, long tail only - elif day <= 13: big, default = 60, 80 - elif day <= 20: big, default = 150, 150 - else: big, default = 300, 250 + """Per-operator daily NEW-recipient caps. Big operators are EXCLUDED entirely + until MAIN_BIG_MX_EXCLUDE_UNTIL_DAY (reputation recovery), then re-introduced + gradually. 'default' is the per-operator cap for the long tail.""" + if day <= MAIN_BIG_MX_EXCLUDE_UNTIL_DAY: + big, default = 0, 120 # big OFF; long-tail operators carry volume + elif day <= MAIN_BIG_MX_EXCLUDE_UNTIL_DAY + 7: + big, default = 40, 150 # re-introduce big slowly + elif day <= MAIN_BIG_MX_EXCLUDE_UNTIL_DAY + 14: + big, default = 120, 200 + else: + big, default = 300, 250 caps = {op: big for op in BIG_MX_OPERATORS} caps["__default__"] = default return caps @@ -728,7 +737,7 @@ def fetch_carriers( # selector still bounds them, and excluding NULLs would starve the pool until # tagging completes. big_mx_exclude = "" - if MAIN_SKIP_BIG_MX and main_warmup_day() <= 6: + if MAIN_SKIP_BIG_MX and main_warmup_day() <= MAIN_BIG_MX_EXCLUDE_UNTIL_DAY: ops = ",".join("'%s'" % o for o in BIG_MX_OPERATORS) big_mx_exclude = f"AND (mx_provider IS NULL OR mx_provider NOT IN ({ops}))"