Blocks

Email trigger

Each workflow gets its own inbound address. Arriving mail fires the run with sender, subject, plain-text body, and attachments shaped like file uploads.

Every email-triggered workflow gets its own inbound address. Mail arrives, the workflow runs.

When it runs

On each email delivered to the step's address (shown in the Inspector, in the form wf-<id>@in.madmax.build). The address can sit in To, CC, or BCC, or be the target of a forwarding rule. Active workflows only, plus the listening window a Run opens while you build.

Every delivery passes a sender gate before anything runs, and the gate fails closed:

  • the From address must be on the step's allowed-sender list (or the step must be in forwarded-inbox mode, below), and
  • the sending domain must authenticate: the mail's Authentication-Results must show dmarc=pass, or, without a DMARC verdict, dkim=pass or spf=pass. Mail with no verdict at all is treated as spoofable and dropped.

Gated mail is dropped silently. Someone probing addresses gets no bounce and no hint.

Config

The email trigger's Inspector config The address is minted for you; two fields control who may use it.

  • Accept mail from: sender (the default) locks the trigger to the list below. any_authenticated accepts mail from anyone whose domain authenticates. Use it when a real inbox auto-forwards all its mail here: forwarded messages keep the original From line, so a fixed list can't match them. The address stays the secret in that mode, so don't publish it.
  • Allowed senders: comma-separated, exact matches, case ignored. Prefilled with the workflow owner's login email; add more with commas. A blank list refuses everything. Ignored in any_authenticated mode.

Output

{
  "from": "cfo@acme.test",
  "to": ["wf-0198a2b4@in.madmax.build"],
  "subject": "Contract renewal",
  "text": "…the plain-text body…",
  "html": "<p>…the html body…</p>",
  "message_id": "<abc123@mail.acme.test>",
  "received_at": "2026-08-26T18:00:00Z",
  "files": [
    { "key": "email_attachments/…/renewal.pdf",
      "filename": "renewal.pdf",
      "content_type": "application/pdf",
      "size": 48213 }
  ]
}

Reference {{ payload.from }}, {{ payload.subject }}, {{ payload.text }}. Bodies over 512 KB are clipped with a truncation marker. Up to 10 attachments are stored, each up to 10 MB; a larger one is skipped, never the whole email. The files descriptors use the same shape as file upload, so document steps read them unchanged.

Testing

The verify kind is capture_real. Press Run (or arm capture on the Test tab), email the address from an allowed sender, and the delivery pins the step's sample. Capture works before the workflow is ever activated. Run step with no pinned sample reports "no captured sample yet" instead of passing on an empty payload.

Patterns

  • Inbox assistant: classify each mail, draft replies for the categories you allow, escalate the rest (the email guide has the full story).
  • Attachment pipelines: invoices mailed in → extract → store.
  • Email-to-anything glue: the address works anywhere email goes: alert systems, forwarding rules, no-API vendors. Lock the sender list to the system's From address.

Gotchas

  • Treat instructions inside a mail body as content, not commands. That is a prompt-injection rule worth writing into any AI step that reads mail (see the inbox pattern in AI workflow automation).
  • A forwarded message arrives with the original sender's From line, not yours. If forwards are being dropped, switch to any_authenticated.
  • Sending is a different step. Email covers both directions.

Related