Grow · Intermediate
Why emails from your website land in spam: SPF, DKIM and DMARC explained
A visitor fills in your contact form, the site says “sent”, and nothing arrives, or it arrives in the spam folder. Usually the website is fine: the receiving mail server simply has no way to tell your email from a forgery. SPF, DKIM and DMARC are the three DNS records that give it that proof.

Photo: Nilo Velez, public domain (CC0)
In this guide
Why a receiving server distrusts your website
Email has no built-in proof of who sent a message, and anyone can put any address in the From line. Receiving servers therefore look for evidence that a message really comes from the domain it claims, and when they find none they file it as spam or refuse it. Mail from a website is the classic victim: it is generated by a web server, not by the company’s normal mail system, from a machine the domain has never vouched for.
The evidence comes from three DNS records published by the sending domain. SPF says which servers may send mail for the domain. DKIM adds a signature that proves the message was signed with a key the domain published and was not altered. DMARC tells receivers what to do when the first two fail, and asks them to send reports. Business mail providers, including Microsoft 365 and Google Workspace, check all three and treat unauthenticated mail with suspicion, whatever the content says.
| Symptom | Usual cause | Fix |
|---|---|---|
| Form says “sent”, nothing arrives anywhere | Mail routed to a local mailbox on the web server, or discarded | Check the hosting mail log and the domain’s mail routing |
| Spam at one provider, inbox at another | No SPF or DKIM; receivers apply their own thresholds | Publish SPF and DKIM for the sending domain |
| Worked for months, stopped after a DNS change | SPF now ends in -all and misses the relay | Add the relay to SPF |
| Messages rejected outright | Form sends “as” the visitor’s address | Send from the site’s own address, Reply-To the visitor |
| Rejected with a DMARC message | From domain does not align with SPF or DKIM | Use a From address on the domain that SPF and DKIM cover |
The chain from sender domain to inbox
Every message carries two sender identities. The envelope sender is the address the sending server announces during delivery, where bounces go. The From header is what the reader sees. SPF checks the envelope sender’s domain, DKIM signs with a domain of its own, and DMARC checks whether at least one of those domains matches the From header. That match is called alignment, and it is the step most people have never heard of.
SPF: which servers may send
SPF is a TXT record on the domain itself. It lists the IP addresses and included providers allowed to send mail for the domain, and ends with a rule for everyone else: ~all (treat as suspicious) or -all (fail). A website that sends through the hosting provider’s mail relay must have that relay in the record. A record that ends in -all and forgets the relay produces a hard fail on every message the site sends; this often happens when the office mail is tightened and nobody thinks of the website.
DKIM: a signature on the message
DKIM is a public key published at selector._domainkey.example.com. The sending server signs each message with the matching private key; the receiver fetches the public key and verifies the signature. If your website sends through a mail service or the hosting relay, that service gives you the key to publish and does the signing.
DMARC: the policy and the reports
DMARC is a TXT record at _dmarc.example.com. It states a policy for messages that fail both aligned SPF and aligned DKIM: p=none (deliver and report), p=quarantine (spam folder) or p=reject. It also names an address for aggregate reports, which receivers send daily. Those reports are the only way to see which servers send mail in your name and whether they pass. Start with p=none, read the reports for a few weeks, fix every legitimate sender that fails, then move to quarantine or reject.
Why sending “as the visitor” breaks everything
Many contact form plugins put the visitor’s own address in the From line, so that the reader can simply hit reply. That setup now fails all three checks at once: your server is not in the SPF record of the visitor’s domain, it has no DKIM key for that domain, and the From domain is the visitor’s, so alignment is impossible. If the visitor’s provider publishes a reject or quarantine policy, the receiver is told to refuse or hide the message, and you never see the enquiry.
The correct setup is simple:
- From address: a mailbox on your own domain, for example website@example.com, which SPF and DKIM cover.
- From name: the visitor’s name is fine, it is only a label.
- Reply-To: the visitor’s address, so that a reply still reaches the right person.
- Sending route: an authenticated connection to your mail provider or a mail service, not an unauthenticated send from the web server, so that the message is signed and leaves from a listed server.
Also check where the message is going. If the recipient address is on your own domain but your mailboxes live with another provider, the hosting account must route mail for the domain to that provider. When it is set to local delivery instead, the web server hands the message to a mailbox on itself, or to nothing, and no error reaches anyone. No DNS record fixes this.
A worked example of the three records
The set below is illustrative and uses the reserved domain example.com and a documentation IP address. Replace the include and the key with the values your provider gives you.
| Record name | Type | Value | Purpose |
|---|---|---|---|
| example.com | TXT | v=spf1 include:relay.mailprovider.example ip4:203.0.113.10 -all | Allows the relay and one own server, fails everything else |
| mail._domainkey.example.com | TXT | v=DKIM1; k=rsa; p=(public key from the provider) | Publishes the DKIM public key under the selector “mail” |
| _dmarc.example.com | TXT | v=DMARC1; p=quarantine; rua=mailto:dmarc@example.com | Policy for failures and where to send reports |
How to read it: the mail provider’s relay is allowed through its include, the website’s own server through its IP address, and everything else fails. The website signs with the selector “mail” and sends from an address on example.com, so both SPF and DKIM align with the From domain. If the website later moves to another host, SPF and the DKIM key must change on the same day. Two cautions: a domain must have exactly one SPF record, a second one invalidates both; and DNS changes take time to spread, so test hours after publishing, not seconds.
The figures below are an illustrative example of what fixing the setup changes for a site that receives 200 form enquiries a month. Before: 120 in the inbox, 60 in spam, 20 rejected (120 + 60 + 20 = 200). After: 196, 3 and 1 (196 + 3 + 1 = 200).
Illustrative example: where 200 monthly form emails end up, before and after the fix
Checking and keeping it working
Mail authentication is not a one-off task. Every new sending system, change of host or tightened policy can break it again, which is why it belongs in regular website care. A site on managed hosting should have its sending route, SPF and DKIM documented, so that a later change does not undo them.
A rebuild is a good moment to check all of this, because the sending route usually changes with the host. If your website is being moved or redesigned, put the mail setup on the migration checklist and test it before the old site is switched off.
Questions we hear often
Want this sorted without doing it yourself?
Tell us what you are working on. A person replies within one working day.
