Receive email
Configure inbound
Section titled “Configure inbound”Create a receive-only Email instance with email.receive(options, handler).
import { email } from "@layeron/modules"
const inbound = email.receive({ name: "support", namespace: "comms", domain: "support.example.com",}, async (message) => { console.log({ from: message.from, to: message.to, cc: message.cc, subject: message.subject, text: message.text, })})
app.use(inbound)domain is the Cloudflare email domain hostname. Layeron enables Cloudflare
Email Routing DNS and updates the Email Routing catch-all rule for this
instance during deploy.
Handler
Section titled “Handler”The handler receives an EmailInboundMessage and a context object.
type EmailReceiveHandler = ( message: EmailInboundMessage, context: EmailReceiveContext,) => void | Promise<void>Message fields
Section titled “Message fields”| Field | Type | Description |
|---|---|---|
id | string | Message ID from email headers or a generated local ID. |
from | string | Sender email address. |
to | string | Recipient email address. |
cc | string[] | CC recipient addresses. |
bcc | string[] | BCC recipient addresses. |
replyTo | string | undefined | Reply-To header value. |
subject | string | undefined | Subject header value. |
text | string | undefined | Plain text body. |
html | string | undefined | HTML body. |
headers | Record<string, string> | Normalized email headers keyed by lowercase name. |
raw | string | Raw email source. |
receivedAt | string | ISO timestamp when Layeron received the message. |
Context
Section titled “Context”| Field | Type | Description |
|---|---|---|
messageId | string | The same message ID from the message. |
The handler runs asynchronously. The inbound email is durably recorded before the handler runs.
Deploy
Section titled “Deploy”layeron deployLayeron enables Cloudflare Email Routing DNS and updates the catch-all rule for the domain to route to the Email product Worker.
The deploy fails when Cloudflare cannot find the zone for domain in the
connected account.
Test locally
Section titled “Test locally”Run local dev, then call the inbound debug endpoint with the recipient address in the path.
curl -X POST \ "http://127.0.0.1:8787/cgi-bin/receive-email/support@mail.example.com" \ -H "content-type: application/json" \ -d '{ "from": "customer@example.com", "cc": ["manager@example.com"], "subject": "Need help", "text": "Hello from local dev" }'The debug endpoint accepts these fields in the JSON body:
| Field | Type |
|---|---|
from | string |
to | string |
cc | string | string[] |
bcc | string | string[] |
replyTo | string |
subject | string |
text | string |
html | string |
headers | Record<string, string> |
messageId | string |
raw | string |
Query parameters with the same names work for quick GET tests.
The endpoint responds with the processing result:
{ "status": "processed", "messageId": "<layeron-...@local.layeron>"}status is processed when the handler ran, or ignored when no receive
handler was configured for the domain.