Why Email Parsing API Capability Matters
For many SaaS platforms, inbound email is a first-class input surface. Support ticketing, user-generated content, automated approvals, lead capture, and programmatic workflows all begin with a message that needs to be normalized and delivered to your application. Choosing an email parsing service is not just about receiving mail - it is about the developer experience of the email parsing API, how structured the JSON is, how you receive it via REST or webhook, and how the provider handles edge cases at scale.
This comparison focuses on the email-parsing-api itself: how an inbound system turns raw MIME into useful fields, what guarantees you get, how webhooks are signed and retried, and whether you can poll with REST for reliability and backfilling. We will look at MailParse alongside Postmark Inbound and evaluate the APIs that push or fetch structured data.
If you are planning email infrastructure for your product, see these resources for broader context:
- Email Infrastructure Checklist for SaaS Platforms
- Top Inbound Email Processing Ideas for SaaS Platforms
- Email Deliverability Checklist for SaaS Platforms
How MailParse Handles the Email Parsing API
This platform provides instant, disposable or long-lived email addresses on demand, ingests MIME, parses it into normalized JSON, and delivers the result via webhook or a REST polling API. The dual-delivery design gives you both real-time webhooks and a reliable fetch path for backfilling, replay, or batch processing.
Key API capabilities
- Instant address provisioning via API - create per-user or per-workflow inboxes in seconds.
- Webhook delivery with signed requests, TLS required, and automatic retries on non-2xx responses.
- REST polling API with cursor-based pagination and time-based filters for deterministic backfills.
- Normalized JSON schema that includes envelope metadata, headers, structured addresses, bodies, parts, and attachments with content-type and size metadata.
- Optional access to raw MIME for advanced processing or auditing.
- Idempotent message IDs and guaranteed ordering per inbox.
Webhook delivery
When a message arrives, the service posts a structured JSON payload to your HTTPS endpoint. Each request includes:
- Message ID and inbox ID for idempotency and scoping.
- Parsed addresses: from, sender, reply-to, to, cc, bcc, each with name and address fields.
- Headers as an array and a normalized map for easy lookup.
- Text and HTML bodies, including a pre-parsed quoted-reply body when detectable.
- Attachments as metadata plus either base64 content or secure download URLs, configurable per inbox.
- A signature header with an HMAC of the request body using your shared secret.
Webhook retries use an exponential backoff with a bounded max window and a dead-letter policy via the REST API. You can replay delivery by ID when required.
REST polling
The REST API exposes message lists and individual messages with consistent pagination. This is ideal when you need strict control in a queue processor, or when your inbound endpoint is temporarily unreachable and you want a guaranteed pull-based recovery path. Typical filters include: since, before, inbox, status, and an after-cursor parameter that guarantees no gaps or duplicates.
JSON structure
The email-parsing-api returns a canonical shape that stays stable across versions. Common fields include:
- id, inbox_id, created_at, message_id (RFC 5322), in_reply_to, references
- envelope: from, recipients, helo, remote_ip
- headers: array of { name, value } and a parallel map for convenience
- from, sender, reply_to: arrays of { name, address }
- to, cc, bcc: arrays of { name, address }
- subject, text_body, html_body, stripped_text_reply
- attachments: [{ id, filename, content_type, size, content_id, inline, disposition, data or url }]
- raw_mime_url when enabled, with short-lived signed URLs
How Postmark Inbound Handles Email Parsing API
Postmark Inbound is Postmark's inbound processing feature that posts JSON to your webhook whenever a message hits your configured inbound address or domain. It is a solid, straightforward webhook-first approach.
What you get with Postmark Inbound
- Webhook-only delivery - the system posts a structured JSON payload to your endpoint.
- A comprehensive payload that includes From, To, Cc, Subject, HtmlBody, TextBody, and Attachments.
- Attachments are included inline as base64 data with filename, content type, and content length.
- Optional RawEmail in the payload when enabled in settings.
- Support for inbound webhook signatures so you can verify authenticity.
- Retries on non-200 responses until a threshold is met.
What Postmark Inbound does not provide
- No REST polling API for inbound messages. If your webhook endpoint is down for an extended period, you cannot pull missed messages via a fetch API.
- No provider-hosted attachment URLs for large files, since attachment content is typically base64 in the JSON payload.
- No inbox provisioning API intended for ephemeral, per-user addresses. You usually configure routes and inbound domains in the UI or server settings.
If your application requires a pull-based queue, or if you prefer to keep inbound endpoints minimal for security and retrieve messages later via REST, this limitation is important.
Side-by-Side Email Parsing API Feature Comparison
| Feature | MailParse | Postmark Inbound |
|---|---|---|
| Delivery modes | Webhook and REST polling | Webhook only |
| Instant inbox provisioning by API | Yes | Primarily configured in UI, not per-inbox API |
| Webhook signatures | HMAC signature header with shared secret | HMAC signature header supported |
| Attachment handling | Configurable: base64 in JSON or signed download URLs | Inline base64 in JSON |
| Raw MIME access | Optional via short-lived URL | Optional RawEmail included when enabled |
| Idempotency and ordering | Stable message IDs and ordered retrieval per inbox | Stable MessageID in payload, ordering via webhook arrival |
| Polling filters and cursors | since, before, inbox, cursor | Not applicable |
| Retry policy | Exponential backoff with replay via REST | Retries on non-200 up to configured limits |
| JSON bodies | text_body, html_body, stripped_text_reply | TextBody, HtmlBody, StrippedTextReply |
Code Examples
Webhook handler for inbound JSON
This minimal Node.js example shows a webhook handler that verifies a signature header, parses the payload, and queues work. It applies to both providers with small changes to the signature verification step and field names.
const express = require('express');
const crypto = require('crypto');
const app = express();
app.use(express.json({ limit: '25mb' }));
function verifySignature(rawBody, signatureHeader, secret) {
const hmac = crypto.createHmac('sha256', secret).update(rawBody, 'utf8').digest('hex');
return crypto.timingSafeEqual(Buffer.from(hmac), Buffer.from(signatureHeader || '', 'hex'));
}
app.post('/inbound', (req, res) => {
const rawBody = JSON.stringify(req.body);
const signature = req.header('X-Signature'); // replace with the provider's actual signature header
const secret = process.env.INBOUND_WEBHOOK_SECRET;
if (!verifySignature(rawBody, signature, secret)) {
return res.status(401).send('invalid signature');
}
const msg = req.body;
// Normalize likely fields across providers
const subject = msg.subject || msg.Subject;
const from = (msg.from?.[0]?.address) || msg.From;
const text = msg.text_body || msg.TextBody;
const html = msg.html_body || msg.HtmlBody;
// Queue for processing
// queue.publish({ id: msg.id || msg.MessageID, subject, from, text, html });
res.status(200).send('ok');
});
app.listen(3000, () => console.log('listening on 3000'));
Polling inbound messages with REST
When a provider exposes a REST API, you can process messages in a worker that periodically polls with a cursor. Here is a Python example.
import os
import time
import requests
API_BASE = os.environ.get("INBOUND_API_BASE") # e.g. https://api.example.com/v1
API_KEY = os.environ.get("INBOUND_API_KEY")
cursor = None
while True:
params = {"limit": 100}
if cursor:
params["after"] = cursor
resp = requests.get(f"{API_BASE}/messages", headers={
"Authorization": f"Bearer {API_KEY}",
"Accept": "application/json",
}, params=params, timeout=30)
resp.raise_for_status()
data = resp.json()
for m in data["items"]:
# Process each message
# download attachments if m["attachments"][i].get("url")
print(m["id"], m.get("subject"))
cursor = data.get("next_cursor")
if not cursor:
time.sleep(5)
Postmark Inbound payload shape example
Postmark Inbound posts fields like From, To, Subject, TextBody, HtmlBody, and Attachments. Here is a trimmed JSON shape you can expect:
{
"From": "Alice <alice@example.com>",
"To": "support@yourapp.example",
"Subject": "Example",
"TextBody": "Hello",
"HtmlBody": "<p>Hello</p>",
"StrippedTextReply": "Reply text",
"MessageID": "f1e2d3c4-...@example.com",
"Headers": [{ "Name": "X-Custom", "Value": "123" }],
"Attachments": [{
"Name": "invoice.pdf",
"Content": "base64string...",
"ContentType": "application/pdf",
"ContentLength": 123456,
"ContentID": null
}]
}
If you enable the RawEmail option, Postmark can include a RawEmail field in the payload for audit or custom parsing.
Performance and Reliability
Inbound email is messy in the real world. An email-parsing-api needs to be resilient to malformed MIME, huge attachments, exotic charsets, and slow or intermittent endpoints. Here is how both approaches play out in practice.
Edge cases and MIME fidelity
- Character sets and encodings: Look for normalized Unicode output and explicit content-transfer decoding. Providers should correctly decode quoted-printable and base64 bodies and expose the original charsets for debugging.
- Nested multipart and inline images: JSON should represent the part tree in a consistent way. Inline images should be identifiable via content-id and disposition so you can reconstruct HTML emails without guesswork.
- Weird headers: Providers should preserve all headers in the raw listing and expose a normalized map with case-insensitive keys. This is critical for things like threading with In-Reply-To and References.
Attachment size and transport
- Inline base64 in webhooks is simple but inflates payloads by roughly 33 percent and can stress your web server if a 25 MB file is posted to a public endpoint.
- Signed URLs shift large payload transfer to pull-time, which reduces webhook latency and lets workers stream downloads to object storage.
- If you rely on webhook-only delivery with base64 attachments, ensure your endpoint and load balancer can handle large POST bodies and that you have a timeout strategy.
Retries, idempotency, and backfilling
- Webhook retries help recover from transient failures, but a hard outage can still create a gap. A REST polling API is a strong complement because it lets you fetch missed messages by time or cursor.
- Deterministic message identifiers, and preferably ordered retrieval per inbox, make it easy to run your own at-least-once consumer with deduplication.
- Signature verification should be constant time and based on an HMAC of the exact request body. Always reject unsigned or invalid requests early.
Throughput and latency
- Webhook-first pipelines can deliver in near-real-time with p99 latencies in the low hundreds of milliseconds when properly scaled.
- Polling can be tuned to your workload: burst mode for catch-up, gentle mode for low-traffic integrations, and adaptive intervals based on backlog.
Verdict: Which Is Better for Email Parsing API?
If you want flexibility with both webhook and REST, plus programmatic inbox provisioning and backfill controls, MailParse is the stronger choice for an email parsing api. You get a unified JSON schema, signed webhooks, and a pull path that fits queue-based architectures.
If you are already invested in Postmark for transactional sends and your integrations are entirely webhook-driven, Postmark Inbound is a reliable, straightforward option. You will trade off the ability to poll or replay via REST, so plan for robust webhook uptime and storage of received payloads.
In short: choose Postmark Inbound when webhook-only is sufficient and you prefer minimal components, choose MailParse when you need both push and pull APIs, larger-scale attachment handling options, and fine-grained control over ingestion workflows.
FAQ
Can I use both webhook and REST together?
Yes. A common pattern is to accept webhooks for real-time processing, write the message ID to a queue, and have a worker fetch message details via REST when needed. This gives you fast response times and strong recovery guarantees.
How do I verify inbound webhook authenticity?
Both providers support a signature header based on an HMAC of the HTTP body with your secret. Compute the HMAC with SHA-256, compare in constant time, and reject if the request time or signature is missing. Rotate secrets periodically.
What is the best way to handle large attachments?
For webhook-only systems that embed base64 content, increase body size limits on your server, stream requests when possible, and move attachments to object storage quickly. When available, prefer signed URLs and download attachments asynchronously to keep webhook handlers fast.
Can I reconstruct threads and replies from parsed JSON?
Yes. Use the Message-ID, In-Reply-To, and References headers to link messages. Many parsers also expose a stripped reply body that removes quoted history, which is useful for ticketing and comment systems.
Does postmark-inbound include the raw email?
Postmark Inbound can include a RawEmail field when you enable it in settings. If you need raw MIME for compliance or custom parsing, ensure this option is active and account for larger payloads.