Why email deliverability matters for inbound parsing
Inbound email deliverability is the foundation of any automation that starts with an email. If messages never reach your parser, the most elegant MIME parsing, webhooks, or workflows do not matter. Ensuring reliable email receipt depends on correct DNS and MX configuration, authentication visibility, robust SMTP handling, resilient webhook delivery, and clear monitoring. This guide compares how two developer-focused options handle email-deliverability: a modern parsing platform and Mandrill Inbound from Mailchimp, with a focus on reliability-first practices you can adopt today.
- DNS and MX - correct records, resilient MX design, and the right subdomain strategy.
- Authentication visibility - surfacing SPF, DKIM, and DMARC signals for safe automation.
- SMTP and filtering - accepting legitimate mail without silent drops, quarantining threats.
- Webhook delivery - signed events, retries, idempotency, and graceful backpressure.
- Fallback and monitoring - REST polling options and actionable metrics.
How MailParse handles email deliverability
This platform is built for inbound-first reliability. It provides instant test addresses for rapid prototyping and supports bring-your-own domains via MX for production. Below is a technical deep dive into the email deliverability pipeline that focuses on reliable receipt, not just parsing.
DNS, MX, and subdomain strategy
Use a dedicated subdomain for automation, for example inbound.example.com. Point that subdomain's MX records at the service and keep low TTLs for fast failover. A typical configuration:
; Dedicated subdomain for inbound parsing
inbound.example.com. 300 IN MX 10 mx1.service.example.
inbound.example.com. 300 IN MX 20 mx2.service.example.
; DMARC to reduce spoofed automation triggers
_dmarc.inbound.example.com. 3600 IN TXT "v=DMARC1; p=quarantine; rua=mailto:dmarc@example.com; fo=1"
; SPF is primarily for sending, but publishing a neutral record helps avoid confusion
inbound.example.com. 3600 IN TXT "v=spf1 ~all"
Why the subdomain matters: it isolates automation from your primary MX traffic, sets clear policy for DMARC, and lets you adjust TTLs without impacting human mail. Add at least two MX targets so that if an anycast site or region experiences issues, mail still flows.
SMTP acceptance and authentication visibility
- STARTTLS is negotiated and recorded. You can require TLS per domain to ensure secure delivery paths.
- No silent drops on content. Messages are accepted and flagged with spam and virus metadata when applicable.
- Authentication surfaced in JSON: Authentication-Results, SPF and DKIM evaluation, and DMARC disposition from upstream.
- Forwarding edge cases: envelope sender is preserved, and SRS or ARC headers are forwarded so you can reason about forwarded mail that might fail SPF but pass DKIM alignment.
Webhook delivery that respects backpressure
After SMTP acceptance, the service posts structured JSON to your endpoint with signed headers. You get at-least-once delivery semantics, exponential backoff on non-2xx responses, and idempotency keys to deduplicate safely. Keep your handler fast and offload heavy work to background jobs.
// Node.js Express example: verify HMAC signature and dedupe by event ID
import crypto from 'crypto';
import express from 'express';
const app = express();
app.use(express.json({ limit: '25mb' }));
function verifySignature(req, bodyBuffer, secret) {
const signature = req.get('X-Service-Signature'); // hex HMAC sent by the service
const hmac = crypto.createHmac('sha256', secret).update(bodyBuffer).digest('hex');
return crypto.timingSafeEqual(Buffer.from(signature || '', 'hex'), Buffer.from(hmac, 'hex'));
}
const seen = new Set(); // replace with Redis for production
app.post('/inbound-webhook', express.raw({ type: 'application/json' }), (req, res) => {
const raw = req.body;
if (!verifySignature(req, raw, process.env.WEBHOOK_SECRET)) {
return res.status(401).end();
}
const event = JSON.parse(raw.toString('utf8'));
const id = req.get('X-Event-Id');
if (id && seen.has(id)) {
return res.status(200).end(); // idempotent ack
}
seen.add(id);
// Ack quickly, then process asynchronously
res.status(200).end();
// Example processing
const { subject, from, to, text, html, attachments, auth } = event;
// enqueue to a worker, store raw MIME if needed via event.raw_mime_url
});
app.listen(3000);
For a deeper dive on secure event handling, see Webhook Integration: A Complete Guide | MailParse. For raw headers and attachment fidelity, see MIME Parsing: A Complete Guide | MailParse.
REST polling fallback and replays
If your webhook is unavailable, messages are queued. You can fetch them over REST with pagination and later request replays. This pattern prevents data loss during deploys or outages:
curl -H "Authorization: Bearer <token>" \
"https://api.service.example/v1/inbound/messages?status=queued&limit=100"
Combining signed webhooks with REST polling gives you reliable delivery regardless of transient failures.
How Mandrill Inbound handles email deliverability
Mandrill Inbound is part of Mailchimp's transactional product. You configure an inbound domain, point its MX records to Mandrill, and define routes that forward messages to a webhook. It is a solid choice if you already use Mailchimp for outbound. The tradeoff is that it is primarily webhook driven and expects the webhook to be available.
Domain setup and MX
- Add an inbound domain in the Mandrill console, verify ownership, then set MX records to Mandrill's endpoints.
- Create recipient routes that match addresses or patterns, for example
support@inbound.example.comor a wildcard. - Mandrill accepts mail and POSTs events to your configured webhook URL.
Authentication and spam filtering
- Mandrill preserves headers, including Authentication-Results, which lets you inspect SPF, DKIM, and DMARC outcomes.
- Inbound events include parsed fields like
text,html,subject, attachments metadata, and araw_msgstring with the original MIME. - Spam scoring is available so you can quarantine automation triggers with high risk.
Webhook-only delivery model
Mandrill Inbound posts events as mandrill_events in a form-encoded payload. There is no REST polling for inbound messages, so webhook availability and retry strategy are important design considerations. Signature verification is done with an HMAC in the X-Mandrill-Signature header tied to your webhook URL.
Side-by-side comparison of email deliverability features
| Deliverability feature | MailParse | Mandrill Inbound |
|---|---|---|
| Instant test addresses for prototyping | Yes | No, requires domain and route setup |
| Bring-your-own domain via MX | Yes | Yes |
| Multiple MX targets for resilience | Yes | Yes |
| Per-domain TLS enforcement option | Configurable | Standard TLS supported, enforcement options limited |
| Authentication visibility (SPF, DKIM, DMARC) in JSON | Rich metadata | Headers preserved, parsed fields available |
| Spam score and virus quarantine | Spam score surfaced, malicious content quarantined | Spam scoring provided, provider-managed filtering |
| Webhook delivery with signed requests | Yes, HMAC with idempotency keys | Yes, X-Mandrill-Signature |
| Automatic retries on non-2xx | Yes, exponential backoff | Yes |
| REST polling fallback | Yes | No |
| Raw MIME access | Yes, stable URL or inline | Yes, raw_msg |
| Dedicated subdomain best practices support | Documented patterns and tooling | Documented patterns |
| Developer tooling and JSON shape for automation | Concise, automation-friendly schema | Comprehensive but form-encoded delivery |
Code examples: developer experience
Verifying a webhook signature and returning a fast 200
Best practice is to acknowledge quickly, then process in the background. This prevents retries and preserves upstream queue health.
// Generic pattern with async processing queue
import express from 'express';
import crypto from 'crypto';
const app = express();
app.post('/inbound', express.raw({ type: 'application/json' }), async (req, res) => {
const sig = req.get('X-Service-Signature');
const id = req.get('X-Event-Id');
const body = req.body;
const valid = crypto.createHmac('sha256', process.env.WEBHOOK_SECRET)
.update(body)
.digest('hex') === sig;
if (!valid) return res.status(401).end();
res.status(200).end(); // ack early
const event = JSON.parse(body.toString('utf8'));
// push to queue: parse attachments, check event.auth.dkim, spam_score, etc.
});
app.listen(8080);
Mandrill Inbound: verify signature and parse events
// Mandrill sends application/x-www-form-urlencoded with "mandrill_events"
import express from 'express';
import crypto from 'crypto';
import qs from 'querystring';
const app = express();
app.use(express.urlencoded({ extended: false }));
function mandrillSignature(apiKey, url, params) {
const keys = Object.keys(params).sort();
let data = url;
for (const k of keys) data += k + params[k];
return crypto.createHmac('sha1', apiKey).update(data).digest('base64');
}
app.post('/mandrill-inbound', (req, res) => {
const signature = req.get('X-Mandrill-Signature') || '';
const expected = mandrillSignature(process.env.MANDRILL_KEY, process.env.WEBHOOK_URL, req.body);
if (signature !== expected) return res.status(401).end();
const events = JSON.parse(req.body.mandrill_events || '[]');
res.status(200).end();
for (const ev of events) {
const msg = ev.msg || {};
const { from_email, subject, text, html, attachments, raw_msg } = msg;
// process safely, store raw_msg in object storage if large
}
});
app.listen(3000);
Performance and reliability under real-world conditions
Forwarded mail, SRS, and DMARC quirks
Forwarding breaks SPF by design. Reliable inbound pipelines should not drop on SPF fail alone. Instead, surface SPF, DKIM, and DMARC outcomes so your app can decide. If DKIM aligns and DMARC passes, treat as authentic. If all fail, quarantine or require manual review. Keep an eye on ARC headers when mail transits through intermediaries.
Large attachments and memory safety
Messages with large attachments or long inline threads can exceed typical body size limits. Prefer streaming to object storage and storing a pointer in your database. Avoid holding raw_msg in memory. If your provider exposes a signed URL to fetch the original MIME, fetch on demand. If the payload is inline, enforce request size limits and move processing to a worker.
Webhook latency, retries, and idempotency
Design for at-least-once delivery. Always include idempotency safeguards, for example dedup by an event ID header or message hash. Return 2xx quickly, usually within a second, then let your worker do heavy lifting. Track retry counts and notify on rising failure rates, which are early indicators of DNS, certificate, or application issues.
DNS hygiene and MX resilience
- Use two or more MX targets with different priorities.
- Keep TTLs modest, for example 300 seconds, so you can react to incidents quickly.
- Publish a DMARC policy on the inbound subdomain to prevent spoofed triggers.
- Rotate credentials used for webhook verification and store them in a secure secret manager.
Monitoring signals to watch
- SMTP acceptance rate and TLS negotiation rate.
- Median and p95 webhook latency.
- Retry volume by domain and route.
- Spam score distribution and quarantine ratio.
- Top attachment types and failure patterns.
Verdict: which is better for email deliverability?
If you already run Mailchimp's transactional stack and want a webhook-only inbound that fits within your existing account, Mandrill Inbound is reliable and well documented. If you need instant test addresses, configurable TLS enforcement, signed web