Skip to content

Troubleshooting

Last updated View as MarkdownAgent setup

Email authentication is critical for successful email delivery. This guide helps you troubleshoot common authentication, delivery, and inbox placement issues with Email Service.

SPF (Sender Policy Framework) issues

Multiple SPF records

Having multiple SPF records on your domain is not allowed and will prevent Email Service from working properly. If your domain has multiple SPF records:

  1. Log in to the Cloudflare dashboard, select your account and domain, then go to DNS > Records.

    Go to Records ↗
  2. Look for multiple TXT records starting with v=spf1.

  3. Delete the incorrect SPF record.

  4. Ensure you have the correct SPF records:

    • For Email Routing (root domain): v=spf1 include:_spf.mx.cloudflare.net ~all
    • For Email Sending (cf-bounce subdomain): v=spf1 include:_spf.mx.cloudflare.net ~all

If you are unsure which SPF record is the correct one to keep, you can remove all of them and let Cloudflare regenerate the required records:

  1. In DNS > Records, delete every TXT record starting with v=spf1 on the affected name.
  2. Go to Compute > Email Service and re-onboard or re-enable the affected service. Cloudflare adds the correct SPF record back automatically.

Missing SPF record

If emails are being rejected due to SPF failures:

  1. Log in to the Cloudflare dashboard, select your account and domain, then go to DNS > Records.

    Go to Records ↗
  2. Add TXT records for the appropriate service:

    • For Email Routing: Name: @ (root domain), Content: v=spf1 include:_spf.mx.cloudflare.net ~all
    • For Email Sending: Name: cf-bounce, Content: v=spf1 include:_spf.mx.cloudflare.net ~all
  3. If you already have an SPF record on the root domain, modify it to include include:_spf.mx.cloudflare.net

SPF record syntax errors

Common SPF record syntax issues:

  • Missing version: SPF records must start with v=spf1
  • Multiple includes: Combine multiple services using separate include: statements
  • Too many DNS lookups: SPF records are limited to 10 DNS lookups total
  • Incorrect all mechanism: Use ~all (SoftFail) or -all (Fail), not +all

Correct format:

v=spf1 include:_spf.mx.cloudflare.net include:other-service.com ~all

Checking SPF records

Verify your SPF record is configured correctly:

dig TXT example.com +short | grep spf

Expected result should include:

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

DKIM (DomainKeys Identified Mail) issues

Missing DKIM records

Email Service automatically generates DKIM keys for your domain, but the DNS records must be properly configured. Email Sending and Email Routing use separate DKIM selectors:

  1. In the Cloudflare dashboard ↗︎, go to Compute > Email Service.
  2. Select your domain.
  3. Check the Settings page for the appropriate service:
    • Email Sending: Go to Email Sending > Settings to find the sending DKIM record (cf-bounce._domainkey).
    • Email Routing: Go to Email Routing > Settings to find the routing DKIM record (cf2024-1._domainkey).
  4. Copy the DKIM record details.
  5. Go to DNS > Records and add the DKIM TXT record with the correct selector name and public key.

DKIM key rotation

If you need to rotate DKIM keys:

  1. Contact Cloudflare support to request key rotation.
  2. Update your DNS records with the new DKIM key when provided.
  3. Monitor email delivery during the transition period.

Checking DKIM records

Verify your DKIM records are configured correctly:

# Check Email Sending DKIM
dig TXT cf-bounce._domainkey.example.com +short

# Check Email Routing DKIM
dig TXT cf2024-1._domainkey.example.com +short

Expected result for either:

"v=DKIM1; h=sha256; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA..."

DKIM signature validation failures

If DKIM validation is failing:

  1. Verify the DKIM record exists in DNS
  2. Check that the record name matches the correct selector:
    • Email Sending: cf-bounce._domainkey.example.com
    • Email Routing: cf2024-1._domainkey.example.com
  3. Ensure there are no extra spaces or characters in the DNS record
  4. Wait for DNS propagation (up to 48 hours)
  5. Use online DKIM validators to test your configuration

DMARC (Domain-based Message Authentication, Reporting & Conformance) issues

Missing DMARC policy

While not required, DMARC significantly improves email deliverability. When Email Sending is enabled on a domain, Cloudflare adds a p=reject DMARC record to the sending domain if none exists. If you already have a DMARC record, Cloudflare keeps it unchanged.

To add a DMARC record manually:

  1. Go to DNS > Records in the Cloudflare dashboard.

    Go to Records ↗
  2. Add a TXT record:

    • Name: _dmarc
    • Content: v=DMARC1; p=quarantine; rua=mailto:dmarc@example.com

DMARC policy too strict

If a strict DMARC policy is causing delivery issues:

  1. Start with a lenient policy: p=none (monitor only)
  2. Monitor DMARC reports for several weeks
  3. Gradually increase strictness: p=quarantine then p=reject
  4. Ensure both SPF and DKIM are properly aligned

DMARC alignment issues

DMARC requires either SPF or DKIM alignment:

SPF alignment: The domain in the Mail From header must align with the domain in the From header DKIM alignment: The DKIM signature domain must align with the domain in the From header

Email Service ensures proper alignment automatically.

Checking DMARC records

Verify your DMARC record:

dig TXT _dmarc.example.com +short

Example result:

"v=DMARC1; p=quarantine; rua=mailto:dmarc@example.com; ruf=mailto:dmarc@example.com; sp=quarantine"

Local development issues

"Cannot serialize value: [object ArrayBuffer]"

This error occurs when passing ArrayBuffer content in attachment fields during local development with wrangler dev. The local email binding simulator cannot serialize ArrayBuffer values.

Solution: Deploy your Worker with npx wrangler deploy and test binary attachments (images, PDFs) against the deployed version. String content for text-based attachments works normally in local development. Refer to local development for email sending for more details.

Common delivery issues

Transactional email going to spam or junk

Use this checklist to diagnose inbox placement problems before opening a support case. Work through each step in order.

Delivery status versus inbox placement

A Delivered status in the Activity log means the recipient's mail server accepted the message with a successful SMTP response. The receiving provider determines what happens after acceptance — inbox, spam, or junk. Cloudflare does not receive that placement signal.

This means:

  • A message can show as Delivered in your logs and still land in the recipient's spam or junk folder.
  • A spam or junk classification after acceptance is a receiver-side decision. It can occur even when SPF, DKIM, and DMARC all pass.
  • The receiving provider's reputation databases, spam filters, and user feedback signals all influence placement independently of authentication.

Step 1: Verify authentication records

Go to Compute > Email Service > Email Sending > Settings and confirm that all DNS records show a healthy status. Every record must be present and valid. For more information about each record type, see SPF issues, DKIM issues, and DMARC issues.

If a DNS record is missing, restore it from the Settings page.

Step 2: Check the Activity log

  1. Go to Compute > Email Service > Email Sending > Activity log.
  2. Locate the affected message and confirm its status is Delivered — not Retrying, Delivery failed, Suppressed, Rejected as spam, or Error.
  3. Note the Message-ID — you will need this value if you open a support case.
  4. Check whether the recipient is on your suppression list with reason: complaint. Spam complaints from some providers are recorded as complaint suppressions. If you subscribe to event subscriptions, also check for message.complained events.

A Delivered status means the provider's server accepted the message. To confirm authentication, check the received headers in Step 3.

Step 3: Read the received headers

Ask a recipient to share the full message source, not just the body. Most email clients expose this under Show original, View source, or Message source.

Look for these headers:

Header What it tells you
X-Spam-Flag: yes / X-Suspected-Spam: true The provider flagged the message as spam after delivery
X-Apple-MoveToFolder: Junk / X-Apple-Action: .../Junk iCloud moved the message to Junk
X-MS-Exchange-Organization-SCL Outlook spam confidence level — 5 or higher causes junk placement
X-Microsoft-Antispam: BCL Outlook bulk confidence level
Authentication-Results The provider's own SPF, DKIM, and DMARC evaluation

If all authentication results show pass and the spam flag is still set, the classification is based on domain reputation or message content — not a Cloudflare configuration problem.

Step 4: Use provider postmaster tools

Register your sending domain with provider postmaster tools to see your reputation from each provider's perspective:

  • Gmail: Add and verify your sending domain in Postmaster Tools ↗︎ to see domain reputation and spam rate. Data appears only when your daily volume to Gmail is high enough.
  • iCloud: Apple does not offer sender dashboards, a feedback loop, or an allowlist.

Step 5: Build sending reputation

If your domain is new or has a low sending volume, inbox placement problems are common while you build a sending history. Refer to Build reputation for a new domain for guidance on domain warm-up, content best practices, and engagement signals.

High bounce rates

To reduce bounce rates:

  1. Validate email addresses: Use real-time validation
  2. Maintain clean lists: Remove hard bounces immediately
  3. Monitor feedback loops: Subscribe to ISP feedback loops
  4. Gradual warm-up: For new domains, start with small volumes

Suppressed recipient

Each sending domain has a Drop suppressed recipients setting. The setting is off by default.

When the setting is off, the REST API returns 400, the Workers binding throws E_RECIPIENT_SUPPRESSED, and SMTP rejects the message. Any suppressed recipient causes the send to fail.

When the setting is on, Email Service removes suppressed recipients and processes the remaining recipients. If none remain, SMTP may return 250 2.0.0 Ok without a Message-ID and deliver nothing.

To investigate a suppressed recipient:

  1. Query the exact recipient:

    List account Email Sending suppressionsbash
    curl "https://api.cloudflare.com/client/v4/accounts/$ACCOUNT_ID/email/sending/suppressions?email=recipient%40example.com" \
    	--request GET \
    	--header "Authorization: Bearer $CLOUDFLARE_API_TOKEN"
  2. Use the reason, expires_at, and read_only fields to choose an action. For the complete decision table, refer to Suppression rules.

  3. If result is empty, confirm that you queried the correct account. Then check the sending logs.

  4. If the logs still report a suppression, contact Cloudflare Support.

Recipient blocked after expiration or deletion

Expired entries stop appearing in the public list after their expires_at timestamp passes. Delivery enforcement can take additional time to stop.

Updates and deletions also propagate asynchronously. The management list and delivery enforcement can briefly differ.

To investigate delayed enforcement:

  1. Confirm that the entry no longer appears in the account list.
  2. Retry later because suppression updates propagate asynchronously.
  3. If the recipient remains blocked, contact Cloudflare Support.

Bounces before suppression enforcement

Bounce suppressions are created through background delivery processing. Messages already in progress can bounce before a new suppression takes effect.

Complaint suppression does not appear

Complaint suppressions appear after Cloudflare receives and validates the provider report. The provider determines when that report arrives.

Missing suppression after a bounce

Not every failure results in a suppression. Email Service creates automatic entries only for eligible recipient-side failures. Sender authentication, sender reputation, and unrelated infrastructure failures do not suppress the recipient. Check Email sending logs for the specific failure.

Conflicts with external mail providers

Onboarding fails with "Non-Cloudflare MX records exist"

When you enable Email Routing on a domain that already has MX records from another provider (such as Google Workspace, Microsoft 365, or Zoho Mail), onboarding fails with error 2008, "Non-Cloudflare MX records exist". Email Routing requires exclusive control of the root domain MX records.

To switch your domain to Email Routing, refer to Move to Email Routing from another provider.

Testing tools

Use these tools to validate your email authentication setup:

Getting help

Before opening a support case for email going to spam or junk, complete the transactional email troubleshooting checklist. Domain warm-up causes many inbox placement problems, and most resolve without engineering involvement.

Cloudflare cannot force inbox placement. Inbox providers classify messages after accepting them, and that decision is entirely within the provider's own systems. Apple iCloud does not offer a feedback loop or allowlist path for any sender.

If you have completed the checklist and still need support, include these details in your support case:

Detail Where to find it
Message-ID Activity log — expand the message row
Session-ID Activity log — expand the message row
Timestamp Activity log — Received column (note your dashboard timezone setting and include it with the time)
Recipient address Activity log or your application logs
Sending domain Email Sending > Settings
Zone ID Cloudflare dashboard Overview page, sidebar
Full received headers Full message source from the recipient's mail client, including Authentication-Results and any X-Spam-* headers
Provider and folder Where the message landed, for example iCloud Mail — Junk
Messages sent in the last 7 days Email Sending dashboard or Analytics

For other authentication and delivery issues:

  1. Check Email Service Analytics for delivery metrics.
  2. Review bounce messages for specific SMTP error codes.
  3. Contact Cloudflare Support ↗︎.

Was this helpful?