← Back to documentation

Email Ingestion

Enable email ingestion on an endpoint to convert inbound email into JSON payloads dispatched to your configured outputs.

5 min read

Email ingestion converts inbound email into JSON relay payloads. Send an email to your endpoint's email address and it gets forwarded to all configured output targets — webhooks, email, Slack, Discord, and Google Sheets.

How it works

  1. You enable email ingestion on an endpoint.
  2. The endpoint gets an email address: {endpointId}@payloadrelay.com.
  3. When someone sends email to that address, the email is parsed into a JSON payload.
  4. The JSON payload is dispatched to all configured output targets, just like an HTTP webhook.

Email payload format

The inbound email is converted to this JSON structure:

Code Example
{
  "from": "sender@example.com",
  "to": ["abc123@payloadrelay.com"],
  "cc": ["cc@example.com"],
  "bcc": [],
  "replyTo": "sender@example.com",
  "subject": "Order confirmation #1234",
  "textBody": "Your order has been confirmed...",
  "htmlBody": "<html>...</html>",
  "date": "2024-01-15T10:30:00Z",
  "messageId": "<abc123@mail.example.com>",
  "headers": {
    "X-Mailer": "Outlook 16.0",
    "X-Priority": "1"
  }
}

What's included

  • Sender, recipients (to/cc/bcc), reply-to address
  • Subject line
  • Text and HTML body content
  • Date and message ID
  • Selected email headers

What's excluded

  • Attachments are stripped entirely. Only text content is relayed.
  • Binary content, inline images, and embedded files are not included.

Body-as-payload mode

By default, the envelope JSON above is the relay payload. If you want the email body itself to be the payload (e.g. an automated system emails a JSON document), enable Treat email body as webhook payload body on the endpoint's Details tab.

When enabled, the body is parsed according to the endpoint's configured payload format:

Payload formatParsing
JSONtextBody parsed as JSON (falls back to htmlBody if textBody is empty).
XMLtextBody forwarded as raw XML text node.
TEXT_PLAINtextBody forwarded verbatim as a string.
FORM, QUERY_PARAMS, QUERY_PARAMS_BASE64_JSONNot supported — rejected as EMAIL_INGESTION_REJECTED.

If parsing fails (e.g. the body isn't valid JSON for a JSON endpoint), the email is rejected with EMAIL_INGESTION_REJECTED and the sending MTA receives an SMTP 550 permanent failure.

Filters and field validations

When body-as-payload mode is enabled, request body filters and field validations configured in the Filter tab also apply to the parsed email body — the same processing pipeline used for webhook payloads. This lets you drop, require, or validate fields in the email body exactly as you would for an HTTP request.

When body-as-payload mode is disabled, filters and field validations have no effect (the metadata envelope has a fixed structure).

Accessing envelope fields as template variables

When body-as-payload is enabled, the envelope (from, subject, to, headers, …) is still accessible inside webhook custom bodies, custom headers, email subjects/bodies, and reply-to fields via the {{email.*}} namespace:

  • {{email.from}}
  • {{email.subject}}
  • {{email.textBody}}, {{email.htmlBody}}
  • {{email.date}}, {{email.messageId}}, {{email.replyTo}}
  • {{email.to}}, {{email.cc}}, {{email.bcc}} — arrays render as comma-separated strings
  • {{email.headers.X-Mailer}} (or any other header name)

These variables are also available in envelope mode (alongside the regular {{from}}, {{subject}}, … which resolve directly against the payload).

Enabling email ingestion

  1. Open the endpoint editor.
  2. In the endpoint editor header, select Email ingestion endpoint from the Endpoint type dropdown.
  3. The email address appears in the Details tab. Copy it.
  4. Save changes.

The endpoint must be enabled and have its type set to Email ingestion endpoint for inbound email to be accepted. Endpoints are exclusively one type — switching from webhook to email clears webhook-specific settings (inbound auth, captcha, IP restrictions, CORS, required headers).

Quota and billing

Each inbound email consumes one request from your monthly quota, the same as an HTTP relay request.

Activity log

Email-sourced relays appear in the Activity tab with these outcome types:

OutcomeMeaning
EMAIL_INGESTION_ACCEPTEDEmail was accepted and dispatched to outputs.
EMAIL_INGESTION_REJECTEDEmail was rejected (endpoint disabled, email ingestion off, or other validation failure).

SPF / DKIM / DMARC enforcement

PayloadRelay can use SPF, DKIM, and DMARC verdicts from trusted mail infrastructure to decide whether an inbound email should be accepted.

Each endpoint has three independent toggles — Require SPF pass, Require DKIM pass, Require DMARC pass — under the endpoint's Security tab. They are off by default.

When enforcement is enabled, only a verdict of pass is accepted. Missing, none, neutral, temperror, softfail, fail, and permerror all result in rejection with AUTH_FAILED in the activity log and an SMTP 550 permanent failure.

Header resultEnforcement outcome
passAccepted.
fail, softfail, permerrorRejected.
none, neutral, temperrorRejected.
missing headerRejected.

The authResults object is also forwarded in the email envelope payload (e.g. {{email.authResults.spf}}) so you can inspect it in transforms or templates even when enforcement is off.

Trusted mail authentication results

Only authentication results from trusted mail infrastructure should be used for SPF/DKIM/DMARC enforcement. If your organization relies on custom mail routing before messages reach PayloadRelay, make sure the system that receives mail for your domain is configured to provide trustworthy authentication results. Contact support if you are unsure whether enforcement is appropriate for your setup.

Allowed senders

You can restrict which email addresses are allowed to send to your endpoint using the Allowed senders list in the Security tab.

  • Add specific addresses: user@example.com
  • Use wildcards to match patterns: *@company.com matches any sender from that domain
  • Leave the list empty to allow any sender (default)

Each entry must be either a valid email address or a wildcard pattern of the same shape (e.g. *@company.com, billing@*, *@*.example.com). You can configure up to 100 unique entries; each entry is limited to 320 characters. Entries are normalised to lowercase on save. Invalid or duplicate entries are rejected with a 400 Bad Request before the endpoint is saved. A universal *@* pattern is not accepted — leave the list empty instead.

When a sender is not in the allowed list, the email is rejected with EMAIL_INGESTION_REJECTED in the activity log and the sending MTA receives an SMTP 550 permanent failure.

The check is performed against the SMTP envelope sender (MAIL FROM), not the message's From: header. The From: header is trivially spoofable by anyone, so an allow-list that matched against it would offer no real protection. As a consequence:

  • A message with MAIL FROM:<attacker@evil.example> and a forged From: trusted@company.com header is rejected when trusted@company.com is on the allow-list — only the envelope address attacker@evil.example is checked.
  • DSN bounce messages, which use the SMTP null-sender (MAIL FROM:<>), are rejected when an allow-list is configured. If you need to receive bounces, leave the allow-list empty and rely on SPF/DKIM/DMARC enforcement instead.

DSN and bounce messages

Delivery Status Notifications (DSN) and automatic bounce messages (e.g. out-of-office replies, non-delivery reports) use the SMTP null sender — MAIL FROM:<> — as specified in RFC 5321. This means the SMTP envelope sender is an empty string.

Behavior with allowed-senders configured: Null-sender messages are rejected because the empty sender does not match any pattern in the allow-list. If you need your endpoint to receive bounce or DSN notifications, leave the allowed-senders list empty.

Behavior without allowed-senders (default): Null-sender messages pass the sender check. The envelopeFrom field in the relay payload will be an empty string, and from will contain whatever the From: header says (which may be the bounce originator address).

Behavior with SPF enforcement enabled: DSN messages will typically fail SPF because the null sender is used for the envelope and no SPF record covers it. If you need to receive DSNs, disable SPF enforcement or handle them via a separate endpoint without enforcement.

Email metadata headers injected into the payload

Every email relayed through PayloadRelay is converted to a structured JSON payload. The top-level fields are always present (though some may be null or empty):

FieldSourceNotes
fromFrom: header (display address)Spoofable. Use envelopeFrom for trust-sensitive checks.
envelopeFromSMTP MAIL FROMEmpty string for DSN/bounce null senders. Use this for allowed-sender enforcement.
toTo: headerArray of addresses.
ccCc: headerArray of addresses; empty array if absent.
bccBcc: headerUsually absent (stripped by sending MTA).
replyToReply-To: headernull if absent.
subjectSubject: headernull if absent.
textBodyFirst text/plain MIME partnull if no plain-text part.
htmlBodyFirst text/html MIME partnull if no HTML part.
dateDate: headerISO 8601 UTC string (e.g. 2024-01-15T10:30:00Z), or null.
messageIdMessage-ID: headerIncludes angle brackets, e.g. <abc@mail.example.com>.
headersAll remaining headersMap of header name → first value. Standard headers are excluded (see below).
authResultsAuthentication-Results: headerMap with keys spf, dkim, dmarc and values like pass, fail, etc.

The headers map

All non-standard headers are forwarded in the headers map. The following standard headers are excluded from headers (they are already represented as top-level fields):

From, To, Cc, Bcc, Reply-To, Subject, Date, Message-ID, Content-Type, Content-Transfer-Encoding, MIME-Version, Authentication-Results

Headers that remain in the headers map include (non-exhaustive):

  • Received — SMTP relay trace headers added by each hop. Multiple Received headers exist; the map stores the first occurrence only.
  • DKIM-Signature — Raw DKIM signature from the sending domain.
  • Return-Path — Bounce address set by the final MTA.
  • ARC-* — Authenticated Received Chain headers (RFC 8617).
  • X-Mailer, X-Priority, X-Spam-Status, and any other X- headers from the sender.
  • List-Unsubscribe, List-Id, and other RFC 2369 list headers.

Note: Because Received, DKIM-Signature, and ARC-* headers can contain detailed routing and infrastructure information, they will appear in your relay payload and may be forwarded to downstream targets. If this is undesirable, use a transform rule to remove them before dispatch.

The authResults map

The authResults map is populated from the Authentication-Results header stamped by the upstream MTA. Keys are spf, dkim, dmarc; values are lowercase result strings (pass, fail, softfail, neutral, none, temperror, permerror). A key is absent if the upstream MTA did not report a result for that check.

You can reference these values in templates as {{email.authResults.spf}}, {{email.authResults.dkim}}, {{email.authResults.dmarc}}.

Operator note (self-hosted only): PayloadRelay's email receiver supports a payloadrelay.email.trusted-authserv-ids configuration (env var TRUSTED_AUTHSERV_IDS, comma-separated list of authserv-id values). When set, only Authentication-Results headers stamped by a trusted authserv-id are parsed; all others are ignored. When unset, only the first Authentication-Results header is read (per the RFC 8601 prepend convention) and a startup warning is logged. Hosted PayloadRelay deployments configure the value of their boundary MTA so that injected Authentication-Results headers from a sender cannot spoof verdicts.

  • 10 MB maximum message size. Emails exceeding this limit are rejected at the SMTP level.
  • No attachments. Only text/HTML bodies are included in the payload. See Multipart parsing below for details.
  • SPF/DKIM/DMARC validation relies on the upstream MTA's Authentication-Results header — see the dedicated section above. In-process DNS verification is not performed.
  • Webhook-specific security features — inbound authentication, captcha, required-headers, IP allowlists, and CORS restrictions are designed for HTTP requests and are not available for email endpoints. Use allowed senders and sender authentication enforcement instead.
  • Transforms and append-field rules apply — they operate on the JSON envelope (or the parsed body, in body-as-payload mode) and run before dispatch, so you can extract values from textBody/headers into the outgoing payload.

Multipart parsing

Email bodies are extracted from the MIME structure according to these rules:

Part typeExtraction behaviour
text/plainExtracted as textBody. When multiple text/plain parts exist, the first is used.
text/htmlExtracted as htmlBody. When multiple text/html parts exist, the first is used.
Attachments (any other content type, Content-Disposition: attachment, binary)Silently dropped. Only text content is relayed.
Inline images / embedded filesSilently dropped.

Deeply nested messages and attachments

Very deeply nested MIME parts may be skipped to keep email processing safe and reliable. Attachments are dropped rather than truncated. The total message must stay within PayloadRelay's email size limit.

Use cases

  • Alert forwarding: Route system alert emails to Slack, Discord, or a webhook.
  • Form submissions via email: Accept structured email content and forward to a webhook or Google Sheet.
  • Email-to-API bridge: Convert email notifications from third-party services into API calls via webhook targets.
  • Monitoring dashboards: Pipe email alerts into a central webhook endpoint for aggregation.

Related guides