Cloudflare Email Routing and DMARC: Why Forwarded Mail Fails
Cloudflare Email Routing breaks SPF by design: when it forwards your mail, the sending IP changes to Cloudflare's, which is not in your SPF record. This is not a misconfiguration. It is how email forwarding works. The fix is DKIM alignment plus ARC, both of which Cloudflare already handles for you.
If you set up Cloudflare Email Routing and then added DMARC monitoring, you will see SPF failures in your aggregate reports. Some forwarded mail may land in spam. Here is what is happening and what to do about it.
Cloudflare Email Routing forwards inbound mail only
Let's start with a critical distinction: Cloudflare Email Routing is an inbound mail forwarder, not an outbound mail service. If you're using Cloudflare to send mail from your domain (like transactional emails from your app), you need a separate outbound service with SPF and DKIM configured. Cloudflare Email Routing does not send mail.
What Cloudflare Email Routing does: intercepts inbound SMTP to your domain, holds the message, and relays it to a destination mailbox you configure in the Cloudflare dashboard. When it forwards that mail, the original message headers are preserved, but the sending IP address changes to one of Cloudflare's forwarder IPs. This is where authentication breaks.
Why SPF fails on forwarded mail
SPF (Sender Policy Framework) uses the message's Return-Path to determine which IPs are allowed to send from your domain. When an external service sends mail to your domain, their IP passes their own SPF check. But when Cloudflare forwards that mail to you, the message now appears to come from Cloudflare's IP, which is almost certainly not in your SPF record.
The receiving mail server (your inbox provider) sees:
- Return-Path:
user@yourdomain.com - Sending IP:
cloudflare-forwarder-ip - Your SPF record:
v=spf1 include:_spf.google.com ~all(or whatever you have)
Cloudflare's IP is not listed. SPF fails.
DKIM usually survives forwarding
DKIM is more forgiving. When the original sender signed the message with their private key, that signature is embedded in the message body. Cloudflare's forwarder doesn't modify the message body or most headers, so the original DKIM signature stays intact and valid.
The receiving mail server checks the DKIM-Signature header against the original sender's public key (in their domain's DNS). The signature is still good. DKIM passes.
ARC: why your forwarded mail still reaches the inbox
This is the silver lining. When Cloudflare forwards your mail, it adds ARC (Authenticated Received Chain) headers. ARC is a wrapper that says: "This message was signed by one party (the original sender), then forwarded by another party (Cloudflare). Here's proof that the forwarder is trusted."
Gmail and many other receiving mail servers understand ARC. Even though SPF failed, Gmail sees the ARC sealing from Cloudflare and trusts the forwarded message enough to deliver it. This is why mail forwarded through Cloudflare often still reaches the inbox despite failing SPF.
But this isn't guaranteed. Other mail servers may not honor ARC. And if both SPF and DKIM fail, no amount of ARC will save you.
DMARC policy on a forwarding domain
DMARC combines SPF and DKIM results with a policy: if at least one of them passes and aligns with the domain, DMARC passes. If both fail, DMARC fails.
For a domain that only forwards mail (you don't send from it), you likely have p=none in your DMARC record. This means mail that fails DMARC still gets delivered. You're in monitoring mode. This is fine for a forwarding domain.
But if you later start sending from the domain too (e.g., transactional emails from an app using a third-party service), you'll want p=quarantine or p=reject. At that point, forwarded mail that fails DMARC might be blocked by recipient mail servers. You'll need to either stop sending from the domain, or stop forwarding it.
For most indie developers: use p=none on forwarding domains and keep monitoring. Don't enforce until you're sure all your mail sources (forwarders + senders) authenticate correctly.
How to set up Cloudflare Email Routing with DMARC
Enable Email Routing in the Cloudflare dashboard
Go to your domain's dashboard, find Email Routing, and enable it. Point it at a destination mailbox. Cloudflare automatically adds the required MX records to your DNS. You don't have to touch DNS for the Email Routing part.
Add a DMARC record
You add the DMARC record yourself, in your DNS. Create a TXT record at _dmarc.yourdomain.com:
v=DMARC1; p=none; rua=mailto:your-email@example.com
Start with p=none. Send aggregate reports to an email address you monitor, or point rua= at a DMARC aggregation service.
Point reports at DMARCdrift
Once your DMARC record is live, aggregate reports will start arriving within 24 to 48 hours. Instead of parsing XML in your email, point rua= at dmarcdrift:
v=DMARC1; p=none; rua=mailto:d-your-domain-id@in.dmarcdrift.com
(Replace with your actual domain ID inbound address from your DMARCdrift account.)
Verify your setup
Use the Email Authentication Checker to confirm your DMARC, SPF, and DKIM records are live and readable.
If you also send from the domain
If you send transactional email from your domain using a service like Resend, AWS SES, or SendGrid, you need SPF and DKIM configured for that service, separate from your forwarding setup.
Each sender needs its own SPF include and DKIM selector. Your SPF record becomes something like:
v=spf1 include:_spf.google.com include:sendgrid.net include:ses.amazonaws.com ~all
And you add DKIM selectors for each sender. Cloudflare Email Routing doesn't interfere with this; it just relays inbound mail. But now you have two authentication contexts: inbound forwarding (uses ARC) and outbound sending (uses SPF + DKIM). Both must work for your domain to have clean authentication.
Common pitfalls
You can't use Cloudflare Email Routing to send mail. It only forwards inbound. If you need to send, use a dedicated ESP.
Forwarded mail fails SPF by design. The sending IP changes. This is not a misconfiguration. ARC is the fix, and major mail providers honor it.
Don't use p=reject on a forwarding domain unless you know what you're doing. Rejected mail is silently dropped. If SPF fails on a forwarded message, and you're using p=reject, that mail disappears. Start with p=none.
RUA reports go to the address you specify (or your DMARCdrift inbound address) within 24 to 48 hours. If you're not seeing reports, wait another day or check that your DNS record is correct with the DMARC Record Checker.
Next steps
Set p=none on your forwarding domain and monitor for a week. You'll see SPF failures on forwarded mail in your aggregate reports. This is expected. DKIM should pass. If both are failing, double-check your DNS records and walk through why your DMARC is failing to pin down the source.
Once your reports are flowing into DMARCdrift, you'll have a readable digest showing sender alignment, spoofing signals, and any actual problems. Most forwarding domains never see actionable alerts. The product is there in case something changes.
Once your DMARC record is live, aggregate reports will start arriving within 24 to 48 hours. DMARCdrift turns the XML into a readable digest, free for one domain.
