One inbound email, end to end
Inbound email on Orbit has two reference guides: Inbound email and SMS routing documents the parse webhook anatomy and the DNS/console steps, and Route inbound support mail to the right team and ticket documents the route-to-ticket patterns. This guide is the missing piece between them: one concrete email, followed through every surface in order, so you leave knowing whether your setup needs a route, a webhook receiver, a Flow, or all three. You will:- Pick your guide
- Meet the email you will follow
- Point the domain at Orbit
- Watch SMTP receive become a signed parse POST
- Verify the signature
- Read the message in the dashboard
- Send the reply
- Recognize the failure paths
1. Pick your guide
The question every new email customer asks is whether they need a route, a webhook, a Flow, or all three. The answer, in one paragraph: the route is the only required piece — no route match means no parse and no ticket. The webhook receiver is where the signed parse POST goes; it is optional if the dashboard alone is enough for your team, because the inbox ticket opens whether or not your endpoint answers. A Flow is optional automation on top — an auto-reply or a branch — and is only needed when something must happen without a human. This walkthrough wires all three surfaces minimally so you can see each one do its job.
2. Meet the email you will follow
Every example in this guide follows the same message. A customer, Maya, writes to your support mailbox with a DKIM-signed reply, one PDF attachment, and one inline image:brightline.co. The signature you verify is the one Orbit adds to the webhook forward in step 5; the two solve different problems.
3. Point the domain at Orbit
Open Email → Inbound routes → Add route in the dashboard. The surface shows the ingress hostname your MX records must point at for the domain you register. At your DNS provider, set the MX record for the receiving domain (a dedicated domain or subdomain such asacme.example keeps inbound parse separate from your corporate mail):
dig returns the hostname and the console shows the domain as verified, send Maya’s message from step 2 (or forward a real one to support@acme.example).
Next, register the route that catches the mailbox. POST /email/inbound-routes takes the recipient pattern and your webhook URL:
201 response carries the route’s signingSecret exactly once — store it now, because list and get responses mask it. You use it in step 5.
recipientPattern accepts the exact address (used here), a catch-all (*@acme.example), or a bare local-part (support). Matching runs against the SMTP envelope recipient first, then the To and Cc headers, so BCC and forwarded mail route correctly. Registering the same pattern twice returns 409 CONFLICT. The full pattern reference lives in Inbound email and SMS routing.
4. Watch SMTP receive become a signed parse POST
Ingress accepts Maya’s message over SMTP, matches the route from step 3, and parses the raw MIME from step 2 into normalized fields. YourdestinationUrl then receives a signed JSON POST:
textandhtmlare the decoded body parts (either can benull); long bodies are shown trimmed here but arrive complete.attachmentsis metadata only: filename, MIME type, decoded byte size, and the inline image’sContent-IDincontentId. Attachment bytes are never inlined into the JSON — setincludeRawMime: trueon the route when you need the full original message alongside the normalized fields.headerscarries every top-level header as a lowercased key map, includingmessage-idand the sender’sdkim-signature.matchedRecipienttells you which registered pattern caught the mail — useful when a catch-all serves several mailboxes.
5. Verify the signature
The forward arrives with anX-Orbit-Signature header: sha256=<hex>, an HMAC over the raw request body keyed by the route’s signingSecret from step 3. Verify it before trusting anything in the body. A minimal Node receiver:
failureCount / lastFailureAt on GET /email/inbound-routes tell you when forwards are failing.
6. Read the message in the dashboard
While your webhook was being forwarded, the same message opened an inbox ticket. Open the inbox and find the thread by subject or sender — for Maya’s mail, a ticket titled Invoice question — order #1234 frommaya@brightline.co. The ticket carries the parsed body as its transcript and the sender’s address as the contact, so a second mail from Maya threads onto the same ticket instead of opening a new one.
The attachment story in the dashboard is one step behind the webhook payload: each decoded part is scanned before it is archived to your media store. A clean part (Maya’s order-1234.pdf) appears in the message detail with a fresh download URL; the inline image is recorded by its Content-ID. A part the scan drops never reaches the store — the payload’s attachments entry still lists it (metadata only), and the message record notes the drop with finding codes under metadata.email_attachments_quarantined. The inbound attachment threat scan concept page covers the clean / suspicious / malicious verdicts; Operate the Inbox Tickets queue covers working the queue.
The conversation also appears as a row under Maya’s contact on the Interactions page, which merges conversations and calls into one recency-ordered list — the place to look when you want the contact’s whole history rather than one ticket.
7. Send the reply
Two surfaces can answer Maya, and both keep the story coherent:- From the ticket. The inbox reply composer answers
maya@brightline.coand threads the exchange onto the same ticket — the designated path for agent-handled mail, and the one that cannot accidentally loop back into your own parse domain. - From the API.
POST /messages/emailsends the outbound half. Send from the same verified sender address the conversation started with, and keep the subject threaded withRe:so Maya’s mail client files the reply under the original message:
from must resolve to a verified sender on your account, and at least one of html / text must be non-empty; the full field table is in the email channel reference. When Maya writes back, her reply matches the route from step 3 again and threads onto the existing ticket, closing the loop.
If you automate the reply with a Flow instead of a human or a direct API call, guard it: an unguarded send back at your own parse domain closes the loop on itself and re-triggers the Flow. The troubleshooting guide covers the reply-to / subject guards.
8. Recognize the failure paths
The four failures every new setup hits once, and how each one looks from your side:
When none of the four explains it, work the inbound email troubleshooting guide top to bottom — it isolates DNS, route matching, normalization, and trigger issues one stage at a time, and lists exactly what to collect before escalating.
Next steps
- Inbound email and SMS routing — the full webhook anatomy and route reference this tutorial walked
- Route inbound support mail to the right team and ticket — the shared-mailbox pattern built on top of this loop
- Close the email loop: inbound parse, Flow reply, ticket — the outbound-then-inbound acknowledgement loop
- Verify webhook signatures — the polyglot verify snippets for the parse handshake
- Troubleshooting: inbound email never routes — when a message stops somewhere in this page’s pipeline