Convert inbound email to structured JSON
MailWebhook receives email from Gmail, Microsoft 365, IMAP, or hosted mailboxes, normalizes the message, extracts useful fields, and sends your application JSON in the shape your route defines.
Built for email-to-JSON webhooks, parser workflows, inbound email automation, and applications that need stable payloads instead of raw MIME.
From: Vendor Billing <billing@vendor.example> To: ap@company.com Subject: Invoice 1042 Invoice ID: INV-1042 Total: $481.92 Due Date: 2026-07-15 Please review the attached PDF invoice.
{
"kind": "invoice",
"invoice_id": "INV-1042",
"total": "$481.92",
"due_date": "2026-07-15",
"vendor": {
"email": "billing@vendor.example",
"domain": "vendor.example"
},
"attachments": [
{
"filename": "invoice-1042.pdf",
"content_type": "application/pdf",
"size": 93259
}
]
}Use MailWebhook to convert email to JSON, replace brittle email parser JSON scripts, and deliver every matching message as an email-to-JSON webhook your application can process.
What is email to JSON?
Email to JSON is a way to turn inbound email messages into structured data that software can process. Instead of handing your application a raw MIME message, an email-to-JSON workflow normalizes senders, recipients, headers, body text, HTML, attachments, timestamps, and selected extracted fields into a predictable JSON payload.
MailWebhook does this inside a route pipeline. A route matches an incoming email, transforms the parsed message, maps it to either the documented generic JSON shape or a custom JSON shape, and delivers that JSON to your webhook endpoint.
From messy mailbox messages to useful JSON
A route turns each matching email into the JSON your application expects, without a separate parsing service.
- Step 1
Connect a source mailbox
Use Gmail, Microsoft 365/Outlook, IMAP, or a MailWebhook-hosted mailbox as the source.
- Step 2
Match the message to a route
Route rules decide which messages should be transformed and delivered.
- Step 3
Normalize the email
Parsed fields become stable message, body, attachment, header, and context objects.
- Step 4
Extract and map
Use the generic JSON mapper or configure map.custom_json to emit the payload your receiver expects.
- Step 5
Deliver the JSON
The route output is serialized as JSON and posted to your endpoint.
Start with a stable schema or shape the payload yourself
Generic JSON
Use map.generic_json when your receiver wants a documented, deterministic payload. The mailwebhook.generic@1 shape includes schema, event, message, body, meta, and optional envelope objects.
Custom JSON
Use map.custom_json when your receiver expects a specific contract. The mapper config can read message fields, route context, metadata, computed vars, and extraction-helper output, then emit the JSON object or value your downstream system needs.
| Need | Use |
|---|---|
| Stable MailWebhook-owned event shape | map.generic_json |
| Receiver-specific payload for CRM, ERP, ticketing, AI, or internal APIs | map.custom_json |
| Fast implementation with known top-level fields | Generic JSON |
| Fewer transformations after receipt | Custom JSON |
| Strict documented event schema | Generic JSON |
| Route-specific extraction fields | Custom JSON |
A documented JSON shape for every matching email
The default mapper emits mailwebhook.generic@1. It keeps the payload predictable: event identifiers in event, email fields in message, body and attachments in body, and source metadata in meta.
Attachments are metadata only. No file URLs or bytes are embedded in the generic JSON body.
Validate the generic shape{
"schema": { "name": "mailwebhook.generic", "version": "1" },
"event": {
"id": "6ff49aa1-7050-4ad1-95d9-2711f2ca7e88",
"project_id": "dca29061-c4a7-4687-a8dd-24d2f26548c7",
"route_id": "2f3713bf-88cc-46c6-aaa3-ea9d6e9d20f3",
"created_at": "2026-06-27T10:14:32Z"
},
"message": {
"message_id": "<invoice-1042@example.com>",
"message_id_type": "original",
"subject": "Invoice 1042",
"date": "2026-06-27T10:13:59Z",
"from": [{ "email": "billing@vendor.example", "name": "Vendor Billing" }],
"to": [{ "email": "ap@company.com" }],
"headers": {
"message-id": "<invoice-1042@example.com>",
"content-type": "multipart/mixed"
}
},
"body": {
"text": "Please review invoice 1042.",
"attachments": [
{
"id": "9f5a1ded-538d-4f5f-a7a9-d3eacf9e58a0",
"filename": "invoice-1042.pdf",
"content_type": "application/pdf",
"size": 93259,
"is_inline": false,
"sha256": "059a0f5260487bbe663994de1fd641401fec76ac9f6bddfe5b53ae60d4bb2d86"
}
]
},
"meta": {
"source": "gmail",
"raw_size_bytes": 26546,
"received_at": "2026-06-27T10:14:32Z"
}
}Map email fields into the JSON your app already expects
Custom JSON routes let you move transformation before delivery. Instead of receiving a large generic payload and writing another adapter, define the route output from message fields, computed vars, route context, and extraction-helper results.
{
"steps": [
{
"name": "map.custom_json",
"args": {
"version": "v1",
"vars": [
{
"name": "sender",
"expr": { "string.lower": { "var": "message.from[0].email" } }
},
{
"name": "vendor_domain",
"expr": {
"regex.replace": {
"value": { "var": "vars.sender" },
"pattern": "^.*@([^>\\s]+)$",
"with": "\\1"
}
}
},
{
"name": "is_invoice",
"expr": {
"regex.match": {
"value": { "var": "message.subject" },
"pattern": "(?i)invoice|receipt|payment"
}
}
}
],
"output": {
"kind": { "if": [{ "var": "vars.is_invoice" }, "invoice", "message"] },
"vendor": {
"email": { "var": "vars.sender" },
"domain": { "var": "vars.vendor_domain" }
},
"subject": { "var": "message.subject" },
"first_attachment": {
"filename": { "var": "message.attachments[0].filename" },
"content_type": { "var": "message.attachments[0].content_type" },
"size": { "var": "message.attachments[0].size" },
"sha256": { "var": "message.attachments[0].sha256" }
}
}
}
}
]
}The mapper config is validated when the route is saved and again before execution. Missing paths evaluate to null, so not every sender will populate every field.
Built-in helpers for the hard parts of email extraction
These helpers handle the fields that usually break parser scripts, so routes can address them with a stable JSON path.
Reply content
Extract only the new reply body from quoted content, forwarded content, and signatures.
vars.reply_segments.text.reply_contentLinks
Extract URLs from HTML attributes, link text, Markdown links, and plain text.
vars.links[0].urlKey/value fields
Turn labels such as Order ID: AZ-123 into normalized lookup fields.
vars.kv.values.order_idTables
Extract text tables, Markdown pipe tables, ASCII tables, native HTML tables, and HTML grids.
vars.tables.tables[0].lookup.by_row.widget.qtyLists
Convert bullet and numbered lists into structured arrays.
vars.lists[0].bullets[0].textDOM fields
Pull repeated records or scalar values from stable HTML layouts using CSS or XPath selectors.
vars.opportunities.itemsTurn email labels into JSON fields
Key/value extraction normalizes labels so fields can be addressed predictably. For example, Order ID becomes order_id, Customer Email becomes customer_email, and Ticket-Type becomes ticket_type. The first value is available through values.<key> and duplicates through groups.<key>.
Order ID: AZ-123 Order ID: AZ-456 Customer Name: Ada
{
"order_id": "AZ-123",
"order_ids": ["AZ-123", "AZ-456"],
"item_values": ["AZ-123", "AZ-456", "Ada"]
}Extract table cells without parsing table text yourself
Table extraction returns normalized rows, columns, lookup maps, cell metadata, and a rectangular text matrix. Routes can map a single cell, iterate rows, or pass selected table records downstream. The extract.tables helper supports TSV, pipe, ASCII, HTML table, and opt-in HTML grid sources.
Item Qty Total Widget 2 $10.00 Gadget 3 $15.00
{
"widget_qty": "2",
"gadget_total": "$15.00",
"row_totals": [
{ "key": "widget", "total": "$10.00" },
{ "key": "gadget", "total": "$15.00" }
]
}Use recipes instead of starting from a blank parser
| Recipe | Use when | Emits |
|---|---|---|
| Reply-only payload | You want the new reply without quoted history. | reply_text, has_quoted_content, quoted_depth |
| All links | You need normalized URLs and link labels from HTML or text. | links[] with url, label, and source_element |
| Repeated DOM cards | A stable HTML sender template contains repeated cards or layout tables. | items[] or named fields selected with CSS/XPath |
Normalize, redact, or trim before the JSON is emitted
Before the final mapper runs, route pipelines can apply transform steps. Use them to normalize HTML into text, remove fields, rewrite values, or strip attachments that should not affect the JSON your receiver gets.
| Step | Use it for |
|---|---|
| html_to_text | Convert message HTML into deterministic plain text. |
| remove_fields | Remove or clear selected message fields, headers, or attachment metadata. |
| replace_values | Set subject, body, or header values from literals or small templates. |
| strip_attachments_if | Remove attachments that match MIME, size, or filename conditions. |
{
"steps": [
{
"name": "html_to_text",
"args": { "width": 0, "preserve_links": true, "keep_tables": true }
},
{
"name": "map.generic_json",
"args": {}
}
]
}Attachment metadata in JSON, file bytes on demand
MailWebhook includes attachment metadata in JSON so your receiver can decide what to do next. Attachment files are not embedded in the webhook body and generic JSON does not include file URLs. When your app needs the bytes, use the attachment URL API.
See attachment API details{
"id": "9f5a1ded-538d-4f5f-a7a9-d3eacf9e58a0",
"filename": "invoice-1042.pdf",
"content_type": "application/pdf",
"size": 93259,
"is_inline": false,
"sha256": "059a0f5260487bbe663994de1fd641401fec76ac9f6bddfe5b53ae60d4bb2d86"
}GET /v1/messages/{message_id}/attachments/{attachment_id}/urlJSON output from the mailbox source you already use
MailWebhook can transform messages from Gmail, Microsoft 365/Outlook, IMAP, or hosted mailboxes into route-defined JSON. Pick the source that matches your workflow, then use the same generic or custom JSON mapping patterns.
Gmail / Google Workspace
Convert Gmail messages into webhook-ready JSON payloads.
Microsoft 365 / Outlook
Convert work mailbox and shared mailbox messages into structured JSON.
IMAP
Convert existing IMAP inbox messages into JSON without maintaining an IMAP worker.
Hosted mailbox
Use a MailWebhook-hosted mailbox for dedicated intake addresses.
Where structured email JSON pays off
Invoice intake
Extract vendor, subject, invoice IDs, attachment metadata, and table totals into accounting workflows.
Order and fulfillment emails
Convert order IDs, item rows, shipping links, and status labels into API events.
Support and customer replies
Capture only the new reply content and useful headers before creating a ticket or agent task.
Lead and CRM routing
Pull contact fields, sender domains, links, and form-like labels into a CRM payload.
AI agent inboxes
Give agents structured inbound email events without letting them parse raw MIME or hold mailbox credentials.
Operations alerts
Convert monitoring and vendor notification emails into compact alert payloads with priority fields.
Where MailWebhook fits
| Approach | What you get | Where it breaks |
|---|---|---|
| DIY IMAP or provider API worker | Full control over mailbox polling and parsing. | You own MIME parsing, HTML cleanup, extraction, retries, signatures, storage, and observability. |
| Basic inbound parse webhook | A parsed email payload posted to an endpoint. | You often still map the payload into your real receiver contract after it arrives. |
| Parser mailbox tools | Template-oriented extraction workflows. | Good for some business users, but less direct for developers who want route-level JSON and webhook contracts. |
| MailWebhook | Existing mailbox intake plus generic or custom JSON mapping before delivery. | Best fit when inbound email should become application events, not when you need a one-off file converter. |
Your JSON is delivered as the webhook body
After the route pipeline emits JSON, MailWebhook sends that payload to your endpoint. Delivery includes idempotency and signature headers so your receiver can process events safely. For request headers, signature verification, endpoint setup, replay, and public API operations, use the Email Webhook API page.
POST /webhooks/email HTTP/1.1 Content-Type: application/json X-Idempotency-Key: 6b8b7f9e... X-MailWebhook-Signature: t=1782478472, kid=whsec_123, v1=...
Start free, scale when you need to
The Free plan includes 300 emails/month at no cost. Paid plans start at $29/per month with a 30-day free trial.
- HMAC-signed webhook delivery
- Automatic retries with backoff
- Event inspector and replay
- Idempotency keys for safe dedupe
Email to JSON FAQ
- Can MailWebhook convert email to JSON?
- Yes. MailWebhook converts matching inbound emails into JSON route outputs. Use the documented generic JSON shape or configure a custom JSON mapper for the fields your receiver needs.
- Is this a one-off email file to JSON converter?
- No. This page is about ongoing inbound mailbox workflows. MailWebhook receives messages from supported sources, transforms them in a route pipeline, and delivers JSON to your endpoint.
- What is the default JSON schema?
- The default mapper emits mailwebhook.generic@1 with top-level schema, event, message, body, meta, and optional envelope objects.
- Can I create my own JSON shape?
- Yes. Use map.custom_json to define ordered vars and an output template. The mapper config is schema-validated, and the emitted output can match the contract your receiver expects.
- Can I extract fields such as order IDs or invoice numbers?
- Yes, when those fields are present in the message body or HTML. Custom JSON routes can use key/value extraction, regex helpers, table extraction, DOM extraction, and normal message-field paths.
- Can MailWebhook parse tables into JSON?
- Yes. The extract.tables helper can return tables, row and column lookup maps, iterable rows and columns, and a text-only matrix for supported text and HTML table formats.
- Are attachments included in the JSON?
- Attachment metadata can be included in JSON. Attachment file bytes are not embedded in webhook bodies; fetch file bytes later through the attachment URL API when needed.
- Can Gmail or Microsoft 365 email become JSON?
- Yes. MailWebhook supports Gmail, Microsoft 365/Outlook, IMAP, and hosted mailbox workflows as sources, then maps matching messages into JSON through the same route pipeline.
- Is this the same as an email webhook API?
- It is related, but the intent is different. /email-to-json explains payload shaping and extraction. /email-webhook-api explains webhook request contracts, endpoint setup, signatures, idempotency, and public API operations.
- Do I still receive a webhook?
- Yes. For HTTP routes, the mapped JSON is posted to your endpoint as the webhook body.
Turn the next matching email into JSON your app can use
Create a route, choose the generic schema or custom mapper, and let MailWebhook deliver structured email data to your webhook endpoint.