diff --git a/scripts/_email_exclusions.py b/scripts/_email_exclusions.py index 85ee257..ded5fa1 100644 --- a/scripts/_email_exclusions.py +++ b/scripts/_email_exclusions.py @@ -1,10 +1,17 @@ """Shared recipient-domain exclusions for outbound cold-email campaigns. We self-host our MTA (transactional relays like SES forbid cold email), so we -must protect our sending-IP reputation manually. The single biggest lever is -NOT mailing the Yahoo/Verizon-Media family: those providers aggressively defer -cold senders with "unexpected volume / user complaints" 421 responses, which -poisons the IP for every other provider too. +must protect our sending-IP reputation manually. The two biggest levers: + + 1. NOT mailing the Yahoo/Verizon-Media family: those providers aggressively + defer cold senders with "unexpected volume / user complaints" 421 + responses, which poisons the IP for every other provider too. + 2. NOT mailing Google CONSUMER mailboxes (gmail.com etc.) from a cold/warming + IP: Google hard-rejects them with 550-5.7.1 "this message is likely + unsolicited mail", and those rejections are reputation-damaging. (On + 2026-06-08 a warmup audit found gmail.com alone was 77% of our 550-5.7.1 + blocks -- 427 of 556.) Custom domains hosted on Google Workspace are a + smaller, MX-only signal handled separately in the per-vertical builders. Keep this list authoritative and import it everywhere we build audiences. """ @@ -29,9 +36,19 @@ YAHOO_FAMILY_DOMAINS: frozenset[str] = frozenset({ "frontier.com", "frontiernet.net", }) +# Google consumer mailboxes. Google's cold-IP spam filter (550-5.7.1) is the +# strictest of the big providers; consumer gmail accounts have the highest +# complaint sensitivity. We hold these out of cold/warmup sends. (This is the +# domain-string layer; custom domains silently on Google Workspace need an MX +# lookup and are handled in the per-vertical builders, e.g. the healthcare +# mx_provider flag.) +GOOGLE_CONSUMER_DOMAINS: frozenset[str] = frozenset({ + "gmail.com", "googlemail.com", +}) + # The full set of consumer domains we refuse to cold-mail. Extend here as we # discover other reputation-sensitive providers. -BLOCKED_EMAIL_DOMAINS: frozenset[str] = YAHOO_FAMILY_DOMAINS +BLOCKED_EMAIL_DOMAINS: frozenset[str] = YAHOO_FAMILY_DOMAINS | GOOGLE_CONSUMER_DOMAINS def domain_of(email: str) -> str: