DMARC, SPF and DKIM for Cloudflare Email Routing

Updated 2026-11-06

Cloudflare Email Routing receives mail for your domain and forwards it to addresses you have verified, or hands it to a Worker. As of November 2026 Cloudflare documents it as part of Cloudflare Email Service, next to a separate sending feature called Email Sending. The domain must use Cloudflare DNS. This guide follows Cloudflare's developer documentation. For the background on each standard, see SPF explained, DKIM explained and DMARC explained.

What Cloudflare Email Routing sends from

Email Routing is a forwarder. It does not send new mail as your domain. The docs say it "does not support sending or replying from your Cloudflare domain". A reply to a forwarded message leaves from your destination mailbox, for example a Gmail address.

When it forwards a message, three things happen, as documented:

  • SRS. Email Routing rewrites the envelope sender (MAIL FROM) "to a Cloudflare-controlled forwarding domain", so SPF can pass at the destination. The From: header "is not modified".
  • ARC. It adds an ARC seal "preserving the original authentication results".
  • DKIM. It adds two signatures: one for email.cloudflare.net, "which covers sender rewriting", and one for "the recipient domain configured by the customer". We read this as the signature made with your Email Routing key; the docs do not say so.

Before forwarding, Cloudflare checks the incoming message. Mail must pass SPF or carry a valid DKIM signature, and mail that fails the sender's DMARC policy is rejected.

Two other paths can send as example.com:

  • A Worker reply. As of November 2026, message.reply() throws unless, among other conditions, "The incoming email must have a valid DMARC result" and "The outgoing sender domain must match the domain that received the email".
  • Email Sending (as of November 2026 in beta, transactional mail; sending to arbitrary recipients requires Workers Paid). Here the Return-Path is "Set to Cloudflare bounce processor", and the bounce records live on cf-bounce.example.com. The docs do not print the full envelope address.

SPF

When you onboard a domain, Email Routing adds MX records and an SPF record on the root domain. As of November 2026 the docs show these records:

example.com MX route1.mx.cloudflare.net
example.com MX route2.mx.cloudflare.net
example.com MX route3.mx.cloudflare.net
example.com TXT "v=spf1 include:_spf.mx.cloudflare.net ~all"

Cloudflare sets the MX priorities itself. Email Routing needs the root MX records to itself; as of November 2026, onboarding fails with error 2008 if MX records from another provider exist.

Cloudflare only adds the SPF record when none exists. If you already have one, merge the include into it. The docs say to "Ensure only one SPF record exists". A typical setup, where _spf.example.net stands for another service that sends as your domain:

example.com TXT "v=spf1 include:_spf.mx.cloudflare.net include:_spf.example.net ~all"

That record uses 2 DNS lookups itself. The docs show the record behind the include as "v=spf1 ip4:104.30.0.0/20 ~all", which adds no further lookups as printed. When we counted include:_spf.mx.cloudflare.net with real DNS on 7 November 2026, the record held only IP ranges, so it cost 1 lookup in total. Cloudflare can change it, and the other service's include adds its own lookups, so count the whole tree with the SPF lookup counter. RFC 7208 sets the limit at 10 lookups, and Cloudflare repeats that "SPF records are limited to 10 DNS lookups total" (too many SPF lookups).

If you also use Email Sending, it publishes the same value on cf-bounce.example.com, not on the root. The ~all at the end is softfail; DMARC decides what happens to failing mail.

DKIM

The docs describe no separate DKIM switch. Onboarding adds the key. As of November 2026 the documented steps are:

  • In the Cloudflare dashboard, go to Compute > Email Service > Email Routing.
  • Select Onboard Domain and choose the domain.
  • Review the records (MX, SPF, DKIM) and select Done.
  • Check them under Email Routing > Settings, in the DNS records section.

The DKIM record is a TXT record:

cf2024-1._domainkey.example.com TXT "v=DKIM1; h=sha256; k=rsa; p=<public key from the dashboard>"

The selector is cf2024-1. Email Sending uses its own selector and key at cf-bounce._domainkey.example.com. The docs say "Use different selectors for different services" and name google._domainkey for Google Workspace, so the records do not normally collide with other providers.

Cloudflare "automatically generates and manages DKIM keys". The docs show k=rsa but do not state a key length, and they describe no way to choose one. To rotate a key, the docs say, as of November 2026, to contact Cloudflare support and then update the DNS record.

Onboarding locks the records. Locked records "cannot be edited or deleted from DNS > Records until they are unlocked" under Email Routing > Settings.

DMARC alignment

DMARC passes when SPF or DKIM passes and the authenticated domain aligns with the From domain.

  • SPF alignment compares the RFC5321.MailFrom (Return-Path) domain with the From domain.
  • DKIM alignment compares the d= domain with the From domain.

Relaxed alignment, the default, only needs the same organisational domain. Strict needs the exact same name.

Forwarded mail. The From stays the original sender's. After SRS the envelope is a Cloudflare domain, so SPF can pass but does not align with the original From. DMARC then rests on the original sender's DKIM signature surviving the forward, or on the receiver trusting Cloudflare's ARC seal. Cloudflare warns: "restrictive DMARC policies might make forwarded emails fail to be delivered." This is the sender's policy, not yours.

Mail from your domain. For Email Sending the docs say "Email Service ensures proper SPF and DKIM alignment". The key is published at cf-bounce._domainkey.example.com, which implies d=example.com, so a signature with it aligns in both modes. The docs do not name the Return-Path domain. If it is under cf-bounce.example.com, which the bounce MX and SPF records there suggest, SPF aligns in relaxed mode only.

Step by step to p=reject

  1. Publish SPF. After onboarding, keep one TXT record on example.com with include:_spf.mx.cloudflare.net, merged with the includes of every other service that sends as your domain. Stay at 10 DNS lookups or fewer in total.
  2. Check DKIM. Confirm that cf2024-1._domainkey.example.com holds the key from Email Routing > Settings, and that every other sender signs with a key under your domain.
  3. Start DMARC at p=none with reports. Publish a TXT record at _dmarc.example.com with v=DMARC1; p=none; rua=mailto:[email protected]. This policy does not protect the domain yet; it turns on aggregate reports. Do this before you onboard Email Sending, because Cloudflare keeps an existing record unchanged.
  4. Read the reports and fix other senders. For two to four weeks, look at which servers send as your domain. Give every legitimate service SPF and DKIM for your domain, so that its mail aligns.
  5. Move to quarantine. Change the policy to p=quarantine once the reports show only aligned mail from your own services. Failing mail usually lands in spam, so a sender you missed is still recoverable.
  6. Reject. Change the policy to p=reject when the reports stay clean. Receivers then refuse mail that fails DMARC.

The record for step 3:

_dmarc.example.com TXT "v=DMARC1; p=none; rua=mailto:[email protected]"

The final record:

_dmarc.example.com TXT "v=DMARC1; p=reject; rua=mailto:[email protected]"

Cloudflare's own deployment strategy is the same: "Start with p=none", then quarantine, then reject "after confirming legitimate mail authenticates".

Common mistakes

  • Two SPF records. If you had SPF before onboarding, adding a second record breaks SPF. The docs say multiple SPF records are "not allowed" (multiple SPF records).
  • Missing the include after onboarding. Cloudflare only creates SPF when none exists. With an existing record you must add include:_spf.mx.cloudflare.net yourself.
  • An automatic p=reject without reports. As of November 2026, when Email Sending is enabled and no DMARC record exists, "Cloudflare adds a p=reject DMARC record". The documented value is v=DMARC1; p=reject;, with no rua. You skip the monitoring phase and get no reports (DMARC without rua).
  • Expecting your DMARC to protect forwarded mail. Forwarded mail usually carries someone else's From, and that sender's policy applies. Your policy covers mail that claims to be from example.com.
  • Expecting to send from routing addresses. Email Routing forwards only. Mail you send from your destination mailbox is not from example.com.
  • Keeping old MX records. Email Routing needs Cloudflare's MX records on the root. You cannot keep another provider's inbound servers on the same name.
  • Relying on a test flag. Some receivers support t=y (RFC 9989, DMARCbis, which obsoletes RFC 7489) or pct (RFC 7489). Neither is a safety net. RFC 7489 says unknown tags must be ignored, so a receiver that implements only RFC 7489 can treat p=reject; t=y as a full reject. Move from p=none to p=quarantine to p=reject and let the reports decide.

How to check it

Run the email security check on your domain to read SPF, DKIM and DMARC in one pass. Use the SPF lookup counter to count every lookup behind include:_spf.mx.cloudflare.net and your other includes. In the DKIM selector finder, look for the selectors documented as of November 2026: cf2024-1 for Email Routing and, if you use Email Sending, cf-bounce. Build or check your policy with the DMARC record generator.

Sources

Frequently asked questions

What SPF record does Cloudflare Email Routing add?

As of November 2026 the docs give v=spf1 include:_spf.mx.cloudflare.net ~all as a TXT record on the root domain. Cloudflare adds it only if no SPF record exists. If you already have one, add include:_spf.mx.cloudflare.net to it by hand.

Which DKIM selector does Email Routing use?

As of November 2026 Email Routing uses cf2024-1, so the TXT record sits at cf2024-1._domainkey.example.com. Email Sending, the separate sending feature, uses cf-bounce._domainkey.example.com. Cloudflare generates the keys.

Can I send mail as my domain through Email Routing?

Not through routing rules. The docs list it as a known limitation: replies to forwarded mail go out from your destination address, not from [email protected]. Sending as your domain needs Email Sending (beta) or another provider, and a Worker can reply to an incoming message under strict conditions.

Does my DMARC policy affect the mail Cloudflare forwards to me?

Mostly not. A forwarded message keeps its original From, so the destination applies the original sender's DMARC policy. Your policy matters when a message claims to be from example.com: Cloudflare rejects incoming mail that fails "according to that domain's DMARC policy", and receivers judge mail sent as your domain by it.