DEV Community

Cover image for Engineering Deliverability: Building a Cold Email Verification Pipeline with Python
Rajat Datta
Rajat Datta

Posted on

Engineering Deliverability: Building a Cold Email Verification Pipeline with Python

Cold email is a delivery problem,not a copy problem. Here’s how I built a Python-powered verification pipeline that increased my agency’s open rates from 3% to 42%.

The Pipeline Architecture:

  1. Input: Raw lead list (CSV/API).
  2. Stage 1 – Syntax & MX Check: Validate email format and domain MX records.
  3. Stage 2 – API Validation: Use a service like NeverBounce or Hunter.
  4. Stage 3 – DNS Record Audit: Check recipient domain’s SPF/DKIM/DMARC.
  5. Output: Clean, verified list ready for sending.

Core Code Snippet (Python - Conceptual):

`import dns.resolver
import requests
import pandas as pd
from typing import Dict, List

class EmailVerificationPipeline:
def init(self, hunter_api_key: str):
self.hunter_api_key = hunter_api_key

def check_mx_record(self, domain: str) -> bool:
"""Check if domain has valid MX records."""
try:
answers = dns.resolver.resolve(domain, 'MX')
return bool(answers)
except:
return False

def verify_via_hunter(self, email: str) -> Dict:
"""Use Hunter.io API for verification."""
url = f"<https://api.hunter.io/v2/email-verifier?email={email}&amp;api_key={self.hunter_api_key}&gt;"
response = requests.get(url).json()
return response.get('data', {})

def audit_dns_security(self, domain: str) -> Dict:
"""Check for SPF, DKIM, and DMARC records."""
records = {}
for record_type in ['TXT', 'SPF', 'DKIM', '_dmarc']:
try:
answers = dns.resolver.resolve(f"{record_type}.{domain}" if record_type == '_dmarc' else domain, 'TXT')
records[record_type] = [str(r) for r in answers]
except:
records[record_type] = None
return records

def process_list(self, emails: List[str]) -> pd.DataFrame:
"""Main pipeline function."""
results = []
for email in emails:
domain = email.split('@')[1]
mx_valid = self.check_mx_record(domain)
hunter_data = self.verify_via_hunter(email)
dns_audit = self.audit_dns_security(domain)

    # Decision Logic
    deliverability_score = 0
    if mx_valid and hunter_data.get('status') == 'valid':
        deliverability_score = 85
    if dns_audit.get('_dmarc'):
        deliverability_score += 15

    results.append({
        'email': email,
        'mx_valid': mx_valid,
        'hunter_status': hunter_data.get('status'),
        'has_dmarc': bool(dns_audit.get('_dmarc')),
        'deliverability_score': deliverability_score
    })
return pd.DataFrame(results)
Enter fullscreen mode Exit fullscreen mode
Enter fullscreen mode Exit fullscreen mode




Usage

pipeline = EmailVerificationPipeline(hunter_api_key='YOUR_KEY')
df = pipeline.process_list(['ceo@example.com', 'fake@notadomain.cc'])
clean_list = df[df['deliverability_score'] >= 85]['email'].tolist()
`
This pipeline becomes the mandatory gatekeeper for all outbound. No verification, no send.

I'm documenting the full $12k debt war. Steal the Zero-Employee System here: DRYPAPERHQ.COM.

Top comments (0)