Email Deliverability: SPF, DKIM, and DMARC for Contact Forms
Roughly 20% of legitimate email never reaches the inbox. It gets routed to spam, quarantined by a gateway, or silently dropped by the receiving server. For transactional messages — password resets, order confirmations, invoices — that number is alarming enough. But for contact form submissions, it is worse, because nobody knows the message was lost. The customer thinks they reached out. You never saw it. The deal dies in silence.
If you run a WordPress site with a contact form, email deliverability is not someone else’s problem. It is your problem. And if bots are hammering that form, it is an urgent one.
This guide covers the three DNS-based authentication protocols that determine whether your form emails reach the inbox — SPF, DKIM, and DMARC — and explains how spam bot abuse accelerates the damage when any of them are misconfigured or missing.
The Problem: Your Contact Form Emails Are Disappearing
Here is a scenario that plays out on thousands of WordPress sites every week.
A visitor fills out your Contact Form 7 form and clicks submit. Your server fires off a notification email to your inbox. The visitor sees a success message and assumes you got it. But the email never arrives. It was rejected by Gmail, flagged by Microsoft 365, or silently dropped by your company’s mail gateway.
You check your spam folder. Nothing. You check your server logs. The mail was sent — wp_mail() returned true. The SMTP handshake completed. The message left your server.
So where did it go?
The Receiving Server Decided You Could Not Be Trusted
Modern mail servers do not just look at the content of your email. Before they even read the subject line, they check three things:
- Is the sending server authorized to send email for this domain? (SPF)
- Was the message cryptographically signed by the domain it claims to be from? (DKIM)
- What should we do if the first two checks fail? (DMARC)
If your domain does not have these records configured — or if they are misconfigured — the receiving server has no way to verify that your email is legitimate. It treats it the same way it treats phishing attempts and spam blasts: with suspicion or outright rejection.
This is not paranoia on the receiving server’s part. It is policy. Google, Microsoft, and Yahoo all enforce strict authentication requirements for inbound mail. As of 2024, Google requires SPF and DKIM and DMARC for any sender delivering more than 5,000 messages per day to Gmail accounts. Even below that threshold, missing authentication records significantly increase the probability of landing in spam.
Spam Bots Make Everything Worse
Now layer bot abuse on top of the authentication problem.
A spam bot discovers your contact form endpoint and starts submitting thousands of entries. Each submission triggers a notification email from your server. Suddenly, your domain is sending hundreds of emails per hour — all containing garbage content laced with pharmaceutical keywords, phishing URLs, or Cyrillic gibberish.
Even if your SPF, DKIM, and DMARC records are perfectly configured, this surge does two things:
- Volume anomaly. Mail providers track your domain’s normal sending patterns. A sudden spike flags your domain for throttling or temporary blacklisting.
- Content reputation damage. The spam payloads in those notification emails — which your server faithfully relayed — poison your domain’s content reputation score. Filters learn that emails from your domain contain spam-like content.
Your authentication records prove the emails really came from you. That is the problem. You just authenticated a flood of garbage, and now your domain owns it.
Technical Deep Dive: SPF, DKIM, and DMARC
These three protocols work together as a chain of trust. Each one solves a specific piece of the authentication puzzle. Let’s walk through them.
SPF (Sender Policy Framework)
SPF answers one question: which servers are allowed to send email on behalf of your domain?
It works through a DNS TXT record published on your domain. When a receiving mail server gets a message claiming to be from you@yourdomain.com, it looks up the SPF record for yourdomain.com and checks whether the sending server’s IP address is on the authorized list.
How to Set It Up
An SPF record is a single TXT record on your root domain. Here is a typical example:
yourdomain.com. IN TXT "v=spf1 ip4:203.0.113.50 include:_spf.google.com include:spf.mailgun.org ~all"
Breaking this down:
v=spf1— Declares this is an SPF record (version 1).ip4:203.0.113.50— Directly authorizes this specific IP address to send mail for your domain. This would be your web server or dedicated SMTP server.include:_spf.google.com— Authorizes any server listed in Google Workspace’s SPF record. Use this if you send email through Gmail/Google Workspace.include:spf.mailgun.org— Authorizes Mailgun’s servers. Swap this for your transactional email provider (Postmark, SendGrid, Amazon SES, etc.).~all— A soft fail for any server not listed. This tells receiving servers to accept the message but treat it with suspicion. Using-all(hard fail) is stricter and tells receivers to outright reject unauthorized senders.
Common Mistakes
- No SPF record at all. Surprisingly common. Without it, any server on the internet can claim to send email as your domain and the receiving server has no basis to reject it.
- Too many DNS lookups. SPF has a hard limit of 10 DNS lookups per evaluation. Each
include:directive triggers at least one lookup. Nested includes (where the included domain’s SPF record contains its owninclude:directives) count toward your limit. Exceeding 10 causes the entire SPF check to returnpermerror, which most receivers treat the same as a fail. - Multiple SPF records. You can only have one SPF TXT record per domain. If you have two (common when adding a new email service and forgetting to merge), the result is undefined behavior — most servers will fail the check entirely.
- Using
+all. This authorizes every server on the internet to send as your domain. It is the same as having no SPF record, but worse, because it looks intentional.
WordPress-Specific Consideration
If your WordPress site sends form notification emails directly via the server’s local sendmail or PHP mail() function, the sending IP is your web server’s IP. That IP must be in your SPF record. If you are on shared hosting, that IP is shared with potentially hundreds of other sites — and their spam problems affect your deliverability.
This is one of the strongest arguments for routing WordPress email through a dedicated SMTP service instead of relying on the server’s local mail transport.
DKIM (DomainKeys Identified Mail)
DKIM answers a different question: was this email actually sent by the domain it claims to be from, and was it tampered with in transit?
SPF checks the server. DKIM checks the message itself.
How It Works
DKIM uses public-key cryptography. When your mail server sends a message, it generates a cryptographic signature of key message headers (From, Subject, Date) and the body content, then attaches that signature as a DKIM-Signature header. The private key used to generate the signature lives on your mail server. The corresponding public key is published in a DNS TXT record.
When the receiving server gets the message, it extracts the DKIM signature, looks up the public key from your DNS, and verifies the signature. If it matches, the receiving server knows two things: (1) the message genuinely came from your domain, and (2) nobody altered it in transit.
DNS Record Example
DKIM public keys are published as TXT records on a subdomain that includes a selector — an arbitrary label that lets you have multiple DKIM keys (for different services or key rotation).
selector1._domainkey.yourdomain.com. IN TXT "v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1Z2..."
Breaking this down:
selector1— The selector name. Your email provider tells you what this is. Google Workspace usesgoogle, Mailgun uses something likemailo, Postmark uses a dated key like20221121._domainkey— A fixed subdomain required by the DKIM spec.v=DKIM1— DKIM version.k=rsa— The key algorithm (RSA is standard; Ed25519 support is growing).p=MIIBIj...— The actual public key, base64-encoded.
Common Mistakes
- Not enabling DKIM at all. Many hosting providers and SMTP services support DKIM but do not enable it by default. You have to explicitly generate the key pair and publish the DNS record.
- Stale keys after switching providers. If you move from Mailgun to Postmark but leave Mailgun’s DKIM record in DNS and remove the key from Mailgun’s side, messages signed with the old key will fail verification.
- Key length too short. RSA keys should be at least 1024 bits, and 2048 bits is the modern standard. Some older configurations still use 512-bit keys, which are considered broken.
Why DKIM Matters for Contact Forms
When your WordPress site sends a form notification through a properly configured SMTP service with DKIM signing, the receiving server can cryptographically verify the message originated from your domain. Without DKIM, the email is one missing signal away from the spam folder — especially if the form notification contains content that looks even slightly suspicious (URLs, HTML formatting, certain keywords).
DMARC (Domain-based Message Authentication, Reporting, and Conformance)
DMARC ties SPF and DKIM together and tells receiving servers what to do when authentication fails.
Without DMARC, SPF and DKIM are informational. A receiving server can check them, but there is no published policy from the domain owner saying “if these checks fail, reject the message.” DMARC provides that policy.
How It Works
DMARC adds two things:
- A policy (
none,quarantine, orreject) that tells receiving servers how to handle messages that fail SPF and DKIM alignment checks. - A reporting mechanism that sends you aggregate and forensic reports about authentication results, so you can see who is sending email as your domain and whether it is passing or failing.
The critical concept is alignment. DMARC requires that the domain in the From: header matches (or is a subdomain of) the domain authenticated by SPF or DKIM. This prevents an attacker from passing SPF using their own domain but spoofing your domain in the From: header.
DNS Record Example
_dmarc.yourdomain.com. IN TXT "v=DMARC1; p=quarantine; rua=mailto:dmarc-reports@yourdomain.com; ruf=mailto:dmarc-forensic@yourdomain.com; pct=100; adkim=r; aspf=r"
Breaking this down:
v=DMARC1— DMARC version.p=quarantine— Policy. Options are:none— Monitor only. Do not take action on failures. Use this when you are first deploying DMARC to collect data before enforcing.quarantine— Send failing messages to the spam/junk folder.reject— Drop failing messages entirely. The strictest setting.rua=mailto:dmarc-reports@yourdomain.com— Where to send aggregate reports. These are daily XML reports from receiving servers showing how many messages passed/failed authentication. Services like Postmark’s DMARC monitoring tool, dmarcian, or Valimail can parse these for you.ruf=mailto:dmarc-forensic@yourdomain.com— Where to send forensic (failure) reports with details about individual failed messages. Not all receivers send these.pct=100— Apply the policy to 100% of messages. You can lower this during rollout (e.g.,pct=25to only apply to 25% of messages).adkim=r— DKIM alignment mode:rfor relaxed (subdomains allowed),sfor strict (exact domain match required).aspf=r— SPF alignment mode:rfor relaxed,sfor strict.
The Recommended Deployment Path
Do not jump straight to p=reject. The recommended approach:
- Start with
p=noneand set upruareporting. Collect data for 2-4 weeks. Review the reports to identify all legitimate services sending email as your domain. - Fix any authentication gaps. Add SPF includes and DKIM records for every legitimate sending service you find in the reports.
- Move to
p=quarantineat a low percentage (pct=25). Monitor for false positives — legitimate emails landing in spam. - Gradually increase
pctto 100, then move top=rejectonce you are confident all legitimate mail is authenticating correctly.
Skipping this process risks blocking your own legitimate email.
How Spam Bots Destroy Your Sending Reputation
Even with SPF, DKIM, and DMARC perfectly configured, a spam bot abusing your contact form can wreck your email deliverability through a different channel: domain reputation.
Mail providers maintain reputation scores at two levels: IP reputation and domain reputation. Authentication records handle the identity question. Reputation scores handle the trust question. You can be perfectly authenticated and still land in spam if your reputation is poor.
The Mechanism
Here is what happens step by step when bots flood your contact form:
- Bot submits 5,000 form entries in 24 hours, each containing spam payloads (fake names, junk URLs, random text with embedded links).
- Your server sends 5,000 notification emails to your admin inbox (or worse, to dynamic recipient addresses if your form has a CC or auto-response feature).
- Volume spike. Google and Microsoft track your domain’s historical sending volume. A sudden jump from 20 emails/day to 5,000 emails/day triggers automated throttling.
- Content analysis. The notification emails contain the bot’s payload in the body. Spam filters scan this content. Pharmaceutical keywords, shortened URLs, excessive links, and patterns associated with phishing all contribute to a negative content score.
- Engagement signals collapse. If your notification emails land in the inbox, nobody clicks through them (because they are garbage). Zero engagement is a negative signal for providers that use engagement-based filtering.
- Reputation degrades. Your domain’s sender reputation score drops. This affects all email from your domain — not just form notifications. Your marketing emails, transactional emails, and personal correspondence from
@yourdomain.comaddresses start landing in spam.
The Feedback Loop From Hell
The worst scenario involves forms with auto-reply functionality — forms that automatically send a confirmation email to the address the submitter provided.
When bots fill in random email addresses (or real email addresses harvested from data breaches), your server sends confirmation emails to those addresses. The recipients did not ask for this email. They mark it as spam or ignore it. Some of those addresses are spam traps — email addresses maintained by blacklist operators specifically to catch unsolicited senders.
Hitting a spam trap is one of the fastest ways to land on a DNSBL (DNS-based Blackhole List). Once you are listed on Spamhaus, Barracuda, or SpamCop, a significant portion of the internet will refuse your email entirely. Delisting is a manual process that takes days to weeks and requires demonstrating the problem has been resolved.
Your DMARC record said p=reject, your SPF and DKIM were perfect, and you still ended up on a blacklist. Authentication proves identity. It does not prove intent.
The Solution: Protecting Deliverability at Every Layer
Fixing email deliverability for contact forms requires work at three levels: DNS authentication, sending infrastructure, and form-level protection.
Level 1: Get Your DNS Records Right
This is table stakes. If you have not done this, do it now.
SPF checklist:
– Publish a single SPF TXT record on your root domain.
– Include every service that sends email as your domain (hosting server, Google Workspace, transactional email provider, marketing platform).
– Stay under 10 DNS lookups. Use an SPF flattening tool if necessary.
– End with ~all or -all. Never +all.
DKIM checklist:
– Enable DKIM signing with your email provider or SMTP relay.
– Publish the public key as a TXT record using the correct selector.
– Use 2048-bit RSA keys at minimum.
– Verify the signature using a tool like dkimvalidator.com or mail-tester.com.
DMARC checklist:
– Start with p=none and aggregate reporting to understand your current authentication landscape.
– Fix all legitimate senders that are failing authentication.
– Gradually move to p=quarantine, then p=reject.
– Monitor reports continuously. Services like Postmark DMARC, dmarcian, or EasyDMARC make this manageable.
Here is a minimal but complete DNS setup for a domain using Google Workspace and Mailgun:
; SPF — authorize Google and Mailgun, soft-fail everything else
yourdomain.com. IN TXT "v=spf1 include:_spf.google.com include:spf.mailgun.org ~all"
; DKIM — Google Workspace key
google._domainkey.yourdomain.com. IN TXT "v=DKIM1; k=rsa; p=MIIBIjANBgkqhk..."
; DKIM — Mailgun key
mailo._domainkey.yourdomain.com. IN TXT "v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3..."
; DMARC — quarantine policy with reporting
_dmarc.yourdomain.com. IN TXT "v=DMARC1; p=quarantine; rua=mailto:dmarc@yourdomain.com; pct=100"
Level 2: Route WordPress Email Through a Dedicated SMTP Service
Stop sending email through PHP’s mail() function or your server’s local MTA. Use a transactional email service:
- Postmark — Built specifically for transactional email. Strict anti-spam policies keep their IP pools clean. Excellent deliverability.
- Mailgun — Flexible API and SMTP relay. Good for high-volume senders.
- Amazon SES — Cheapest at scale. Requires more manual reputation management.
- SendGrid — Widely used. Mixed reputation due to shared IP pools on lower-tier plans.
Configure your chosen service using a WordPress SMTP plugin (WP Mail SMTP, FluentSMTP, or Post SMTP). This gives you:
- Dedicated sending IPs (or well-managed shared pools) that are not contaminated by your hosting neighbors.
- Automatic DKIM signing handled by the service.
- Delivery logs and bounce tracking so you can see exactly what happened to each message.
- Reputation monitoring with alerts when something goes wrong.
Level 3: Stop Spam Before It Generates Email
This is the part most guides skip, and it is arguably the most important.
DNS authentication and a good SMTP service protect your infrastructure. But if spam bots are still submitting thousands of form entries, your server is still sending thousands of notification emails full of junk content. Authentication proves those emails are really from you. A high-quality SMTP service delivers them reliably. You have just authenticated and reliably delivered garbage.
The only way to protect your domain reputation is to prevent spam submissions from generating email in the first place.
Rate limiting at the server level helps:
# Nginx: limit CF7 submissions to 5 per minute per IP
limit_req_zone $binary_remote_addr zone=cf7:10m rate=5r/m;
location ~* /wp-json/contact-form-7/ {
limit_req zone=cf7 burst=2 nodelay;
}
But rate limiting alone is not enough. Modern bots rotate through thousands of IP addresses. You need form-level protection that blocks automated submissions before the processing pipeline reaches wp_mail().
This is where server-side spam prevention becomes a deliverability tool, not just a convenience feature. A honeypot that catches a bot submission and silently discards it — before any email is sent — is directly protecting your SPF, DKIM, and DMARC investment. Every spam email you do not send is one less data point degrading your domain reputation.
For Contact Form 7, Samurai Honeypot for Forms handles this by intercepting spam submissions before they enter the mail pipeline. Its layered detection — polymorphic honeypot fields, timing analysis, server-side token validation — stops bots at the form layer, which means no notification email gets generated, no SMTP connection gets opened, and no reputation-damaging content leaves your server. It is the missing layer between your DNS authentication setup and your sending infrastructure.
Verifying Your Setup
After configuring everything, verify the entire chain:
- Check SPF. Use MXToolbox SPF Lookup to verify your record parses correctly and stays under 10 lookups.
- Check DKIM. Send a test email to
check-auth@verifier.port25.comor use mail-tester.com. The report will show whether your DKIM signature validates. - Check DMARC. Use MXToolbox DMARC Lookup to verify your record syntax. Then wait for aggregate reports to arrive (usually within 24-48 hours of publishing the record).
- Check reputation. Google Postmaster Tools shows your domain’s reputation with Gmail. Microsoft SNDS does the same for Outlook.
- Test the full path. Submit your contact form and trace the notification email. Check the raw headers for
Authentication-Results. You want to seespf=pass,dkim=pass, anddmarc=pass.
A passing header looks like this:
Authentication-Results: mx.google.com;
dkim=pass header.i=@yourdomain.com header.s=google header.b=abc123;
spf=pass (google.com: domain of noreply@yourdomain.com designates 203.0.113.50 as permitted sender) smtp.mailfrom=noreply@yourdomain.com;
dmarc=pass (p=QUARANTINE sp=QUARANTINE dis=NONE) header.from=yourdomain.com
If any of those show fail or softfail, trace back through the relevant DNS record and fix the gap.
Key Takeaways
-
SPF, DKIM, and DMARC are not optional. Major mail providers enforce authentication requirements. Without all three, your contact form emails will increasingly land in spam or get rejected outright.
-
Authentication is necessary but not sufficient. These protocols prove your identity. They do not protect your reputation. A perfectly authenticated flood of spam emails damages your domain just as effectively — arguably more so, because the receiving server knows it was really you.
-
Spam prevention is a deliverability strategy. Blocking bot submissions before they generate email is the most direct way to protect your sender reputation. Every spam email you do not send is a reputation hit you do not take.
-
Use a dedicated SMTP service. Stop sending WordPress email through your web server’s local MTA. Transactional email services provide better deliverability, DKIM signing, and reputation management out of the box.
-
Monitor continuously. Publish your DMARC record with reporting enabled. Check Google Postmaster Tools. Watch your bounce rates. Deliverability is not a set-it-and-forget-it configuration — it is an ongoing operational concern.
Your contact form is only useful if the messages it sends actually arrive. Getting SPF, DKIM, and DMARC right is the foundation. Keeping spam bots from abusing the pipeline is what keeps that foundation from cracking.
This post is part of a series on WordPress form security and deliverability. Previously: The Hidden Cost of Spam: IP Blacklisting and Server Load.