Open Source · Apache 2.0

Open-source inbound
email webhooks.

MXHook is a self-hosted SMTP server that receives email, parses it into structured JSON, and delivers it to your application via webhooks. An open-source alternative to Mailgun Routes, Sendgrid Inbound Parse, and Postmark Inbound.

terminal
$git clone https://github.com/mxhook/mxhook && cd mxhook
$cp .env.example .env
$docker compose up
✓ SMTP server listening on :2525
✓ API server listening on :8080
✓ Ready to receive email
<800ms
p95 webhook delivery
100+
emails per second
10MB
max message size
Apache 2.0
fully open source

Three steps. No mail server.

From MX record to webhook in minutes.

1

Point your MX records

Add a single DNS record to route your domain's inbound email to MXHook.

2

MXHook parses the email

Headers, body, and attachments are extracted into structured JSON. RFC 5322 compliant.

3

Receive a signed webhook

MXHook POSTs JSON to your endpoint, signed with HMAC-SHA256, with automatic retries on failure.

What your endpoint receives

Every inbound email becomes a signed HTTP POST with structured JSON. Headers, body, attachments — parsed and ready to use.

webhook-payload.jsonPOST /your-webhook
{
  "from": "alice@example.com",
  "to": ["support@yourapp.com"],
  "subject": "Order #1234 issue",
  "text": "Hi, I have a problem with my order...",
  "html": "<p>Hi, I have a problem with my order...</p>",
  "headers": {
    "message-id": "<abc123@example.com>",
    "in-reply-to": "<prev456@example.com>",
    "date": "2026-03-19T10:30:00Z"
  },
  "attachments": [
    {
      "filename": "screenshot.png",
      "content_type": "image/png",
      "size": 48210
    }
  ]
}
X-MXHook-Signature: sha256=a1b2c3d4...

Everything you need for inbound email.

Production-ready features, out of the box.

Pattern Routing

Route emails by exact match, wildcard, or plus-addressing. *@yourapp.com routes all mail. user+tag@yourapp.com strips the tag and matches. Priority-ordered rules give you full control.

Webhook Signing

Every delivery includes an X-MXHook-Signature header with an HMAC-SHA256 hash. Verify authenticity with constant-time comparison. One line of code.

Retries & Dead Letter Queue

Failed deliveries retry with exponential backoff. After max attempts, messages land in a dead letter queue. Replay any message via the API.

Raw Email Storage

Original .eml files are stored alongside parsed data. Useful for compliance, auditing, or reprocessing later.

Prometheus Metrics

mxhook_messages_received_total, mxhook_delivery_latency_seconds — latency, throughput, and error rates exposed out of the box.

REST API

Manage domains, routes, messages, and DLQ entries programmatically. Full OpenAPI 3.1 spec included. Authenticate with API keys.

Multi-Domain

Register as many domains as you need. Each domain gets its own routing rules, webhook endpoints, and delivery logs.

Self-Hosted

Run on your infrastructure with Docker Compose, or deploy to any container platform. Your data never leaves your network.

Built for AI

Your agent's inbox,
as an API.

Autonomous agents and LLM-powered workflows need to receive email — support requests, notifications, form submissions, approval chains. MXHook delivers structured JSON over HTTP. No IMAP libraries. No email parsing SDKs. Just an HTTP POST with clean data.

  • Structured by default

    Subject, sender, body, threading headers (In-Reply-To, References), and attachments arrive as typed JSON fields. No parsing step needed.

  • Webhook-native

    Your agent receives email the same way it receives any event: a signed HTTP POST to an endpoint you control.

  • Programmable routing

    Route different senders, domains, or subject patterns to different agent endpoints. Support emails go to one agent, billing to another.

  • Conversation threading

    In-Reply-To and References headers let agents track multi-turn email conversations without external state.

agent_inbox.pyPython
@app.post("/webhook/support")
async def handle_support_email(payload: dict):
    customer = payload["from"]
    subject = payload["subject"]
    body = payload["text"]
    thread_id = payload["headers"].get("in-reply-to")

    # Extract intent using an LLM
    intent = await llm.classify(
        f"Subject: {subject}\nBody: {body}"
    )

    if intent == "order_issue":
        order_id = extract_order_id(subject)
        order = await db.get_order(order_id)
        response = await llm.draft_response(order, body)
        await email.send(to=customer, body=response)

    elif intent == "refund_request":
        await tickets.create(
            customer=customer,
            type="refund",
            context=body,
            thread=thread_id
        )
Apache 2.0 License

Open source. Self-hosted. Yours.

MXHook core is licensed under Apache 2.0. Run it on your infrastructure. Full source on GitHub. No vendor lock-in, no data leaving your network, no usage limits.

Enterprise features — regex routing, header-based conditions, RBAC — are available under a Business Source License that converts to Apache 2.0 after two years.

Don't want to self-host?

MXHook Cloud is a fully managed version — we run the SMTP servers, handle scaling, and guarantee uptime. You configure routes and receive webhooks. Currently in development.

Join the waitlist

Frequently asked questions

Everything you need to know about MXHook.