ElmsPark Guides
Email & deliverability guide

Why your website’s email lands in spam

Your contact form fires, the log says “sent”, and the message lands in the recipient’s spam folder. Three DNS records, SPF, DKIM and DMARC, are almost always the missing piece. This guide explains what each one does and how to get them right.

📬 Access to your DNS settings 🔑 Details from your mail provider 📋 No coding required 🛡 Required since February 2024
What you’ll need: access to your domain’s DNS settings (usually via your domain registrar or your DNS host), and the sending details from your mail provider: the SPF include value and the DKIM key or CNAMEs they ask you to add. Your provider’s documentation will have both.
Why this happens. When an email arrives, the receiving mailbox provider checks whether the sending server was actually authorised to send on behalf of your domain. If it cannot verify that, the message looks potentially forged, so it is junked or dropped quietly. Your sending software has no way to know this happened: the log still says “sent” because the message left your server. The authentication check happens at the other end, silently.
▶ Prefer to learn it interactively? Tap through the interactive lesson, one idea at a time, about two minutes, with quick questions as you go.

Use this guide with any AI assistant

Download it as a prompt file, paste it into Claude, ChatGPT, Gemini or any LLM, and it will walk you through diagnosing and fixing your email deliverability one step at a time.

↓  Download as LLM prompt

1The one-minute diagnosis

Before adding any records, establish which problem you actually have. There are two distinct failure modes.

Transport failure: the message never left your server, or was rejected immediately. Check your mail plugin or application logs. An error like “connection refused” or “authentication failed” means your sending credentials or SMTP settings are wrong. No DNS record will fix that.

Authentication failure: the message was sent successfully but landed in spam. This is the SPF, DKIM and DMARC problem this guide addresses. The fast way to confirm it is to send a test message to yourself at Gmail or another major provider, open it, and look at the headers.

In Gmail, open the message, click the three-dot menu in the top right, and choose “Show original”. Near the top you will see lines like this:

SPF:    PASS  with IP 192.0.2.10
DKIM:   FAIL
DMARC:  FAIL

Any FAIL tells you exactly which record needs attention. If all three show PASS and mail is still going to spam, the issue is content or sender reputation, not authentication.

Log says “sent”. It still landed in spam. That is normal. The sending log records whether the message left your server. The spam verdict is made by the receiving server, after delivery, and it does not report back to you. A successful send log is not delivery proof.

2SPF: who is allowed to send

SPF (Sender Policy Framework) is a TXT record on your domain that lists the servers permitted to send email on its behalf. When a message arrives, the receiving server looks up this record and checks whether the sending IP is on the list.

A typical SPF record for a site that sends via Mailgun looks like this:

# DNS TXT record on yourdomain.com
v=spf1 include:mailgun.org -all

Breaking that down: v=spf1 declares it as an SPF record; include:mailgun.org says “also allow whatever servers Mailgun publishes”; -all says “reject anything else” (a hard fail).

If you use ~all instead, that is a soft fail: recipients are advised to treat other senders with suspicion rather than reject them outright. Hard fail (-all) is the more decisive choice for a domain you control.

One SPF record only. A domain must have exactly one SPF TXT record. If you add a second one, both are ignored and SPF fails for every message. If you send through more than one provider, merge them into a single record:
v=spf1 include:mailgun.org include:sendgrid.net -all
The 10-lookup limit. Each include: in your SPF record can itself pull in more includes, and SPF only permits 10 DNS lookups in total across the chain. Large providers can use several. If you hit the limit, SPF returns a permerror and mail fails. Keep your includes to the minimum you actually need.

3DKIM: a signature that proves it

DKIM (DomainKeys Identified Mail) works differently from SPF. Rather than listing who can send, it proves that a specific message was signed by the holder of your domain, and that the message was not altered in transit.

Your mail provider generates a pair of cryptographic keys. They give you the public key to publish as a DNS record; they keep the private key and use it to sign every outgoing message. The receiving server fetches the public key from DNS and uses it to verify the signature in the message headers.

The DNS record is a TXT entry at a subdomain shaped like this:

# TXT record at:  selector._domainkey.yourdomain.com
v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUA...

The selector part is chosen by your provider (for example mx, k1, or a custom name you set). The p= value is the public key itself, which your provider gives you to paste in.

Some providers use CNAMEs instead of a TXT record: they ask you to add a CNAME that points to a subdomain they control, so they can rotate keys without you touching DNS again. Either way, your provider’s setup guide will tell you exactly what to add and where.

Once it is set up, DKIM is invisible. The signature is added to each message automatically. You do not need to do anything per-message.

4DMARC: the policy that ties it together

DMARC (Domain-based Message Authentication, Reporting and Conformance) is a TXT record that tells receiving servers what to do when a message fails SPF or DKIM, and where to send reports about what is happening.

A DMARC record goes at a specific subdomain of your domain:

# TXT record at:  _dmarc.yourdomain.com
v=DMARC1; p=none; rua=mailto:[email protected]

The key parts:

Start at p=none, watch the reports for a week or two, confirm that your own legitimate mail is all passing, then move to p=quarantine and eventually p=reject.

Why DMARC matters beyond policy. The aggregate reports (sent as XML digests to the rua address) show you exactly what is claiming to be from your domain. They often reveal third-party services sending on your behalf that you had forgotten about, which is useful before you tighten the policy.

5Verify it reaches the inbox

DNS changes can take a few minutes to an hour to propagate. Once they are live, verify properly rather than trusting that the records are there.

Use mail-tester.com. Send a test message to the address it gives you, then check your score. It reads the actual received headers and shows pass or fail for each authentication check, plus a plain-English explanation of anything that needs attention.

Use Gmail’s “Show original”. Send a test to a Gmail address and open the raw headers as described in step 1. You want to see this:

SPF:    PASS
DKIM:   PASS
DMARC:  PASS

All three passing is the only reliable confirmation. Your DNS panel showing the records is necessary but not sufficient: a record can be there and still fail if the value is wrong, the selector is mismatched, or the SPF record has a syntax error.

A “sent” log is not verification. Neither is your DNS panel saying the record exists. The only ground truth is a received message whose headers show all three checks passing. Run the test, read the headers, then call it done.

Alignment: why SPF or DKIM alone is not enough

DMARC introduces a concept called alignment, which is why having one authentication method is often still not enough.

For DMARC to pass, one of two conditions must be true. Either SPF passes and the domain in the SPF check (the envelope sender) aligns with the domain in the visible From header. Or DKIM passes and the d= domain in the DKIM signature aligns with the domain in the From header.

This matters because a provider’s shared SPF record proves that the message came from their servers, but it does not prove it came from your domain. If you send from [email protected] via a provider and only SPF is set up, the SPF check passes for the provider’s domain, not yours. DMARC alignment fails.

DKIM sidesteps this cleanly. When the DKIM signature uses your domain (d=yourdomain.com), the signing domain and the From domain are the same, so alignment passes. This is why DKIM is the more reliable path to a DMARC pass for most shared-sending setups.

Sending from a website, not the server

The most common cause of website email going to spam is that it is sent directly from the web server, without any authentication at all.

PHP’s built-in mail() function, and similar server-side mailers, simply hand the message to the local mail transfer agent and send it from the server’s IP address. That IP has no SPF record for your domain pointing to it, no DKIM key, and almost certainly no sending reputation.

From the perspective of the receiving server, the message is unauthenticated and comes from an unfamiliar IP. It will be junked or silently dropped. The site’s PHP log records a successful send, because PHP handed it off. The failure happens on the other side, invisibly.

The fix is to route all website email through a proper SMTP provider: Mailgun, Postmark, SendGrid, or a standard SMTP mailbox. The provider’s infrastructure has established sending reputation, and you publish SPF and DKIM records that authorise it to send on behalf of your domain. The message then has authentication the receiving server can verify.

Real example. A live site’s contact form logged every submission as status: sent. The messages were never reaching Gmail. On inspection, the sending subdomain had no SPF record at all and no DKIM key published. Every message was arriving unauthenticated from a shared hosting IP with no reputation. Switching to an SMTP provider and publishing both records resolved it. The log had been truthful all along: the messages left the server. They just could not get past the receiving end.
Since February 2024, Gmail and Yahoo have required SPF, DKIM and DMARC for bulk senders, and are increasingly applying pressure to all senders. The days of getting by without authentication are over for anyone who wants reliable inbox delivery.

On PageMotor and the Mailgun route

If you build on PageMotor, the EP Email plugin handles the sending layer. Configure it to use a real SMTP transport.

By default, PHP’s mailer is available but is not a reliable delivery route for the reasons above. EP Email should be pointed at a transactional email provider that gives you SPF and DKIM coverage.

Mailgun is the provider most commonly used in the ElmsPark ecosystem. The ElmsPark Mailgun guide covers the full setup: creating your Mailgun account, adding your domain, publishing the SPF and DKIM records Mailgun provides, and configuring EP Email to use the Mailgun SMTP credentials.

See: Setting up Mailgun email delivery for the step-by-step walkthrough.

The split between this guide and the Mailgun guide. This guide covers the theory: what SPF, DKIM and DMARC are, why they matter, and how to read the results. The Mailgun guide covers the click-by-click provider setup for PageMotor sites. Read this one first if the terminology is new, then follow the Mailgun guide to implement it.

The three records at a glance

A summary of each record, where it goes, and what it proves.

Record Where it goes Type Example value What it proves
SPF yourdomain.com TXT v=spf1 include:mailgun.org -all This server is allowed to send for this domain
DKIM selector._domainkey.yourdomain.com TXT (or CNAME) v=DKIM1; k=rsa; p=MIGf... This message was signed by the domain owner and not altered
DMARC _dmarc.yourdomain.com TXT v=DMARC1; p=none; rua=mailto:[email protected] What to do when SPF or DKIM fails, and where to send reports

Troubleshooting

The problems that actually come up, and what to do about each one.

SPF passes but DMARC still fails

This is almost always an alignment issue. SPF is passing for the provider’s domain (the envelope sender), not for your visible From domain. Set up DKIM with d=yourdomain.com in the signature and DMARC will pass via DKIM alignment instead. Most transactional email providers offer DKIM as part of their domain setup.

My DNS panel shows the records but DKIM still fails

Check the selector. The DKIM record name must match the selector the provider uses when signing messages. If your provider signs with selector mg, the record must be at mg._domainkey.yourdomain.com. A mismatch means the receiving server fetches the wrong name and finds nothing. Also check for trailing whitespace or split-string issues if your registrar has line-length limits.

SPF fails with “permerror”

You have exceeded the 10-lookup limit. Count how many includes your SPF record pulls in, remembering that each include can itself pull in more. Remove providers you no longer use, or use a tool like MXToolbox to count your lookups. Some providers also offer a flattened SPF record (a list of IP addresses rather than includes) to stay under the limit.

I have two SPF records on my domain

Delete one. A domain must have exactly one SPF TXT record. Merge all your providers into a single record: v=spf1 include:mailgun.org include:sendgrid.net -all. While both records exist, every SPF check returns an error and every message is treated as unauthenticated.

Mail-tester gives a low score but all three checks pass

The score factors in content as well as authentication. Common deductions include: HTML with no plain-text alternative, links to domains with a poor reputation, a From address on a domain different from the sending domain, and a subject line with spam-like patterns. The authentication checks are the critical part for deliverability; the content score is advisory.

DMARC reports are not arriving at my rua address

If the rua address is on the same domain you are protecting, the reports should simply arrive (check your spam folder, since they come as XML attachments and are easily filtered). If the rua address is on a different domain, that domain has to opt in: it must publish a DMARC external-reporting authorisation record, a TXT record at yourdomain.com._report._dmarc.theirdomain.com with the value v=DMARC1. Without it, many receivers will refuse to send the reports. Free services like Postmark’s DMARC Digests or dmarcian can receive and parse reports for you.

See also