Overview
Email messages are delivered over the wire in MIME format — a dense, multipart text structure that encodes headers, body parts, attachments, and metadata in a format designed for 1990s mail servers, not modern application code. Parsing MIME reliably is surprisingly complex: boundary markers, quoted-printable encoding, base64 attachments, nested multipart trees, and header folding all create edge cases that trip up hand-rolled parsers.
JsonHook solves this at the infrastructure level. Every email received by a JsonHook inbound address is automatically parsed by a battle-tested MIME library and the result is delivered to your webhook as a clean JSON object. Your application only sees the final, structured data — not the raw MIME.
The parsed JSON payload includes:
- Headers:
from,to,cc,bcc,replyTo,subject,messageId,date, and all raw header fields - Body:
textBody(plain text),htmlBody(HTML version if present) - Attachments: array of objects with
filename,contentType,size, andcontentId - Metadata: delivery timestamp, envelope sender, recipient address
Prerequisites
To receive parsed email JSON from JsonHook, you need:
- A JsonHook account (free tier available)
- An inbound address created via the API or dashboard
- A webhook endpoint that can receive HTTPS POST requests
If you want to explore the payload structure before building a full handler, set your webhook URL to a temporary inspector like webhook.site or requestbin.com — you'll see the exact JSON JsonHook sends for a real email within seconds of sending a test message.
Get Parsed Email JSON in Seconds
No MIME parsing. No email server. Just clean JSON delivered to your endpoint.
Get Free API KeyStep-by-Step Instructions
Here is how to go from raw email to parsed JSON in your application:
- Create a JsonHook inbound address. Use the API or dashboard to create an address and point it at your webhook handler URL.
- Send a test email. Send a message to your JsonHook address, ideally one with both a plain-text and HTML body and at least one attachment so you can see all payload fields populated.
- Inspect the JSON payload. Your webhook receives a POST body like this:
{ "email": { "from": "[email protected]", "to": ["[email protected]"], "subject": "Test message", "textBody": "Hello, this is a test.", "htmlBody": "<p>Hello, this is a test.</p>", "date": "2025-01-12T10:00:00Z", "messageId": "<[email protected]>", "headers": { "x-mailer": "MyApp/1.0" }, "attachments": [ { "filename": "invoice.pdf", "contentType": "application/pdf", "size": 48210 } ] }, "deliveryId": "dlv_01HX...", "receivedAt": "2025-01-12T10:00:01Z" } - Access fields in your handler. Read
payload.email.textBody,payload.email.from, etc. directly — no further parsing needed. - Handle null fields gracefully. If an email has no HTML version,
htmlBodywill benull. Always check before accessing nested data.
Code Example
This Python Flask handler extracts the sender, subject, and plain-text body from a parsed JsonHook email payload:
import hmac
import hashlib
import json
from flask import Flask, request, abort
app = Flask(__name__)
SECRET = b"your_webhook_secret"
@app.route("/webhooks/email", methods=["POST"])
def handle_email():
sig = request.headers.get("X-JsonHook-Signature", "")
expected = hmac.new(SECRET, request.data, hashlib.sha256).hexdigest()
if not hmac.compare_digest(sig, expected):
abort(401)
payload = json.loads(request.data)
email = payload["email"]
sender = email["from"]
subject = email["subject"]
text = email.get("textBody") or ""
attachments = email.get("attachments", [])
print(f"From: {sender}, Subject: {subject}")
print(f"Body preview: {text[:200]}")
print(f"Attachments: {[a['filename'] for a in attachments]}")
return "", 200
Notice the use of email.get("textBody") or "" — this safely handles emails where textBody is null.
Common Pitfalls
Watch out for these issues when working with parsed email JSON:
- Assuming textBody is always present. HTML-only emails have a
nulltextBody. Always handle both cases, or usehtmlBodyas a fallback. - Relying on subject format for routing. Subject lines change. Build routing logic against the recipient address (
email.to) rather than subject patterns, which are fragile. - Ignoring the
headersobject. Custom headers (X-Order-Id,X-Priority) are available inemail.headersas lowercase keys. They carry useful metadata from automated senders. - Not deduplicating on
messageId. Some mail servers deliver duplicate copies of the same message. Useemail.messageIdas an idempotency key in your database. - Expecting attachment content in the payload. JsonHook includes attachment metadata (filename, size, content type) but not the raw binary content inline. Attachment content download is available via a separate API call on Pro plans.