"""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. Keep this list authoritative and import it everywhere we build audiences. """ from __future__ import annotations # Yahoo / Verizon Media operates ALL of these consumer domains. Legacy AT&T and # Frontier consumer mail was handed off to Yahoo's infrastructure as well. YAHOO_FAMILY_DOMAINS: frozenset[str] = frozenset({ # Yahoo / AOL core "yahoo.com", "yahoo.com.mx", "yahoo.es", "yahoo.it", "yahoo.ca", "myyahoo.com", "ymail.com", "rocketmail.com", "aol.com", "aol.com.mx", "aim.com", "love.com", "games.com", "wow.com", "netscape.net", "netscape.com", "cs.com", "compuserve.com", # AT&T family (Yahoo-hosted) "att.net", "sbcglobal.net", "bellsouth.net", "pacbell.net", "ameritech.net", "swbell.net", "snet.net", "flash.net", "prodigy.net", "wans.net", "nvbell.net", # Verizon family (Yahoo-hosted) "verizon.net", "verizongni.com", "bellatlantic.net", # Frontier (Yahoo-hosted) "frontier.com", "frontiernet.net", }) # 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 def domain_of(email: str) -> str: """Return the lowercased domain part of an email, or '' if malformed.""" if "@" not in email: return "" return email.rsplit("@", 1)[-1].strip().lower() def is_blocked(email: str) -> bool: return domain_of(email) in BLOCKED_EMAIL_DOMAINS