MultiMail scores every recipient domain against MX records, SPF, DMARC, and platform-wide bounce history before your agent sends a single message.
High-volume AI agents sending to stale or invalid addresses accumulate bounces rapidly. Hard bounces above 2% trigger ISP throttling and can blacklist your sending domain within days. The damage is not isolated — in a shared infrastructure environment, one agent's bounce spike degrades deliverability for every tenant on the platform. Traditional approaches catch bounces after the fact. By then the reputation hit has already landed, and unwinding a blacklisting takes weeks of remediation that no agent can automate away.
MultiMail evaluates recipient domain health before send_email executes. Each domain receives a Green, Yellow, or Red classification based on live MX lookups, SPF and DMARC record validation, and aggregated bounce history from across the platform. Red domains are blocked at the API layer — the request returns a structured error before any message enters the queue. Yellow domains are flagged in the response with specific signal breakdowns so your agent can decide whether to proceed or defer. Bounce webhooks fire on every delivery failure, carrying SMTP diagnostic codes and suppression state so your agent can update its contact list without polling or manual intervention.
Before queuing a message, MultiMail resolves the recipient domain's MX records, validates SPF and DMARC alignment, and checks platform-wide bounce history. The check runs in under 50ms and is transparent to your agent unless the domain is Yellow or Red.
Green domains pass all checks and send normally. Yellow domains have degraded signals — expired SPF, missing DMARC, or elevated bounce rates — and are flagged in the API response with a domain_signals array. Red domains are blocked outright; send_email returns a 422 with domain_blocked as the error code before the message is queued.
When a hard bounce occurs (SMTP 5xx, invalid mailbox, domain not found), MultiMail fires a bounce webhook to your registered endpoint and adds the address to your tenant's suppression list. Subsequent send_email calls to that address return a SuppressedAddressError before consuming send quota.
Bounce data from all MultiMail tenants contributes to the platform-wide domain reputation model. A domain that begins bouncing across the platform is classified Red for every agent — you benefit from signals your own sends have not yet generated, before your first attempt to a degraded domain.
Your agent can check suppression status and domain risk for a batch of addresses via the suppression/check endpoint before building a send list. This lets agents prune stale contacts during list preparation rather than discovering suppressions one by one mid-campaign.
import multimail
from multimail.exceptions import DomainBlockedError, SuppressedAddressError
client = multimail.Client(api_key="mm_live_...")
def send_with_domain_check(mailbox_id, recipient, subject, body):
try:
result = client.send_email(
mailbox_id=mailbox_id,
to=recipient,
subject=subject,
body=body,
)
if result.domain_risk == "yellow":
"cm"># Flagged but not blocked — agent decides
print(f"Yellow domain signals: {result.domain_signals}")
return result
except DomainBlockedError as e:
"cm"># Red domain — blocked before send, zero bounce impact
print(f"Blocked: {e.recipient} — reason: {e.reason}")
return None
except SuppressedAddressError as e:
"cm"># Prior hard bounce — suppressed at platform level
print(f"Suppressed: {e.recipient} — suppressed_at: {e.suppressed_at}")
return None
result = send_with_domain_check(
mailbox_id="mbx_01JDEF456",
recipient="[email protected]",
subject="Q2 update from Acme",
body="Hi, wanted to share our Q2 summary with you.",
)Handle Green, Yellow, and Red domain outcomes in your agent. Yellow domains surface a domain_signals array — your agent decides whether to proceed or defer.
import { createHmac } from 'crypto';
export async function handleBounceWebhook(req, res) {
const sig = req.headers['x-multimail-signature'];
const expected = createHmac('sha256', process.env.MM_WEBHOOK_SECRET)
.update(JSON.stringify(req.body))
.digest('hex');
if (sig !== expected) {
return res.status(401).json({ error: 'invalid_signature' });
}
const event = req.body;
if (event.type === 'email.bounced') {
const { recipient, bounce_type, smtp_code, message_id, suppressed_at } = event.data;
if (bounce_type === 'hard') {
"cm">// Platform has already suppressed this address.
"cm">// Sync the event to your CRM or contact store.
await markContactInvalid(recipient, {
reason: 'hard_bounce',
smtp_code,
bounced_message_id: message_id,
suppressed_at,
});
console.log(`Hard bounce suppressed: ${recipient} (SMTP ${smtp_code})`);
} else if (bounce_type === 'soft') {
"cm">// Temporary failure — platform will retry automatically.
"cm">// Log for monitoring but no action needed.
console.log(`Soft bounce on ${message_id}, smtp_code=${smtp_code}`);
}
}
res.status(200).json({ received: true });
}Process bounce events from MultiMail webhooks. Hard bounces are already suppressed by the platform; your handler syncs the event to your CRM or contact database.
"cm"># Validate addresses before campaign send
curl -X POST https://api.multimail.dev/v1/suppression/check \
-H "Authorization: Bearer $MULTIMAIL_API_KEY..." \
-H "Content-Type: application/json" \
-d &"cm">#039;{
"addresses": [
"[email protected]",
"[email protected]",
"[email protected]"
]
}&"cm">#039;
"cm"># Response:
"cm"># {
"cm"># "results": [
"cm"># {
"cm"># "address": "[email protected]",
"cm"># "suppressed": false,
"cm"># "domain_risk": "green"
"cm"># },
"cm"># {
"cm"># "address": "[email protected]",
"cm"># "suppressed": true,
"cm"># "reason": "hard_bounce",
"cm"># "domain_risk": "red",
"cm"># "signals": ["no_mx_records", "platform_bounce_rate_exceeded"]
"cm"># },
"cm"># {
"cm"># "address": "[email protected]",
"cm"># "suppressed": false,
"cm"># "domain_risk": "yellow",
"cm"># "signals": ["missing_dmarc"]
"cm"># }
"cm"># ],
"cm"># "suppressed_count": 1,
"cm"># "sendable_count": 2
"cm"># }Validate a batch of addresses for suppression status and domain risk before building a campaign. Prune Red and suppressed addresses before your send_email loop starts.
import multimail
from multimail.exceptions import DomainBlockedError, SuppressedAddressError
client = multimail.Client(
api_key="mm_live_...",
oversight_mode="autonomous",
)
def run_bounce_safe_campaign(mailbox_id, contacts, subject, body_template):
results = {"sent": [], "blocked": [], "suppressed": [], "yellow_flagged": []}
for contact in contacts:
try:
result = client.send_email(
mailbox_id=mailbox_id,
to=contact["email"],
subject=subject,
body=body_template.format(name=contact["name"]),
)
if result.domain_risk == "yellow":
results["yellow_flagged"].append({
"address": contact["email"],
"signals": result.domain_signals,
})
else:
results["sent"].append(contact["email"])
except DomainBlockedError as e:
results["blocked"].append({
"address": contact["email"],
"reason": e.reason,
"signals": e.domain_signals,
})
except SuppressedAddressError as e:
results["suppressed"].append(contact["email"])
print(f"Sent: {len(results[&"cm">#039;sent'])}")
print(f"Blocked (red domain): {len(results[&"cm">#039;blocked'])}")
print(f"Suppressed (prior bounce): {len(results[&"cm">#039;suppressed'])}")
print(f"Flagged (yellow domain): {len(results[&"cm">#039;yellow_flagged'])}")
return resultsA complete agent loop that pre-validates addresses, handles domain blocks inline, and collects structured results for post-campaign reporting.
Domain classification runs before send_email queues a message. Red domains never reach the mail server, contributing zero bounce rate to your sending domain's reputation.
MultiMail aggregates bounce signals across all tenants. A domain that begins bouncing for one agent is classified Red for every agent — you benefit from signals your own sends have not yet generated.
Hard bounces trigger suppression automatically at the platform level. Subsequent send_email calls to suppressed addresses return a typed SuppressedAddressError before the request enters the queue, consuming no send quota.
Every block or suppression surfaces a typed exception with machine-readable reason codes — domain_blocked, hard_bounce, soft_bounce, no_mx_records. Your agent routes, logs, or escalates without parsing human-readable strings.
Degraded but not blocked domains are surfaced with specific signal breakdowns: missing_dmarc, stale_mx, elevated_bounce_rate. Your agent receives the signal and makes the call — MultiMail does not silently drop borderline addresses.
Email infrastructure built for AI agents. Verifiable identity, graduated oversight, and a 50-tool MCP server. Formally verified in Lean 4.