Worker -> MailChannels -> email routing = SPF permerror

I have two domains on Cloudflare. Both are using the email routing service. One of them also has a worker which sends emails using the MailChannels API. The “from” address is from its same domain.

When the worker on domain 1 sends an email to an address on domain 2, it never arrives. The email routing logs for domain 2 say that the email was rejected by Gmail (the destination mailbox), and the SPF status says “permerror”.

However, if I change the worker to send the email directly to the Gmail address, it arrives correctly, and Gmail says that SPF passed. The SPF record was configured according to instructions by MailChannels, and several online SPF record checkers say that everything looks fine.

What could be causing this?

permerror” could be because of an syntactically incorrect SPF record.

permerror” could also be because of having more than the 10 mechanisms in your SPF record, that requires further DNS lookups.

ip6” and “ip4” for example come with no limits, because they do not require further DNS lookups.

a”, “exist”, “include”, “mx”, “ptr” requires further DNS lookups, and as such, you can maximum have 10 of them, in the whole chain of the SPF record.

In the whole chain: If your own SPF record requires 4 DNS lookups, and you’re having include:_spf.example.com, and that include:_spf.example.com would require 7 DNS lookups to be processed, then you would have a total of 11, literally breaking your SPF record.

The final result for your own 4, plus your third party’s 7 (= 11), would in this example result in “permerror”.

The above would be two possible explanations to the issue.

Can you share domain 1 and domain 2?

1 Like

Thank you for your reply.

I did some more testing:

When the worker sends an email to a Gmail address or to another regular address at another email host, it works fine and SPF passes.

When the worker sends an email to an address on its own domain or on another domain which is also using Cloudflare’s email routing, it doesn’t arrive and Cloudflare reports a permerror.

A problem with the SPF record would fail everywhere, not just on Cloudflare. It seems to be the particular combination of “worker to MailChannels to email routing” that somehow creates a problem.

The domain with the worker sending the emails is cloverkey.com.ar. The SPF record appears fine, and it has 10 total DNS lookups. Just in case Cloudflare rejected it for being at the limit, I temporarily removed one of the include in the SPF record to reduce the number of DNS lookups. It made no difference.

Thanks again!

This one sounds like we should shift our focus to the other Email Routing domain, in order to investigate the issues when routing (further) through that one.

A lot of email forwarders these days are rewriting the SMTP MAIL FROM / Envelope From, so, if your chain of re-routing is:

Sender ↔ Email Routing Domain (example.com) ↔ Gmail

Then Gmail will end up no seeing example.com as being the SMTP MAIL FROM / Envelope From / RFC5321.MFROM.

And if we’re passing it over multiple chains, e.g.:

Sender ↔ Email Routing Domain (example.com) ↔ Email Routing Domain (example.net) ↔ Email Routing Domain (example.org)

.ORG would see the SPF check being done at the .NET domain, and similarly, before that, the .NET domain would see the SPF cheek being done at the .COM domain.

Is this domain operating through a paid Google Workspace set up?

If not, then you should sanitize your SPF by removing include:_spf.google.com.

In it’s current state, I would agree that it is perfectly fine, according to the limits.

If it only fails when passing through other Email Routing domains or similar, as it sounds like by the above explanation, then I would go that far as to say that the SPFpermerror” problem should be found on one of these other domains.

Which one would likely be a mystery, depending on how many (other domain(s)) you’re sending through.

Do you see the SPFpermerror” in the “Activity Log” on the first domain on Cloudflare, the second, … or how and where exactly?

1 Like

OK, I’ve tried several combinations and here’s the takeaway:

Worker → Any email address without Email Routing = The message arrives, SPF passes.

Worker → Email Routing → Any non-Gmail address = The message arrives, SPF passes, Cloudflare says SPF permerror in the Email Routing Activity Log.

Worker → Email Routing → Gmail = The message never arrives because Gmail rejects it, Cloudflare says SPF permerror in the Email Routing Activity Log.

I tried mailboxes from Gmail, Outlook, Yahoo, and a small email provider. I tried several domains for Email Routing. The results are always those.

So there are two seemingly-separate problems:

  1. Gmail outright rejects messages sent by the worker via Cloudflare’s Email Routing, even though SPF and DMARC pass, and DKIM is not used. Won’t even send them to the spam folder. It will accept the same message when sent directly to the Gmail address, just not via Cloudflare.

  2. Cloudflare marks all messages sent by the worker as SPF permerror even when the message is forwarded, received, and SPF passes at the destination.

Anyway, I’ll have the worker send the messages to a destination which doesn’t involve Cloudflare+Gmail, for now.

Thank you for your time!

Is this Worker set up like e.g. the example shown here?

… Can you possibly show how exactly you’re setting all kind of “from”-related fields?

This one is quite much to be expected.

Google and Yahoo released new requirements for email authentication as per February 2024 for deliveries to their mailboxes.

You have NEVER been able to pass SPF after forwarding, and especially not the alignment, as e.g. required in order to be able to pass e.g. DMARC.

So technically, running SPF-only means that there will be no email authentication, with proper alignment to your own domain, after the forwarding has happened (e.g. when it reaches Gmail).

Last week, I did some testings, and the results were clear:

  1. DKIM with proper alignment
    → Delivered via Email Routing to the free Gmail in 19 seconds.

  2. no DKIM at all
    → Delivered via Email Routing to the free Gmail in 399414 seconds (~ 4.63 days, ~ 111 hours)

The message wasn’t lost, but simply rate limited for a long time.

It’s the way that all of the (bigger) free mail providers have been moving towards, for several years now.

1 Like

This is sadly not a direct solution to your issue, but I would recommend avoiding MailChannels and using some other service like Amazon SES, Sendgrid, Postmark, etc.

There are a lot of security implications and their responses to the situation have been very undesirable. Further reading:

To this day, that have still not truly acknowledged the problems, and brushed it aside or “patched” it with paywalls.

2 Likes

I don’t know about the security implications that you mentioned, but I switched to Sendgrid and it solved all the problems I was having.

I was using MailChannels because it seemed like they had partnered with Cloudflare and I didn’t even need to create an account with them, but this is better.

Thanks!

2 Likes