From 97f6a08183c3dce90b63dd55dc3fbf8c0dafee30 Mon Sep 17 00:00:00 2001 From: justin Date: Sat, 30 May 2026 14:52:22 -0500 Subject: [PATCH] Bind email verifier to secondary IP (.72) for SMTP probes Campaign emails send from .71 via Postfix (now explicitly bound). Verification RCPT TO probes go from .72 to protect sending reputation. Configurable via VERIFY_SOURCE_IP env var. Co-Authored-By: Claude Opus 4.6 (1M context) --- scripts/workers/email_verifier.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/scripts/workers/email_verifier.py b/scripts/workers/email_verifier.py index 64cab33..61398b8 100644 --- a/scripts/workers/email_verifier.py +++ b/scripts/workers/email_verifier.py @@ -40,6 +40,8 @@ logging.basicConfig( DATABASE_URL = os.environ.get("DATABASE_URL", "postgresql://pw:pw@localhost:5432/performancewest") OUR_DOMAIN = "performancewest.net" OUR_EMAIL = f"verify@{OUR_DOMAIN}" +# Bind SMTP probes to secondary IP so campaign sending IP (.71) stays clean +VERIFY_SOURCE_IP = os.environ.get("VERIFY_SOURCE_IP", "207.174.124.72") # Regex for basic email validation EMAIL_RE = re.compile(r"^[a-zA-Z0-9._%+\-]+@[a-zA-Z0-9.\-]+\.[a-zA-Z]{2,}$") @@ -108,7 +110,7 @@ def verify_email(email: str) -> tuple[bool, str]: # Step 4: SMTP handshake + catch-all detection for mx_host in mx_hosts[:2]: # Try first 2 MX servers try: - with smtplib.SMTP(timeout=10) as smtp: + with smtplib.SMTP(timeout=10, source_address=(VERIFY_SOURCE_IP, 0)) as smtp: smtp.connect(mx_host, 25) smtp.helo(OUR_DOMAIN) code, _ = smtp.mail(OUR_EMAIL)