Skip to content
Nuits ReceiptsDocs
HomeSearch the docs, Ctrl KGitHubDark mode

Email and sender trust

Why only approved senders are read, what happens to mail from anyone else, how SPF and DMARC prove who sent a message, and why unproven mail is kept but not read.

Updated

An inbox address is convenient: you forward a receipt and it appears in the app. It is also an address anyone can write to. Every message that is read costs a little AI reading and puts a document into your books, so the app is strict about whose mail it reads. This page explains the three gates a message passes through and why each one exists.

Gate 1: approved senders

Only mail from an approved sender is read. The list starts from ALLOWED_SENDER_EMAILS and you manage it in Settings > Email > Email senders, or with Allow in Receipts To do. With an empty list, nothing is read. That is the default, so a fresh deployment never reads mail from strangers.

A sender counts as approved when either of these is on the list:

  • the envelope sender, the address the sending server gave when it delivered the message, or
  • the From address, when Cloudflare reports that DMARC passed for exactly that address’s domain.

The second case matters for shops and payment services. They often send from a bounce address that changes with every message, while the From address you see stays the same.

Mail from anyone else

Mail from a sender who is not on the list is not read and costs no AI reading. What happens next depends on whether Cloudflare’s checks prove who sent it:

  • Proven (DMARC passed for the From domain, or SPF passed for the envelope sender): the message is stored and shown at the top of Receipts To do as a New sender row, with who sent it, the subject, when it arrived, the address it was sent to and how many attachments it has. Nothing is read until you act.
  • Not proven: the message is dropped and logged. Nothing is stored.

For each Unknown sender item you can:

  • Allow: the exact address is added to your allowed senders, and this email plus any others waiting from them are read the normal way. Their future mail is read as soon as it arrives.
  • Ignore: their waiting mail is deleted, and future mail from them is logged but not kept. Because it deletes mail, Ignore asks first, with Ignore and delete. To read them again later, use Stop ignoring in Settings > Email > Email senders.

Limits keep a stranger from filling your storage: at most 50 Unknown sender emails wait at once and 10 from one sender, the same email (by Message-ID) is kept once, and the 20 MiB size limit applies. Mail over a limit is logged, not kept. The Worker’s log names only the sender’s domain, never the full address.

Settings > Email > Email senders ends with Mail we didn’t keep: the emails that reached the app but were not read, newest first, with the sender, the subject and the reason. It lets you see why a message did not turn into a receipt, and Allow a sender from there. Only these details are kept, never the message. See App pages.

If you set FORWARD_COPY_TO, every message that reaches the Worker is also forwarded there, from any sender, whether or not it is read. That is how one-time codes and other mail sent to the receipt address still reach a person. See Forward a copy of incoming mail.

Gate 2: proving the sender

An envelope sender is just text. Anyone can claim to be your own address. On its own, the allowlist would let anyone who guessed an allowed address put documents into your books.

SPF closes that gap. The domain behind an address publishes which mail servers may send for it, and the receiving server checks the message came from one of them. Cloudflare Email Routing does this check when the message arrives and records the result in an Authentication-Results header at the top of the message.

The app reads only that header, and only the copy Cloudflare added. A sender can write their own Authentication-Results header further down the message, claiming anything, so headers below Cloudflare’s are ignored. ARC headers are ignored too: without verifying their seal, a forged one looks the same as a real one.

From Cloudflare’s result the app reaches one of three verdicts:

  • Pass. SPF passed for the envelope sender, or DMARC passed for the domain of an approved From address. The message is read.
  • Fail. SPF failed or soft-failed, DMARC failed, or the address Cloudflare checked is not the one the Worker was handed. The message is dropped and a short reason code is logged. Nothing is stored.
  • Unknown. There is no clear SPF result. A common case is mail signed with DKIM but without SPF, where Cloudflare’s summary does not say which domain signed it, so it cannot prove the envelope address.

Cloudflare’s own rules apply before the Worker sees anything: Email Routing rejects mail that fails the sender’s DMARC policy, and mail that passes neither SPF nor DKIM. Those messages never reach the app.

Gate 3: unproven mail is kept, not read

A message with an unknown verdict might be a genuine receipt from a sender with unusual mail settings. Dropping it would lose the receipt. Reading it would mean spending AI reading on, and putting into your books, a document nobody can vouch for.

So the app keeps it and does nothing else. The whole message is stored and waits in Receipts To do, unread, asking Is this email genuine? You can open the source email, decide it is genuine, and have it read. Nothing is sent to Workers AI until you do.

This costs you a click now and then. In return, a spoofed message cannot trigger AI spend or slip a document into your month without you looking at it first.

What arrives after the gates

A message that passes is stored whole. Up to 10 PDF or image attachments are read as separate receipts, with the email’s text passed along as context. A message with no attachments is read from its body. A message over 20 MiB is dropped and logged. If some attachments were skipped, or the message could not be parsed, the stored email is flagged so you can check it yourself. See Limits.

Mail to INVOICES_ADDRESS, if you set one, goes through the same gates and is filed as a sales invoice rather than a receipt. See Keep sales invoices.

Type to search…

↑↓ navigate↵ selectEsc close