Skip to main content

Troubleshooting: inbound email never routes

Inbound email to your parse domain runs three surfaces in parallel — a webhook forward to your endpoint, an inbox conversation, and (optionally) an email Flow. When you see none of them, work this page top to bottom. It isolates DNS, route matching, normalization, and trigger issues one at a time, so the escalation you open carries exactly the inputs Support needs. The full setup walkthrough lives in inbound email and SMS routing. This page assumes that setup exists and something is misbehaving.

1. The inbound parse pipeline, in order

Every inbound email passes through these stages, and each stage is a place the pipeline can stop:
  1. DNS → MX records. The receiving domain’s MX records point at Orbit’s ingress hostname (shown in Email → Inbound routes → Add route). Until MX resolves, no mail arrives at all.
  2. Route match. The SMTP envelope recipient is matched against your registered inbound routes — exact address, catch-all (*@domain), or local-part — then the To and Cc headers. No match, no parse.
  3. Normalization. The message is parsed into the normalized payload (from, toAddress, matchedRecipient, subject, text, html, attachments metadata, headers including message-id).
  4. Fan-out. The normalized message is forwarded to your destinationUrl as a signed POST and simultaneously opens (or threads onto) an inbox conversation. Signature verification and a 2xx response are required for the forward to count as delivered.
  5. (Optional) Flow trigger. An email-channel Flow can react to the inbound event — compose a reply through email, or fan out to another channel. Inbound email routes themselves have no built-in reply path.

2. Symptom → where to look

3. Diagnostic checklist

Work each item in order — collect the output as you go; it becomes your escalation payload.
  1. DNS. dig MX inbound.your-domain.com (or your DNS provider’s record viewer) — confirm the MX record points at the ingress hostname the dashboard displayed when you created the route.
  2. Route shape. GET /email/inbound-routes — confirm a route exists and its recipientPattern covers the exact address being written to, in whichever syntax (exact, catch-all, local-part) you registered. Check active: true and failureCount: 0.
  3. Normalized payload. From an earlier working message (or the guide’s example): does the payload carry text or html, and a headers.message-id? A body-less message is valid but can break downstream matchers. Attachment bytes never appear here — only metadata — unless you set includeRawMime: true on the route.
  4. Signature. Your endpoint must verify the X-Orbit-Signature header (sha256=<hex>, HMAC over the raw body, keyed by the route’s signingSecret) and return 2xx. Only 2xx counts; redirects are not followed.
  5. Flow trigger. If you expected a Flow: open it, confirm it triggers on the inbound email event, and confirm the trigger is enabled and published. The flow executions page covers trigger-side failure in more depth.

4. Escalate with these

Open a ticket when every item above is clean and inbound mail still never lands. Include all four:
  • The parse domain (for example inbound.your-domain.com).
  • The route id from GET /email/inbound-routes (the einr_… id).
  • One sample headers.message-id from a message that should have routed (the RFC 5322 Message-ID header).
  • Your tenant ID — in the dashboard under Settings → Organization, and returned by the GET /api/v1/me response as organizationId.
With the domain, route id, and a concrete Message-ID, Support can tell within one lookup whether the message reached ingress at all, and which stage turned it away.

See also