Skip to content

Concepts

Understanding MXHook's core concepts helps you configure it effectively.

Domains

A domain represents an email domain that MXHook is authorized to receive mail for. When an email arrives, MXHook checks the recipient's domain against registered domains and rejects mail for unknown domains.

yourdomain.com     ✓ registered → accepted
unknown.com        ✗ not registered → rejected at SMTP level

Domains are managed via the REST API or the mxhook domain CLI command.

Routes

A route connects a recipient pattern to a webhook URL. When an email matches a route's pattern, MXHook delivers the parsed payload to that route's webhook endpoint.

Each route has:

  • Domain — which domain this route applies to
  • Recipient pattern — who the email is addressed to (supports exact, wildcard, and plus-addressing)
  • Webhook URL — where to deliver the parsed email
  • Webhook secret (optional) — used to sign payloads with HMAC-SHA256

Matching Patterns

PatternMatchesExample
user@domain.comExact address onlyuser@domain.com
*@domain.comAny recipient on the domainalice@domain.com, bob@domain.com
user@domain.comPlus-addressing variantsuser+tag@domain.comuser@domain.com

Routes are evaluated in priority order. The first matching route wins.

Message Lifecycle

Every email that enters MXHook moves through a series of states:

accepted → queued → parsed → routed → delivered

                               failed → retried → delivered

                                 dlq
StateDescription
acceptedSMTP server received the message
queuedMessage placed in the processing queue
parsedEmail parsed into structured data
routedMatched to a route with a webhook destination
deliveredWebhook POST succeeded (2xx response)
failedWebhook POST failed, will retry
retriedRetrying delivery with exponential backoff
dlqAll retry attempts exhausted, moved to dead letter queue

Queue

MXHook uses a queue to decouple SMTP ingestion from webhook delivery. This ensures the SMTP server responds quickly and messages are processed reliably.

Two queue backends are supported:

  • PostgreSQL (default) — uses SELECT FOR UPDATE SKIP LOCKED for at-most-once delivery
  • Cloudflare Queues — for serverless/edge deployments

Webhook Delivery

When a message is routed, MXHook:

  1. Serializes the parsed email as JSON
  2. Signs the payload with HMAC-SHA256 using the route's secret (if configured)
  3. POSTs to the webhook URL with the signature in the X-MXHook-Signature header
  4. Retries with exponential backoff on failure (default: 3 attempts)
  5. Moves to the dead letter queue if all retries are exhausted

Dead Letter Queue

The DLQ captures messages that failed all delivery attempts. You can:

  • Inspect failed messages to understand why delivery failed
  • Replay messages to re-attempt delivery
  • Remove entries once they're handled

See the DLQ guide for details.

Released under the Apache 2.0 License.