How to Parse Email to JSON

Stop writing MIME parsers. JsonHook converts every inbound email into a clean, structured JSON object — headers, body, attachments, and all — delivered directly to your webhook.

Table of Contents
  1. Overview
  2. Prerequisites
  3. Step-by-Step Instructions
  4. Code Example
  5. Common Pitfalls

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, and contentId
  • 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 Key

Step-by-Step Instructions

Here is how to go from raw email to parsed JSON in your application:

  1. Create a JsonHook inbound address. Use the API or dashboard to create an address and point it at your webhook handler URL.
  2. 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.
  3. 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"
    }
  4. Access fields in your handler. Read payload.email.textBody, payload.email.from, etc. directly — no further parsing needed.
  5. Handle null fields gracefully. If an email has no HTML version, htmlBody will be null. 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 null textBody. Always handle both cases, or use htmlBody as 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 headers object. Custom headers (X-Order-Id, X-Priority) are available in email.headers as lowercase keys. They carry useful metadata from automated senders.
  • Not deduplicating on messageId. Some mail servers deliver duplicate copies of the same message. Use email.messageId as 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.

Frequently Asked Questions

Does JsonHook parse all MIME email formats including multipart/mixed?

Yes. JsonHook's parser handles all standard MIME types including multipart/mixed, multipart/alternative, multipart/related, and deeply nested MIME trees. The result is always normalized into the same flat JSON structure regardless of the original MIME complexity.

Are email headers included in the JSON payload?

Yes. All headers are available under email.headers as a key-value map with lowercase header names. Standard headers like from, to, subject, and date are also promoted to top-level fields on the email object for convenience.

How does JsonHook handle character encoding in email bodies?

JsonHook decodes all standard email character encodings (quoted-printable, base64, UTF-8, ISO-8859-1, Windows-1252, etc.) and delivers the body content as a proper UTF-8 string in the JSON payload. You never have to deal with encoded bytes or charset declarations.

What is the maximum email size JsonHook will parse?

JsonHook parses emails up to 25 MB in total size, which covers the vast majority of real-world email including emails with multiple attachments. Emails exceeding this limit are rejected at the SMTP level and the sender receives a bounce notification.