diff --git a/scripts/build_trucking_campaigns.py b/scripts/build_trucking_campaigns.py index 3dd896e..b255c1d 100644 --- a/scripts/build_trucking_campaigns.py +++ b/scripts/build_trucking_campaigns.py @@ -331,9 +331,25 @@ TEST_EMAIL = os.getenv("CAMPAIGN_TEST_EMAIL", "carrierone@gmx.com") REPLY_TO_EMAIL = os.getenv("CAMPAIGN_REPLY_TO", "info@performancewest.net") REPLY_TO_HEADERS = [{"name": "Reply-To", "value": REPLY_TO_EMAIL}] +# Which verification results are safe to SEND to. We key ONLY off +# email_verify_result, never the email_verified boolean: the verifier sets +# email_verified=TRUE optimistically for 'mx_unreachable' (domain exists but its +# mail server didn't answer the probe) — those addresses HARD-BOUNCE when we +# actually send, which is what tanked deliverability (≈47% bounce, half the list +# blocklisted). So 'mx_unreachable' and all error/reject results are excluded. +# +# Recovery mode (default ON while reputation is damaged): send ONLY 'smtp_valid' +# — addresses an MX explicitly accepted at RCPT time — to drive the bounce rate +# to near-zero and rebuild sender reputation. Once recovered, set +# CAMPAIGN_INCLUDE_CATCH_ALL=1 to re-add catch-all domains (which accept at SMTP +# time but can still bounce later, so they stay out during recovery). +_SENDABLE_RESULTS = ["smtp_valid"] +if os.getenv("CAMPAIGN_INCLUDE_CATCH_ALL", "0") not in ("0", "false", ""): + _SENDABLE_RESULTS += ["catch_all_domain", "catch_all_detected"] USABLE_FILTER = ( - "(email_verified IS TRUE OR email_verify_result IN " - "('smtp_valid','catch_all_domain','catch_all_detected'))" + "email_verify_result IN (" + + ", ".join(f"'{r}'" for r in _SENDABLE_RESULTS) + + ")" ) DB_URL = os.getenv("DATABASE_URL", "")