The contact form says the message was sent. Your inbox disagrees. Or worse — it worked for a month, you stopped checking, and you've been quietly missing enquiries since.
Almost every version of this has the same root cause, and it isn't your sending provider. It's one line of the email you're generating, written the way that seems most obviously correct.
The mistake: the visitor's address in the From header
You build the email and you want it to look like it's from whoever filled in the form, so replying is natural. So you set:
From: jane@example.com
You have just told the receiving mail server that your application, sending from your infrastructure, is example.com. You are claiming to be a domain you have no authority over. That is indistinguishable — technically identical, in fact — from what a phishing campaign does, and the entire modern email authentication stack exists to catch exactly this.
The rule that kills it is DMARC alignment: the domain in the visible From: header has to match the domain authenticated by SPF or DKIM. Your provider signs for your domain. The From header says someone else's. They don't align, so the check fails, and what happens next is decided by the policy the real owner of that domain published — which for any large mail provider is "reject" or "quarantine".
Note the sting in that: whether your contact form works depends on the DMARC policy of whatever domain the visitor happens to use. Someone on a small host with no policy gets through. Someone on Gmail doesn't. That is why this bug is so often reported as intermittent, and why it survives testing — you tested with your own address.
The fix, in two lines
Send from your own verified domain, and put the visitor's address where it belongs.
From: forms@yourdomain.com— a real address on a domain you control and have verified with your provider. This is the field that has to authenticate.Reply-To: jane@example.com— the visitor. This is the field that exists precisely for "the sender and the person you should answer are different".
Now hitting reply still goes to Jane, which was the entire reason you wanted her address in From, and nothing is being spoofed. Every mail provider supports this. It has always been the right shape.
Put her name and address in the body too. When something goes wrong with headers — and eventually something will — you want the actual reply address visible as text rather than only in metadata.
The three records, and what each does
These get listed as a checklist, which makes them feel arbitrary. They're not; they do three different jobs.
SPF is a DNS record listing who is allowed to send on your domain's behalf. One trap worth knowing: it fails if resolving your record takes more than ten DNS lookups. Each include: costs at least one, so a domain that has accumulated a mail host, a CRM, a newsletter tool and an invoicing service can silently blow the limit — and then SPF fails for everything, including mail that was working yesterday.
DKIM cryptographically signs the message. You publish a public key in DNS, your provider signs with the private half, and the receiver verifies. Unlike SPF, it survives forwarding, which is why it's the stronger of the two.
DMARC ties them together and is the part that does the work. It says what to do when neither aligns — none, quarantine, or reject — and it can send you reports about who is sending as you.
Start at p=none with reporting on. You'll find out what's actually sending as your domain, which on any domain with a few years of history is more things than you remember. Fix those, then move to quarantine, then reject. Going straight to p=reject is how you discover that your invoicing system was never authenticated, by way of your accountant not receiving anything.
You are almost certainly not a bulk sender
Worth saying plainly, because the guidance around this is written for marketing teams and it makes a contact form sound like a compliance project.
Google's bulk sender rules kick in at around 5,000 messages a day to Gmail addresses. A portfolio contact form is four orders of magnitude below that. The one-click unsubscribe requirement — List-Unsubscribe and List-Unsubscribe-Post — applies to marketing mail, not to a message someone deliberately sent you.
What does apply to everyone is authentication, because alignment isn't a threshold rule — it's how the receiver decides whether to believe your From header at all. And enforcement has tightened: what began in early 2024 as temporary deferrals has become permanent rejection for non-compliant mail. Failing quietly into spam is no longer the worst case.
Set the envelope up so bounces reach you
A detail that catches people whose headers are otherwise perfect: if your form emails you and you've set Reply-To to the visitor, a bounce or an auto-reply may follow the return path rather than the From address.
Make sure whatever address that resolves to is one a human reads. A sending domain whose bounces go nowhere accumulates failures that you can't see and the provider can, and provider-side reputation is built from exactly that.
Then actually verify it
Don't infer this from the absence of complaints. Send a message through your real form to a Gmail address you control, open it, and view the original. You want three explicit passes — SPF, DKIM, DMARC — and you want the From domain to be yours.
Then send to an Outlook address, because the providers don't agree with each other, and a setup that satisfies Gmail can still be marginal elsewhere.
And put a calendar reminder in for six months. DNS records get edited by whoever is migrating something, provider defaults change, domains get moved between registrars. The failure mode of email deliverability is that it stops working and tells absolutely nobody — the sender sees a success response, the recipient sees nothing, and there is no error anywhere in your logs.