Why Your Contact Form Emails Land in Spam (and How to Fix It)
The usual cause isn't your content — it's sending the notification as the visitor. What From, Reply-To, SPF, DKIM and DMARC actually do, and the 2026 rules.
The ShipMyForm team
· 5 min read
Most contact form notifications land in spam for one reason, and it is not
the wording. It is the From address. If your form sends the notification
as the person who filled it in, you are sending mail that claims to come from
a domain you do not control. That is exactly the forgery that SPF and DMARC
were built to stop, so the message fails authentication before anyone reads a
word of it.
The fix is a one-line change in concept: send from your own domain, and put
the visitor's address in Reply-To.
- From: [email protected] ← claims to be Gmail, fails authentication
+ From: [email protected] ← a domain you can prove you own
+ Reply-To: [email protected] ← hitting reply still reaches themFull disclosure: ShipMyForm is our product, and it does exactly this on your behalf. The explanation below applies whoever sends your mail.
Why that one field decides it
From is a claim about identity, and receivers check it. Reply-To is only an
instruction about where a reply should be addressed, and nothing verifies it at
all.
So putting the visitor in From fails in the worst possible way. Gmail asks
whether your server is allowed to send for gmail.com, the answer is no, and
the message is treated as impersonation. Putting the visitor in Reply-To
costs you nothing, because replying still opens a message addressed to them.
This single mistake causes more form-email spam filtering than every other cause combined, and almost every "PHP contact form" tutorial on the internet teaches it.
The three records, in plain terms
If you send the mail yourself, you own all three. They are not interchangeable, and passing one is not enough.
| Record | The question it answers | What breaks without it |
|---|---|---|
| SPF | Which servers may send mail for this domain? | Any server can claim to be you, so receivers distrust all of it |
| DKIM | Was this message actually signed by that domain, unaltered? | Nothing cryptographically ties the mail to you |
| DMARC | What should I do when the above fail, and do the domains line up? | Receivers guess, and increasingly they guess "reject" |
The part people miss is DMARC alignment. It is not enough for SPF or DKIM
to pass for some domain. The domain in the visible From header has to match
the domain that passed. This is precisely why sending as the visitor cannot be
rescued by adding records to your own domain.
What changed, and why old advice is now wrong
The tolerant era is over. Google, Yahoo and Microsoft now require SPF, DKIM and
DMARC from bulk senders, generally defined as 5,000 or more messages a day to
their users, with a DMARC policy of at least p=none and From alignment.
They also expect a spam complaint rate under 0.3 percent, with 0.1 percent as
the real target.
Two details matter more than the thresholds. Enforcement is now full rather than phased. And non-compliant mail is increasingly rejected outright rather than delivered to a spam folder, which means it does not quietly arrive somewhere unloved, it never arrives at all.
A contact form is nowhere near 5,000 messages a day, so the bulk rules do not formally bind you. That is the trap. The infrastructure built to enforce them inspects everything, and mail that fails authentication is now judged against expectations set by those rules. Being small exempts you from the paperwork, not from the filter.
One-click unsubscribe (RFC 8058) is required for bulk promotional mail, not for a notification you asked to receive. Do not add it to form notifications and do not let a checklist tell you otherwise. Authentication applies to everything; unsubscribe headers apply to marketing.
Why sending it yourself is harder than it looks
SMTP from your application server. The server almost certainly has no sending reputation, often shares an IP with strangers, and usually signs nothing. Shared hosting is worse: you inherit the reputation of every other account on the box.
mail() and similar. It hands the message to a local agent with no
authentication, no signing and no delivery feedback. It returns success when
the message was accepted locally, which tells you nothing about whether it
arrived.
Credentials in the browser. Any email API key reachable from client-side code is public. Someone will find it and send from your domain, and your reputation goes with it. This is covered in more detail in sending form email without SMTP.
Serverless functions. Better, but you still own the provider account, the DNS records, the bounce handling, and the retry logic for the minutes your provider is having a bad day. The Vercel contact form guide walks through what that actually costs.
The two honest fixes
Send it properly yourself. Use a transactional email provider, verify a
sending domain, publish SPF, DKIM and DMARC records for it, and send from a
subdomain such as mail.yourdomain.com so that form mail cannot damage the
reputation of your ordinary correspondence. Put the visitor in Reply-To.
This is a genuine, correct answer if you already run email infrastructure.
Let something that already did it send for you. A
form backend sends from its own
authenticated domain with the records already in place and a reputation it has
an incentive to protect. ShipMyForm sends notifications from
[email protected] and sets Reply-To to the address found in
the submission, so replying reaches the person who wrote to you. You publish no
DNS records and hold no keys.
Check yours in about a minute
Send one submission through your own form, open the email you receive, and view the original message. In Gmail that is the three-dot menu, then Show original.
You want to see three lines reading PASS:
SPF: PASS with IP 203.0.113.10
DKIM: 'PASS' with domain mail.example.com
DMARC: 'PASS'Then check the domain on the DKIM line matches the domain in From. If it does
not, you have an alignment problem even though both checks passed.
SOFTFAIL, NEUTRAL or none on any line is the answer to why you are in the
spam folder. It is not your subject line, and rewording it will not help.
The thing to change today
If your form sends the notification as the visitor, change From to an address
on your own domain and move theirs to Reply-To. Nothing else on this page
matters until that is true, because no amount of DNS configuration can
authenticate you as somebody else's mail provider.
Next steps
- The mechanics of getting form mail delivered at all: HTML form to email
- Why client-side sending cannot be secured: send form email without SMTP
- New to the pattern: what is a form backend?
- Start free: notifications sent from an authenticated domain, 100 submissions a month, no credit card.
Frequently asked questions
- Why do my contact form emails go to spam?
- The most common cause is the From address. If your form sends the notification as the visitor (From: [email protected]), you are sending mail claiming to be a domain you do not control. SPF and DMARC exist precisely to stop that, so the message fails authentication and gets filtered or rejected. Send from an address on your own domain and put the visitor's address in Reply-To instead.
- What is the difference between From and Reply-To on a form notification?
- From is who the message claims to be sent by, and it is checked against your DNS records. Reply-To is only where a reply is addressed, and nothing authenticates it. You want From to be your own authenticated sending domain, and Reply-To to be the person who filled in the form, so hitting reply still reaches them.
- Do I need SPF, DKIM and DMARC for a contact form?
- If you send the mail yourself, yes. SPF lists which servers may send for your domain, DKIM signs the message so it can be verified, and DMARC tells receivers what to do when those checks fail and requires the From domain to align with one of them. Google, Yahoo and Microsoft formally require all three from bulk senders, and the expectation has spread to ordinary transactional mail. If a form backend sends on your behalf, it handles this on its own domain.
- Can I just use SMTP or PHP mail() from my site?
- You can, and it is the fastest route to the spam folder. Shared hosting and most application servers send from IP addresses with no reputation and usually no DKIM signing, and any credentials in client-side code are exposed to anyone who views source. A transactional email provider with a verified domain, or a form backend that already has one, is what actually reaches inboxes.
- How do I tell whether my form emails are authenticated?
- Send yourself one and open the original message. In Gmail, use Show original, and look for SPF, DKIM and DMARC each showing PASS, and check that the From domain matches the signing domain. If any says fail, softfail or none, that is your problem, not your subject line.
- Does the spam folder problem affect the auto-reply to the submitter too?
- Yes, and often worse. A confirmation sent to the person who just submitted goes to a stranger's inbox with no prior relationship, so it is judged harder than mail to your own address. It needs the same authenticated sending domain, and it should come from you rather than appearing to come from them.
Related guides
Send Email From an HTML Form — No SMTP, No PHP
What SMTP actually is, why your HTML form can't speak it (and shouldn't), and the modern setup that emails you submissions with zero mail servers.
How to Send an HTML Form to Your Email (Without a Backend)
Why mailto: and PHP mail() let you down on a static site — and the reliable way to get form submissions into your inbox, spam folder avoided.
What Is a Form Backend? (And When You Need One)
The plain-language definition, how form endpoints work, and when a hosted backend beats rolling your own.