If you ask people who run websites for a living what gives them the most grief, many will say email. A website either loads or it does not. Email can appear to work perfectly from your side while your messages vanish into someone's junk folder, and nobody tells you. The mail leaves, the log says "sent", and a customer waits three days for an invoice that is sitting in spam.
Part of the difficulty is age. Email predates almost everything else you use online, and its basic design assumed that every server on the network was run by someone trustworthy. Part of it is that the rules are now set by a few very large mailbox providers rather than by any standard, and they change them without a vote. And part of it is that the failure is silent: when a web page breaks, you see an error, but when a message is discarded, nothing appears anywhere.
This piece explains what receiving servers check, how the three DNS records fit together, what the small signals are that tip a borderline message one way or the other, and a sequence of steps that works for most small sites.
Sending is easy, being believed is hard
The mail system was designed back when the sender's claim about who they were was taken on trust. Anyone can still put any address in the From line, which is why so much spam works, and why a message that says it is from your bank proves nothing by itself. There are in fact two sender addresses on every message: the envelope sender (also called the Return-Path or MAIL FROM), which servers use between themselves for bounces, and the header From, which the recipient sees. Much of the confusion about mail authentication is confusion between these two.
Over the years the industry layered three checks on top, all of which live in your DNS.
- SPF is a list of the servers allowed to send mail for your domain. The receiving server compares the sender's IP address against it.
- DKIM adds a cryptographic signature to each message. Your DNS publishes the public key, so the receiver can verify the message was not altered and really came from a system you authorised.
- DMARC tells receivers what to do if SPF or DKIM fail to line up with the visible From domain, and where to send reports about it.
Since 2024, large mailbox providers such as Gmail and Yahoo have required these for anyone sending in volume (the published threshold is around five thousand messages a day to their users), together with easy unsubscribing for marketing mail and a low spam-complaint rate. The rules were aimed at bulk senders, but being without them has become noticeable even for small senders, because the same filters handle everyone. If your invoices or contact-form replies suddenly land in spam, check these three first. The SPF builder and the DMARC builder will produce correct records if you are starting from nothing.
SPF in practice
An SPF record is a single TXT record at the root of the domain. It lists the places mail may come from and says what to do with everything else.
example.com. 3600 IN TXT "v=spf1 ip4:203.0.113.25 include:_spf.example.net ~all"
Read left to right: this is SPF version 1; the server at 203.0.113.25 may send; whatever the provider behind _spf.example.net lists may send; and anything else is a soft fail. The ending matters. -all says "reject everything not listed", ~all says "treat it as suspicious", and ?all or +all say nothing useful or the opposite. ~all is the common choice because it is forgiving of mistakes, and with DMARC in place it carries enough weight.
Two rules cause most of the support tickets. A domain may have only one SPF record: two TXT records beginning with v=spf1 make the result an error, and the usual cause is that two different people added a service independently. And SPF checks the envelope sender, not the From line you can see, so a message sent through a third party that uses its own bounce domain can pass SPF while still failing DMARC alignment.
DKIM, the signature
With DKIM, the sending system holds a private key and signs selected headers and the body of each message. The signature is added as a header that names the signing domain (d=) and the selector (s=). The receiver looks up the public key in DNS at selector._domainkey.domain and checks the signature.
mail1._domainkey.example.com. 3600 IN TXT "v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA..."
Selectors let you run several keys at once, one per sending service, and rotate them without a gap. Use 2048-bit keys where your DNS host accepts the long record; some web interfaces need the value split into quoted chunks of up to 255 characters, which is normal and not an error. A signature survives forwarding if nobody alters the signed parts, which makes DKIM the more resilient of the two older checks. A mailing list that adds a footer breaks it.
The important detail is whose domain signs. A message from your domain that is signed by d=mailer.example.net proves the mailer sent it, not that you authorised it. For DMARC purposes the signing domain must match your From domain, which is why every serious sending service offers a way to add your own DKIM record, often a pair of CNAMEs.
DMARC, and why alignment is the point
DMARC ties the others to the visible From address. A message passes DMARC if SPF or DKIM passes and the domain that passed matches the From domain (alignment). The record sits at _dmarc:
_dmarc.example.com. 3600 IN TXT "v=DMARC1; p=none; rua=mailto:[email protected]; adkim=r; aspf=r"
The p tag is the policy: none (report only), quarantine (send failures to spam) or reject (refuse them). The rua address receives daily XML summaries from the big providers, showing every IP that sent mail claiming to be your domain, and whether it passed. These reports are why you start at none: they tell you about the forgotten server, the old CRM and the printer that emails scans before you start blocking things.
The little things that count
Receiving servers also look at reverse DNS (does the sending IP resolve to a believable name, and does that name resolve back to the same IP?), at whether the IP address appears on any blocklists, at how many recipients have marked your earlier messages as spam, and at the content itself: shortened links, image-only messages, mismatched link text and a long list of spammy phrases all count against you. Encrypted delivery (TLS) is expected now, and a server that cannot offer it looks old.
A brand-new IP address with no history is treated cautiously, which is why a new server that suddenly sends five thousand messages tends to be refused. Reputation is earned by volume that grows steadily and by recipients who open rather than complain. Senders who move to a new IP deliberately warm it up: a few hundred messages a day to their most engaged recipients, doubling every few days, as an illustration of the shape rather than a rule.
Reputation attaches to domains as well as IPs. A domain registered last week that starts sending newsletters has no history either, and spammers' habit of using fresh domains means that new ones start under suspicion. Send ordinary mail from a new domain for a while before the first bulk campaign.
Shared hosting adds a wrinkle
The IP address that sends your mail is shared with other customers on shared hosting. A good host watches outbound traffic and removes abusers quickly, rate-limits scripts that try to send thousands of messages, and monitors blocklists. A careless one does not, and you inherit the reputation. The symptom is mail that worked for a year and then began bouncing with a blocklist message while you changed nothing at all.
| Where mail is sent from | Reputation | Your responsibility |
|---|---|---|
| Shared hosting, built-in mail | Shared with neighbours; depends on the host's policing | Publish SPF, DKIM, DMARC; keep volume modest |
| VPS or dedicated, your own mail server | Yours alone, but starts from nothing | Reverse DNS, blocklist monitoring, warm-up, patching, TLS |
| Managed mailbox provider | Large, actively managed IP pools | Add the provider's SPF include and DKIM records |
| Dedicated sending service for transactional or bulk mail | Pooled or dedicated IPs managed for you | Authenticate your domain with their records; keep lists clean |
Many hosts also block outbound port 25 from customer servers to limit abuse, so a VPS that cannot send directly is not broken. It is expected to use a relay on port 587 or 465.
SPF has a limit people trip over
An SPF record may trigger no more than ten DNS lookups when it is evaluated. Each include: for a service such as a newsletter tool, a CRM, a helpdesk and your own host adds one or more lookups, because the included record can itself include others. The mechanisms a, mx, exists, ptr and redirect count too; plain ip4: and ip6: entries do not. Add enough services and the record silently breaks, returning a permanent error that many receivers treat as a failure.
The sign of this problem is intermittent: some receivers are lenient, so mail passes at one provider and fails at another. If you use many senders, an SPF flattening service or consolidating tools is worth considering. Flattening replaces includes with raw IP lists, which works until a provider changes its addresses and your copy goes stale, so use a service that refreshes automatically or accept a recurring maintenance job. Often the better answer is to stop using SPF alignment for third parties at all and rely on their DKIM signing, which does not use lookups against your record.
A worked example: the invoices that went to spam
A small design studio sends invoices from its accounting package, replies to clients from its mailbox provider, and sends a monthly newsletter from a third tool. In March, three clients say the invoices are in their junk folders. The studio's first guess is that the accounting package has a problem. The package's support says the messages leave fine.
Opening the full source of a test invoice sent to a free webmail account shows spf=pass for the accounting package's own bounce domain, dkim=none, and dmarc=fail. The package sends with its own domain in the envelope, so SPF passes, but that domain does not match the studio's From address, so it does not count for DMARC. There is no DKIM signature for the studio's domain at all. The studio had published DMARC with p=quarantine a year earlier on the advice of a checklist, without ever reading a report, and the policy had been waiting to bite.
The fix takes an afternoon: add the package's two DKIM CNAME records to the studio's DNS, wait for them to verify in the package settings, send a new test, and see dkim=pass header.d=example.com and dmarc=pass. The studio also drops the policy back to p=none while it reads a fortnight of reports, finds the forgotten newsletter tool still unsigned, and fixes that as well. Nothing was wrong with any single service; the gap was the record that connected them.
Receiving mail is a separate problem
Everything above is about sending, but the other half of email has its own failure modes. Incoming mail finds your domain through its MX records, which name the servers that accept mail for it. Those servers might be at your web host, at a mailbox provider or at a filtering service in front of one. If the MX records point to the wrong place, mail arrives somewhere nobody looks, or nowhere at all, and the sender gets a bounce several hours later.
example.com. 3600 IN MX 10 mail.example.com.
example.com. 3600 IN MX 20 mail2.example.com.
The lower number is preferred; the higher one is a backup. Do not add a second MX for a provider you are not actually using, because senders will sometimes pick it and the message will be lost. Moving a website to a new host, or changing nameservers, silently takes mail with it unless the MX records are copied across, so check them whenever DNS moves, as covered in the piece on domain transfers in this series. Mailbox quotas matter too: a full mailbox rejects new messages with a 5xx code, and a catch-all address that collects thousands of spam messages fills one fast.
Forwarding, lists and bounces
Forwarding breaks SPF by design. When a mailbox at one provider forwards to another, the forwarding server's IP is not in the original sender's SPF record, so the check fails at the final destination. DKIM usually survives because the signed content is unchanged, which is another reason to have both. Mailing lists that alter subjects or footers can break DKIM too, and modern forwarders add measures such as sender rewriting and ARC to preserve the authentication history. You cannot fix these from your side, but a DMARC policy of p=reject makes the consequences sharper, which is one reason to arrive there gradually.
Read bounce messages instead of deleting them. They arrive from the receiving server and often contain the reason in plain text: the IP is blocklisted, the recipient does not exist, the mailbox is full, or the message failed authentication. A code beginning with 4 means a temporary problem and the sending server will retry for a few days; one beginning with 5 is final. A mailbox that bounces once is usually a typo, but one that bounces repeatedly should be removed from your lists, because continuing to send to dead addresses is a reputation problem of your own making.
A practical approach
Pick one place to send transactional mail (receipts, password resets, contact-form replies), preferably through an authenticated SMTP connection rather than the web server's built-in mail function. The built-in function sends from whatever the server is, with no authentication and no useful log; an SMTP plugin that logs in to a real mailbox or sending service fixes both.
- List every system that sends mail as your domain: the website, the mailbox provider, newsletter and CRM tools, invoicing, helpdesk, monitoring.
- Publish one SPF record that covers those systems, and keep it under the lookup limit.
- Turn on DKIM signing for each system, with your domain as the signer.
- Publish DMARC with
p=noneand aruaaddress you actually read, or a reporting service that digests the XML. - Read the reports for a few weeks, fix whatever shows up, and then tighten the policy to quarantine, then reject.
It takes patience, but it is the difference between email that works and email that mostly works. Keep marketing and transactional mail on separate subdomains or services if you can, so that a bad campaign cannot drag the password-reset emails into spam with it.
news.example.com and system mail from example.com keeps their reputations apart. Each subdomain needs its own SPF and DKIM records, and inherits the parent DMARC policy unless you set one.Try it on your own site
Start with what DNS says:
dig TXT example.com +short | grep spf1
dig TXT mail1._domainkey.example.com +short
dig TXT _dmarc.example.com +short
dig -x 203.0.113.25 +short
Expect exactly one SPF line, a key for each selector in use, a DMARC record beginning v=DMARC1, and a reverse lookup that returns a name belonging to your sender. Then test a real message. Send one to a mailbox you control at a large provider, open the full message source (usually "show original"), and read the authentication results header. You want to see spf=pass, dkim=pass and dmarc=pass, each naming your domain.
Authentication-Results: mx.example.net;
spf=pass smtp.mailfrom=example.com;
dkim=pass header.d=example.com header.s=mail1;
dmarc=pass header.from=example.com
If one says fail or none, that is the lead to follow. Also look at the first Received header, which shows the IP that really sent the message; it is often not the one you expected. For anything else that is wrong with delivery, the troubleshooting guide has a longer checklist, and the DNS cheat sheet covers the record types used above.