MXcatch
Use case

Turn email into a webhook

Point your MX records at MXcatch and every message sent to your domain arrives at your endpoint as signed JSON — parsed, decoded, and with attachments already extracted.

The usual way is worse than it looks

Receiving email programmatically has three well-worn options, and all of them cost more than they first appear.

Running your own SMTP server means owning spam filtering, TLS, greylisting, MIME parsing and the operational reality of a service that anyone on the internet can connect to. It is a genuinely hard surface to keep healthy, and it is rarely the problem you set out to solve.

Polling IMAP is the shortcut most people take. It works until it doesn't: you inherit connection limits, flaky mailbox state, races between workers marking messages as read, and a latency floor set by your polling interval. Debugging "why did this message get processed twice" at 2am is a rite of passage nobody needs.

Zapier or Make gets you moving in an afternoon and then meters you per task. Fine for a hundred messages a month; painful at ten thousand, and you are still one vendor away from your own data.

What MXcatch does instead

MXcatch is the SMTP server. It accepts the connection, handles TLS, parses the MIME tree, decodes the subject and body, extracts attachments to object storage, and then makes one HTTPS POST to you with the result.

Your side of the contract is a single endpoint that verifies a signature and returns 200.

The payload

POST /your/webhook200 OK
// X-MXcatch-Signature: sha256=a1b2c3...
{
  "event": "email.received",
  "id": 48213,
  "received_at": "2026-08-29T09:14:02+00:00",
  "from": { "address": "notify@stripe.com", "name": "Stripe" },
  "to": "billing@acme.com",
  "subject": "Invoice paid",
  "text": "Your subscription has been renewed.",
  "attachments": [{
    "name": "receipt.pdf",
    "size": 49152,
    "sha256": "9f8e7d...",
    "url": "https://ams3.digitaloceanspaces..."
  }]
}

Verifying it

$raw = file_get_contents('php://input');
$expected = 'sha256=' . hash_hmac('sha256', $raw, $secret);

if (! hash_equals($expected, $_SERVER['HTTP_X_MXCATCH_SIGNATURE'] ?? '')) {
    http_response_code(401);
    exit;
}

Node and Python equivalents are in the webhook reference, along with the full field-by-field schema.

Setting it up

  1. Add your domain and set two MX records — per-provider instructions.
  2. Create an alias, or turn on catch-all to receive every address on the domain.
  3. Add a webhook action with your endpoint URL and a signing secret.
  4. Email the address. The POST arrives within seconds.

What people build with it

Delivery guarantees

Deliveries are at-least-once. A 2xx acknowledges; anything else — including a timeout — schedules a retry, five attempts over roughly 45 minutes with widening gaps.

Because a response can be lost after your side has already committed, key your processing on the id field, which is stable across retries of the same message. And acknowledge fast: do the real work in a background job rather than holding the request open, or you will collect retries for messages you have already handled.

Compared with the alternatives

If you are currently on Cloudflare Email Routing, webhooks mean writing and maintaining a Worker. On Mailgun Routes you get a webhook, but as multipart form fields on a plan priced for outbound sending you may not need. ImprovMX forwards mail but does not do webhooks at all.

Frequently asked questions

How do I convert an email into a webhook?

+
Point your domain's MX records at MXcatch, create an alias, and add a webhook action with your endpoint URL. Every message that arrives at that address is POSTed to you as signed JSON, usually within a few seconds.

Do I need to run an SMTP server?

+
No. MXcatch runs the SMTP side — accepting connections, handling TLS, parsing MIME, decoding attachments. Your side only ever sees an ordinary HTTPS POST.

How are attachments delivered?

+
As pre-signed download URLs valid for 60 minutes, with the filename, MIME type, byte size and SHA-256 alongside. Nothing is base64-inlined, so a large PDF does not bloat the request body.

How do I know the request really came from MXcatch?

+
Every request carries an X-MXcatch-Signature header: an HMAC-SHA256 of the raw body, keyed with your secret. Verification is a few lines in any language — see the webhook reference.

What happens if my endpoint is down?

+
The delivery is retried five times over roughly 45 minutes with an increasing gap. A handler that is briefly down catches up without losing anything.

Can I use a catch-all address?

+
Yes, and it is a common setup: turn on catch-all and every address on the domain becomes an event stream into a single endpoint, with the recipient in the payload's to field.

Your first webhook, five minutes from now.

Free forever for one domain. No card, no trial clock.

Create your free account