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.comEach 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:
| Week | Daily Warming Emails | Daily Cold Emails | Total Daily |
|---|---|---|---|
| 1-2 | 5-10 | 0 | 5-10 |
| 3 | 15-20 | 5-10 | 20-30 |
| 4 | 20-25 | 15-20 | 35-45 |
| 5+ | 20-30 | 25-40 | 45-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 reputationMulti-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 assignmentsDNS 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 resultsBounce 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
| Scale | Domains | Accounts/Domain | Daily Volume | Proxy IPs Needed |
|---|---|---|---|---|
| Starter | 3 | 2 | 150-300 | 3 |
| Growth | 10 | 3 | 750-1,500 | 10 |
| Scale | 25 | 3 | 1,875-3,750 | 25 |
| Enterprise | 50+ | 3 | 3,750-7,500+ | 50+ |
Key Scaling Principles
- Never rush warming — Each new domain needs 3-4 weeks of warming regardless of urgency.
- Monitor bounce rates daily — If any account exceeds 3% bounce rate, pause and investigate.
- Rotate sending patterns — Vary send times, volumes, and sequences to avoid pattern detection.
- Separate domains by campaign type — Use different domains for different industries or offering types.
- 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.
- How to Build an Automated Lead Scraping Pipeline with Proxies
- Building a B2B Contact Enrichment Pipeline with Mobile Proxies
- How to Scrape Job Listings at Scale with Rotating Proxies
- Proxies for HR Tech: Salary Benchmarking & Talent Intelligence
- How to Scrape AliExpress Product Data Without Getting Blocked
- Amazon Buy Box Monitoring: Proxy Setup for Continuous Tracking
- How to Build an Automated Lead Scraping Pipeline with Proxies
- Building a B2B Contact Enrichment Pipeline with Mobile Proxies
- How to Scrape Job Listings at Scale with Rotating Proxies
- Proxies for HR Tech: Salary Benchmarking & Talent Intelligence
- aiohttp + BeautifulSoup: Async Python Scraping
- How to Scrape AliExpress Product Data Without Getting Blocked
- How to Build an Automated Lead Scraping Pipeline with Proxies
- Building a B2B Contact Enrichment Pipeline with Mobile Proxies
- How to Scrape Job Listings at Scale with Rotating Proxies
- Proxies for HR Tech: Salary Benchmarking & Talent Intelligence
- aiohttp + BeautifulSoup: Async Python Scraping
- How to Scrape AliExpress Product Data Without Getting Blocked
- How to Build an Automated Lead Scraping Pipeline with Proxies
- Building a B2B Contact Enrichment Pipeline with Mobile Proxies
- How to Scrape Job Listings at Scale with Rotating Proxies
- Proxies for HR Tech: Salary Benchmarking & Talent Intelligence
- aiohttp + BeautifulSoup: Async Python Scraping
- How to Scrape AliExpress Product Data Without Getting Blocked
Related Reading
- How to Build an Automated Lead Scraping Pipeline with Proxies
- Building a B2B Contact Enrichment Pipeline with Mobile Proxies
- How to Scrape Job Listings at Scale with Rotating Proxies
- Proxies for HR Tech: Salary Benchmarking & Talent Intelligence
- aiohttp + BeautifulSoup: Async Python Scraping
- How to Scrape AliExpress Product Data Without Getting Blocked