Proxies for Cold Email Infrastructure: Warming and Deliverability

Proxies for Cold Email Infrastructure: Warming and Deliverability

Cold email remains one of the most effective B2B outreach channels when executed properly. The critical challenge is deliverability — getting your emails into the prospect’s inbox rather than their spam folder. Email warming services, domain reputation monitoring, and multi-inbox management all benefit from proxy infrastructure that isolates each sending domain’s digital fingerprint.

This guide covers how mobile proxies integrate into cold email infrastructure for warming, deliverability monitoring, and multi-account management.

Cold Email Infrastructure Architecture

A production cold email system has five layers:

[Domain Setup] → [Email Warming] → [List Building] → [Sending] → [Monitoring]

Each layer involves web-based activities that benefit from proxy isolation.

Domain and Mailbox Setup

Professional cold email operations use multiple domains to distribute sending volume and protect the primary business domain:

Primary: company.com (never used for cold email)
Cold 1: getcompany.io
Cold 2: trycompany.co
Cold 3: companymail.net
Cold 4: company-solutions.com

Each domain needs 2-3 email accounts (e.g., john@getcompany.io, sarah@getcompany.io), with each account sending a maximum of 30-50 emails per day.

Email Warming with Proxies

Email warming tools like Instantly, Warmbox, and Mailwarm simulate real email conversations to build sender reputation before cold outreach begins. Proxies are critical for managing multiple warming accounts.

Why Proxies Matter for Warming

Warming services require you to log into each email account via their web interface or IMAP/SMTP. When you manage 10-20 email accounts from the same IP address, email providers (especially Google and Microsoft) correlate those accounts and may flag them as a spam network.

from playwright.async_api import async_playwright
import asyncio
import random

class EmailWarmingManager:
    """Manage email warming across multiple accounts with proxy isolation"""

    def __init__(self, accounts, proxy_pool):
        self.accounts = accounts
        self.proxy_pool = proxy_pool

    async def setup_warming_account(self, account, proxy_config):
        """Set up a single email account on warming service"""
        async with async_playwright() as p:
            browser = await p.chromium.launch(
                proxy=proxy_config,
                headless=False,
            )
            context = await browser.new_context(
                viewport={"width": 1920, "height": 1080},
                locale="en-US",
            )
            page = await context.new_page()

            # Navigate to warming service
            await page.goto("https://instantly.ai/login")
            await page.wait_for_timeout(random.randint(2000, 4000))

            # Login
            await page.fill('input[name="email"]', account["warming_email"])
            await page.fill('input[name="password"]', account["warming_password"])
            await page.click('button[type="submit"]')
            await page.wait_for_timeout(random.randint(3000, 6000))

            # Add email account for warming
            await page.click('text="Add Account"')
            await page.wait_for_timeout(random.randint(1000, 3000))

            # Fill IMAP/SMTP details
            await page.fill('[name="email"]', account["email"])
            await page.fill('[name="imapHost"]', account["imap_host"])
            await page.fill('[name="imapPort"]', str(account["imap_port"]))
            await page.fill('[name="smtpHost"]', account["smtp_host"])
            await page.fill('[name="smtpPort"]', str(account["smtp_port"]))
            await page.fill('[name="password"]', account["email_password"])

            await page.click('text="Save"')
            await page.wait_for_timeout(random.randint(3000, 5000))

            await browser.close()

    async def setup_all_accounts(self):
        """Set up warming for all accounts with isolated proxies"""
        for i, account in enumerate(self.accounts):
            proxy = self.proxy_pool.get_sticky_proxy(f"warming_{i}")
            proxy_config = {
                "server": proxy["url"],
                "username": proxy["username"],
                "password": proxy["password"],
            }
            await self.setup_warming_account(account, proxy_config)
            await asyncio.sleep(random.uniform(30, 60))

Warming Schedule

Follow a gradual warming schedule before beginning cold outreach:

WeekDaily Warming EmailsDaily Cold EmailsTotal Daily
1-25-1005-10
315-205-1020-30
420-2515-2035-45
5+20-3025-4045-70

Never exceed 50 total emails per day per account. Keep warming running continuously even after cold campaigns begin.

Deliverability Monitoring

Inbox Placement Testing

Use proxy-isolated email accounts to test where your emails land:

import imaplib
import email

class DeliverabilityTester:
    """Test email deliverability across major providers"""

    def __init__(self, test_accounts, proxy_pool):
        # Test accounts at Gmail, Outlook, Yahoo, etc.
        self.test_accounts = test_accounts
        self.proxy_pool = proxy_pool

    def check_inbox_placement(self, test_email_subject):
        """Check where a test email landed across providers"""
        results = {}

        for account in self.test_accounts:
            proxy = self.proxy_pool.get_next()
            placement = self.check_single_account(
                account, test_email_subject, proxy
            )
            results[account["provider"]] = placement

        return results

    def check_single_account(self, account, subject, proxy_url):
        """Check a single test account for email placement"""
        try:
            mail = imaplib.IMAP4_SSL(account["imap_host"])
            mail.login(account["email"], account["password"])

            # Check inbox
            mail.select("INBOX")
            _, inbox_msgs = mail.search(None, f'SUBJECT "{subject}"')
            if inbox_msgs[0]:
                return {"placement": "inbox", "provider": account["provider"]}

            # Check spam
            mail.select("[Gmail]/Spam")  # Gmail-specific
            _, spam_msgs = mail.search(None, f'SUBJECT "{subject}"')
            if spam_msgs[0]:
                return {"placement": "spam", "provider": account["provider"]}

            # Check promotions (Gmail)
            mail.select("[Gmail]/Promotions")
            _, promo_msgs = mail.search(None, f'SUBJECT "{subject}"')
            if promo_msgs[0]:
                return {"placement": "promotions", "provider": account["provider"]}

            mail.logout()
            return {"placement": "not_found", "provider": account["provider"]}

        except Exception as e:
            return {"placement": "error", "error": str(e)}

    def generate_report(self, results):
        """Generate deliverability report"""
        total = len(results)
        inbox_count = sum(1 for r in results.values() if r["placement"] == "inbox")
        spam_count = sum(1 for r in results.values() if r["placement"] == "spam")

        return {
            "total_tested": total,
            "inbox_rate": inbox_count / total if total > 0 else 0,
            "spam_rate": spam_count / total if total > 0 else 0,
            "details": results,
        }

Domain Reputation Monitoring

Monitor your sending domains’ reputation using various tools with proxy isolation. Understanding different proxy types and their applications is covered in our proxy glossary.

async def check_domain_reputation(domain, proxy_config):
    """Check domain reputation across multiple blacklist services"""
    from playwright.async_api import async_playwright

    reputation = {"domain": domain, "checks": {}}

    async with async_playwright() as p:
        browser = await p.chromium.launch(proxy=proxy_config)
        page = await browser.new_page()

        # Check Google Postmaster Tools
        await page.goto("https://postmaster.google.com/")
        await page.wait_for_timeout(3000)
        # Parse reputation data if authenticated

        # Check MXToolbox
        await page.goto(f"https://mxtoolbox.com/SuperTool.aspx?action=blacklist%3a{domain}")
        await page.wait_for_timeout(5000)

        blacklist_results = await page.query_selector_all('[class*="tool-result"]')
        reputation["checks"]["mxtoolbox"] = {
            "total_checked": len(blacklist_results),
        }

        await browser.close()

    return reputation

Multi-Inbox Management

Proxy Isolation Per Domain

Each sending domain should have its own proxy IP for all web-based management activities:

class ColdEmailInfrastructure:
    """Manage complete cold email infrastructure"""

    def __init__(self, domains, proxy_pool):
        self.domains = {}
        for i, domain in enumerate(domains):
            self.domains[domain["name"]] = {
                "domain": domain["name"],
                "accounts": domain["accounts"],
                "proxy": proxy_pool.get_sticky_proxy(f"domain_{i}"),
                "warming_status": "not_started",
                "daily_cold_limit": 0,
                "reputation": None,
            }

    def get_available_senders(self, required_volume):
        """Get senders with available daily capacity"""
        available = []
        remaining_volume = required_volume

        for domain_name, domain_data in self.domains.items():
            if domain_data["warming_status"] != "ready":
                continue

            for account in domain_data["accounts"]:
                account_capacity = account.get("daily_limit", 30) - account.get("sent_today", 0)
                if account_capacity > 0:
                    available.append({
                        "email": account["email"],
                        "capacity": account_capacity,
                        "proxy": domain_data["proxy"],
                        "domain": domain_name,
                    })
                    remaining_volume -= account_capacity

                if remaining_volume <= 0:
                    break

            if remaining_volume <= 0:
                break

        return available

    def distribute_campaign(self, recipients, campaign_template):
        """Distribute campaign across available senders"""
        senders = self.get_available_senders(len(recipients))

        assignments = []
        recipient_index = 0

        for sender in senders:
            batch_size = min(sender["capacity"], len(recipients) - recipient_index)
            batch = recipients[recipient_index:recipient_index + batch_size]

            assignments.append({
                "sender": sender["email"],
                "proxy": sender["proxy"],
                "recipients": batch,
                "template": campaign_template,
            })

            recipient_index += batch_size
            if recipient_index >= len(recipients):
                break

        return assignments

DNS and Authentication Setup

Proper DNS configuration is critical for deliverability. Automate DNS verification:

import dns.resolver

def verify_email_dns(domain):
    """Verify all DNS records required for email deliverability"""
    results = {"domain": domain, "checks": {}}

    # SPF Record
    try:
        spf_records = dns.resolver.resolve(domain, 'TXT')
        spf_found = any('v=spf1' in str(r) for r in spf_records)
        results["checks"]["spf"] = {
            "configured": spf_found,
            "records": [str(r) for r in spf_records if 'spf' in str(r).lower()]
        }
    except Exception:
        results["checks"]["spf"] = {"configured": False, "error": "No TXT records found"}

    # DKIM Record
    try:
        dkim_selectors = ['google', 'default', 'selector1', 'selector2', 'k1']
        dkim_found = False
        for selector in dkim_selectors:
            try:
                dkim_records = dns.resolver.resolve(f'{selector}._domainkey.{domain}', 'TXT')
                if dkim_records:
                    dkim_found = True
                    results["checks"]["dkim"] = {
                        "configured": True,
                        "selector": selector,
                    }
                    break
            except Exception:
                continue
        if not dkim_found:
            results["checks"]["dkim"] = {"configured": False}
    except Exception:
        results["checks"]["dkim"] = {"configured": False}

    # DMARC Record
    try:
        dmarc_records = dns.resolver.resolve(f'_dmarc.{domain}', 'TXT')
        results["checks"]["dmarc"] = {
            "configured": True,
            "records": [str(r) for r in dmarc_records]
        }
    except Exception:
        results["checks"]["dmarc"] = {"configured": False}

    # MX Records
    try:
        mx_records = dns.resolver.resolve(domain, 'MX')
        results["checks"]["mx"] = {
            "configured": True,
            "records": [str(r.exchange) for r in mx_records]
        }
    except Exception:
        results["checks"]["mx"] = {"configured": False}

    return results

Bounce and Response Tracking

Monitor campaign performance through proxy-isolated IMAP connections:

class CampaignMonitor:
    """Monitor cold email campaign metrics"""

    def __init__(self, sender_accounts, proxy_pool):
        self.accounts = sender_accounts
        self.proxy_pool = proxy_pool

    def check_bounces(self, account):
        """Check for bounce notifications"""
        try:
            mail = imaplib.IMAP4_SSL(account["imap_host"])
            mail.login(account["email"], account["password"])
            mail.select("INBOX")

            # Search for bounce messages
            _, msgs = mail.search(None, 'FROM "mailer-daemon"')
            bounce_count = len(msgs[0].split()) if msgs[0] else 0

            # Search for auto-replies
            _, msgs = mail.search(None, 'SUBJECT "Out of Office"')
            ooo_count = len(msgs[0].split()) if msgs[0] else 0

            mail.logout()

            return {
                "account": account["email"],
                "bounces": bounce_count,
                "out_of_office": ooo_count,
            }
        except Exception as e:
            return {"account": account["email"], "error": str(e)}

    def calculate_health_score(self, metrics):
        """Calculate overall email health score"""
        sent = metrics.get("total_sent", 0)
        if sent == 0:
            return 100

        bounce_rate = metrics.get("bounces", 0) / sent
        spam_rate = metrics.get("spam_complaints", 0) / sent
        reply_rate = metrics.get("replies", 0) / sent

        score = 100
        score -= bounce_rate * 200   # Heavy penalty for bounces
        score -= spam_rate * 500     # Very heavy penalty for spam complaints
        score += reply_rate * 50     # Bonus for replies

        return max(0, min(100, score))

Scaling Cold Email Operations

For teams running large-scale cold outreach using proxy-collected leads from web scraping pipelines, scaling requires careful infrastructure management:

Infrastructure Sizing

ScaleDomainsAccounts/DomainDaily VolumeProxy IPs Needed
Starter32150-3003
Growth103750-1,50010
Scale2531,875-3,75025
Enterprise50+33,750-7,500+50+

Key Scaling Principles

  1. Never rush warming — Each new domain needs 3-4 weeks of warming regardless of urgency.
  2. Monitor bounce rates daily — If any account exceeds 3% bounce rate, pause and investigate.
  3. Rotate sending patterns — Vary send times, volumes, and sequences to avoid pattern detection.
  4. Separate domains by campaign type — Use different domains for different industries or offering types.
  5. Maintain a buffer — Always have 20% more warmed domains than you actively need.

Conclusion

Cold email infrastructure is a system of interdependent components where proxy isolation plays a critical role in maintaining deliverability. Each sending domain, each warming account, and each monitoring check should operate through its own proxy IP to prevent cross-contamination of digital fingerprints. Combined with proper DNS authentication, gradual warming, and continuous reputation monitoring, this approach sustains inbox placement rates above 90% even at scale. The investment in proper infrastructure pays for itself through higher response rates and lower domain burn rates.


Related Reading

Scroll to Top