When company mail keeps landing in spam, the cause is usually three DNS records nobody set up when the domain was registered. Not a plugin, not the hosting, not the wording of the message. Anyone typing “spf dkim dmarc” into Google has usually already had a few conversations along the lines of “I sent you the quote on Monday, you did not get it?” and wants one concrete thing: what to paste into the domain panel, and how to confirm it worked.
This is a setup guide from zero, for a small company domain with mail in one place and a website in another. Diagnosing a store that sends nothing at all is a separate story, covered in the piece on WooCommerce not sending order emails. Here I assume the messages leave correctly and nobody on the other end has a reason to trust them.
One warning up front. DNS is one of the few places where a typo stops all of your company mail, not just the mail from your site. Take it slowly, copy the current value of every record into a notepad before you touch it, and change one record at a time.
SPF, DKIM and DMARC - what each one does and why mail fails without them
The receiving server gets a message claiming to be from your company. It has no reason to believe that, because the sender field can say anything, exactly like the return address on an envelope. The three records in your domain’s DNS are the only place where you can tell that server how to separate your message from a forgery.
SPF answers “is this server allowed to send on behalf of this domain”. It is a list of the addresses and services you authorise. If your mailbox sits in Google Workspace and your website sends through your hosting, both have to be on the list, because those are two independent channels.
DKIM answers “was the content altered in transit, and does the sender hold the key”. The sending server signs each message with a private key, and the matching public key sits in your DNS. The recipient verifies the signature on their own, without asking anybody.
DMARC answers “what should I do when the first two fail”. It is your instruction to the entire internet: let it through anyway, send it to spam, or reject it outright. As a bonus, DMARC asks recipients to send you reports on who is sending from your domain.
One detail catches most people out. DMARC does not only check whether SPF or DKIM passed. It also checks that the signing domain matches the domain your recipient sees in the From field. You can have a valid SPF record and still fail DMARC if the message goes out under somebody else’s technical domain. That is why an SMTP plugin on its own is sometimes not enough.
What Gmail expects from a sender today
It helps to know where the bar sits before you type anything. Under the Google sender guidelines, anyone sending to Gmail addresses needs SPF or DKIM in place, a valid PTR record for the sending IP, a TLS connection for delivery, and a spam rate below 0.3 percent as measured in Postmaster Tools.
Bulk senders, meaning anyone sending more than five thousand messages a day to Gmail addresses, face stricter rules in that same documentation: SPF and DKIM together, plus DMARC, plus alignment between the From domain and the signing domain, plus one-click unsubscribe on marketing mail. The rules have applied since February 2024, and the other large mailbox providers have moved the same way.
A small company rarely reaches the bulk sender threshold, but the setup below is complete anyway - with only three records to write, there is no point doing half the job.
Step by step: the DNS records for your company mailbox
Start with the mailbox, because that is the channel carrying your quotes and invoices. Every example below uses yourcompany.com - substitute your own and do not copy values blind.
Step 1. See what you already have. In whichever panel holds your DNS (registrar, hosting, or Cloudflare), open the record list and look for TXT entries. You want the one starting with v=spf1 and the one on the _dmarc name. Write down their current contents. If an SPF record already exists, you will be editing it, not adding a second one.
Step 2. SPF. One TXT record on the root of the domain. For mail in Google Workspace it looks like this:
v=spf1 include:_spf.google.com ~all
If your hosting server sends as well, you add it to the same record rather than creating a second one:
v=spf1 include:_spf.google.com include:_spf.yourhost.com ~all
Two rules that prevent the most common failures. A domain may carry exactly one SPF record - two means an error, and the recipient treats both as invalid. And leave ~all (soft fail) at the end until you are certain you have listed every server that actually sends. A hard -all is better in the long run, but it assumes you forgot nothing.
Step 3. DKIM. You do not invent this record, your mail provider gives it to you. In Google Workspace you go to the admin console, then Apps, then Google Workspace, then Gmail, and pick “Authenticate email”. Per the Google Workspace documentation, the default key prefix is google and the recommended length is 2048 bits, provided your DNS host supports it. The console generates the key and shows you a TXT record ready to paste:
google._domainkey.yourcompany.com TXT v=DKIM1; k=rsa; p=MIIBIjANBgkq...
Once the record is in, return to the console and click “Start authentication”. This step is easy to miss: the DNS record alone turns nothing on until the provider starts signing.
Step 4. DMARC. One TXT record on the _dmarc name. Begin in observation mode so you can see your traffic before you start rejecting anything. A DMARC record to start with:
_dmarc.yourcompany.com TXT v=DMARC1; p=none; rua=mailto:dmarc@yourcompany.com
p=none means “block nothing, just report to me”. rua is the address where aggregate reports arrive. After a few weeks, once the reports confirm every one of your sending channels passes, you tighten the policy to p=quarantine and eventually to p=reject. That order is not caution for its own sake: setting p=reject straight away on an incomplete SPF record deletes your own invoices in flight.
Allow a day for changes to spread. TXT records usually appear within minutes, but old values can sit in recipients’ caches considerably longer.
DKIM on WordPress and WooCommerce, the second sending channel
Here is the part the mail providers’ own guides leave out. Your website and your store are a separate sender, even when the address in the From field is identical. Contact form replies, order confirmations and password resets leave from the hosting server, not from the mailbox in Workspace.
By default WordPress sends through wp_mail(), which uses the server’s local mail, unsigned and unauthenticated. A message like that has no way to pass DKIM, and under any DMARC policy stricter than none it simply disappears.
The correct order is this:
- Route sending through a real mailbox over SMTP. The site then sends as an authenticated sender and inherits your provider’s DKIM signature, which is what gives its messages any chance of passing DMARC. Configuring the plugin itself, matching the addresses and working around mailbox limits are covered in the store diagnosis piece, so I will not repeat them here.
- Once the volume outgrows the mailbox, move to a dedicated transactional sending service - and in the same pass add its
include:to SPF and its own DKIM record, usually on a prefix other thangoogle.
That last point is the most common source of “I set everything up and it still does not arrive”. Somebody adds a sending service, forgets to list it in SPF, and the store keeps sending as a sender its own domain will not vouch for.
How to verify it works, and how to read DMARC reports
I check in this order every time, and only call it done after the third step.
Headers of a single message first. Send one mail from your site and one from your mailbox to a Gmail address. In Gmail, open the message menu and pick “Show original”. You will see three lines, SPF, DKIM and DMARC, each with a result. Check both messages, because they travel two different channels and very often one passes while the other does not.
Then an external validator. You enter the domain and get a syntax review of all three records. This catches what a single message will not show you: two SPF records at once, too many include: lookups, a typo in the DKIM key.
DMARC reports last. XML files start arriving at the address in your rua field, one a day from each larger provider. Raw XML is unreadable for a human, so either drop it into a free report viewer or point rua at a service that turns it into a table.
Look for three things in a report. First, the list of IP addresses sending as your domain - only your own channels belong there, and anything unfamiliar is either a forgotten service or somebody impersonating your company. Second, the SPF and DKIM result columns, where a correct setup steadily raises the share of messages passing both. Third, the counts on the failing rows: if they have sat at zero for two or three weeks, you can safely tighten the policy.
As long as the reports show traffic you cannot account for, leave p=none alone. That is the one rule in this article worth taking literally.
What I do differently - site and store mail through a dedicated sender
For clients whose site mail actually matters to sales, I split the channels from the start. Human correspondence stays where it is, and the site and store get their own transactional sending provider, with their own DKIM key and their own SPF entry.
Three reasons, all from practice. Limits: a mailbox is not built to push two hundred confirmations a day and will stall mid-afternoon when sales spike. Visibility: a separate channel has its own log, so “did the customer get the invoice” takes a minute instead of guesswork. And risk: when a form gets buried under fake orders and spam, the reputation damage lands on the sending account rather than on the mailbox you quote from.
Three DNS records are not a set-and-forget job either. Providers change their include: values, DKIM keys get rotated, and every new system that sends on the company’s behalf means another SPF update. For clients on ongoing care I review these records and the DMARC reports on a schedule, alongside backups and updates - precisely because this is the kind of failure nobody notices on the day it happens.
Impersonation, and where my role ends
A correct DMARC policy has one more effect that rarely comes up during setup: it makes it considerably harder to send fake invoices and payment requests in your company’s name. Under p=reject, a message impersonating your domain is refused before anyone sees it.
It is not complete protection, because it does nothing about lookalike addresses registered on a different domain. And it is not legal advice. Liability for the consequences of impersonation, your obligations towards personal data sitting in a mailbox, and what has to be reported to the authorities after an incident are all questions for a lawyer - I am answerable for the records being correct, not for the legal classification of an incident.
Frequently asked questions
Do I need all three, or is SPF enough? The minimum Gmail asks of an ordinary sender is SPF or DKIM. In practice SPF alone breaks down as soon as a message is forwarded, because the sending server changes, while a DKIM signature survives forwarding intact. DMARC added on top turns the other two into real protection and gives you reports. If you are doing this once, do all three.
My mail is on shared hosting, not Google Workspace. What changes?
Only the values. In SPF you use your host’s include: instead of _spf.google.com, and you generate the DKIM record in the hosting panel, usually filed under “DKIM signature” or “mail authentication”. The key prefix is often something other than google - use whatever the panel gives you. The DMARC record is identical regardless of provider.
I set it all up and store mail still goes to spam. Where do I look? Almost always at the channel somebody forgot. Open the headers of a message from the store, not from your mailbox, and check which domain appears on the DKIM signature. If it belongs to the hosting or a plugin rather than to you, the message fails DMARC alignment despite correct records. The fix is SMTP sending or a dedicated transactional service.
How long between p=none and p=reject?
Until the reports show no traffic from unknown sources for two consecutive weeks. In calendar terms that is usually a month, longer for a company running several sending systems. The intermediate p=quarantine step is worth taking, because it sends suspect mail to spam rather than deleting it, leaving you a chance to spot a mistake.
Can changing these records block my normal email?
Yes, and the risk is real, which is why the order in this article is what it is. A broken SPF record with -all, or p=reject over an incomplete sender list, will also stop the mail you send by hand from Outlook. That is why you start at ~all and p=none and tighten only on the evidence in your reports.
Would rather not watch over it every month yourself? I take sites and stores under ongoing care - backups, updates, monitoring, and priority when something breaks. Tell me what you run and I will send back scope and price.