{"id":61,"date":"2026-09-02T16:25:43","date_gmt":"2026-09-02T16:25:43","guid":{"rendered":"https:\/\/www.tkwebhosts.com\/blog\/how-to-configure-spf-dkim-dmarc\/"},"modified":"2026-09-02T16:52:20","modified_gmt":"2026-09-02T16:52:20","slug":"how-to-configure-spf-dkim-dmarc","status":"publish","type":"post","link":"https:\/\/www.tkwebhosts.com\/blog\/how-to-configure-spf-dkim-dmarc\/","title":{"rendered":"How to Configure SPF, DKIM and DMARC for Email Deliverability"},"content":{"rendered":"<p class=\"article-byline\">By the <a href=\"https:\/\/www.tkwebhosts.com\/about\">TK WebHosts Web Team<\/a> \u00b7 Last reviewed 2 September 2026<\/p>\n<p>Email was designed without any way of proving who sent a message. Nothing in the original protocol stops a server anywhere on the internet from sending mail that claims to come from any domain it likes. Every anti-spoofing mechanism in use today is a layer added afterwards, and all three of the important ones are published the same way: as DNS records on the domain being protected.<\/p>\n<p>That is the practical point. SPF, DKIM and DMARC are not settings inside a mail client or features of a mail provider. They are public statements, made in DNS, about who is allowed to send as a domain and what should happen to anything that fails the test. Configuring them means editing a DNS zone, and getting them wrong means either that spoofing stays possible or that legitimate mail starts disappearing.<\/p>\n<p>Since February 2024, this stopped being optional for anyone sending at volume. Google and Yahoo both began requiring bulk senders \u2014 those sending more than 5,000 messages a day to their users \u2014 to publish SPF, DKIM <strong>and<\/strong> a DMARC policy, with the From: header aligned to one of the authenticated domains. Microsoft applied comparable requirements to Outlook.com addresses from May 2025. Domains that do not authenticate now get rejected or filtered by the largest mailbox providers on the internet as a matter of published policy.<\/p>\n<p>What follows is what each record proves, the exact syntax, where each one goes, and the order to roll them out in without breaking anything.<\/p>\n<p>If the underlying DNS concepts are unfamiliar, <a href=\"https:\/\/www.tkwebhosts.com\/blog\/what-is-dns-and-how-dns-records-work\/\" target=\"_blank\" rel=\"noopener\">what a DNS record is and how one works<\/a> covers the foundation this article assumes.<\/p>\n<h2>The three records answer three different questions<\/h2>\n<p>They are routinely discussed as a set, which obscures the fact that each proves something the other two cannot.<\/p>\n<div class=\"table-wrap\">\n<table>\n<thead>\n<tr>\n<th>Record<\/th>\n<th>The question it answers<\/th>\n<th>Where it is published<\/th>\n<th>Survives forwarding<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td><strong>SPF<\/strong><\/td>\n<td>Is the server that sent this authorised to send for this domain?<\/td>\n<td>TXT at the domain root<\/td>\n<td>No<\/td>\n<\/tr>\n<tr>\n<td><strong>DKIM<\/strong><\/td>\n<td>Was this message actually signed by the domain, and unaltered since?<\/td>\n<td>TXT or CNAME at <code>&lt;selector&gt;._domainkey.&lt;domain&gt;<\/code><\/td>\n<td>Usually<\/td>\n<\/tr>\n<tr>\n<td><strong>DMARC<\/strong><\/td>\n<td>What should a receiver do when the first two fail, and who should be told?<\/td>\n<td>TXT at <code>_dmarc.&lt;domain&gt;<\/code><\/td>\n<td>Not applicable \u2014 it is policy<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<p>DMARC is the one that has teeth, but it is worthless on its own: it is an instruction about the results of SPF and DKIM, so it has nothing to act on until both exist.<\/p>\n<h2>Before touching DNS: the sending inventory<\/h2>\n<p>The single largest cause of authentication going wrong is not syntax. It is publishing a policy before knowing everything that sends mail as the domain.<\/p>\n<p>Most organisations send from more places than they think. A typical list runs to five or six: the mailbox provider, a marketing platform, an invoicing or accounting system, a helpdesk, a website&#8217;s contact form, and a CRM. Each has its own sending servers, and every one of them has to be authorised before any enforcing policy goes live.<\/p>\n<p>Write the list down first. Everything below depends on it being complete.<\/p>\n<h2>SPF: authorising the servers that may send<\/h2>\n<p>SPF \u2014 <strong>Sender Policy Framework<\/strong> \u2014 publishes a list of the servers permitted to send mail for a domain. A receiving server compares the connecting server against that list and gets a pass, a fail, or something in between.<\/p>\n<h3>The record<\/h3>\n<p>SPF is a TXT record published at the <strong>root of the domain<\/strong> \u2014 the name shown as <code>@<\/code> in most control panels. A minimal one:<\/p>\n<p><code>v=spf1 include:_spf.google.com -all<\/code><\/p>\n<p>Read left to right: SPF version 1, authorise everything Google&#8217;s <code>_spf.google.com<\/code> record authorises, fail everything else.<\/p>\n<p>A record covering several senders:<\/p>\n<p><code>v=spf1 ip4:203.0.113.10 include:_spf.google.com include:mail.provider.net -all<\/code><\/p>\n<h3>The parts<\/h3>\n<div class=\"table-wrap\">\n<table>\n<thead>\n<tr>\n<th>Term<\/th>\n<th>Meaning<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td><code>v=spf1<\/code><\/td>\n<td>Version. Required, and must come first<\/td>\n<\/tr>\n<tr>\n<td><code>ip4:<\/code> \/ <code>ip6:<\/code><\/td>\n<td>Authorise a specific address or CIDR range<\/td>\n<\/tr>\n<tr>\n<td><code>include:<\/code><\/td>\n<td>Authorise everything another domain&#8217;s SPF record authorises<\/td>\n<\/tr>\n<tr>\n<td><code>a<\/code><\/td>\n<td>Authorise the domain&#8217;s own A record address<\/td>\n<\/tr>\n<tr>\n<td><code>mx<\/code><\/td>\n<td>Authorise the servers listed in the domain&#8217;s MX records<\/td>\n<\/tr>\n<tr>\n<td><code>-all<\/code><\/td>\n<td>Fail everything not matched above<\/td>\n<\/tr>\n<tr>\n<td><code>~all<\/code><\/td>\n<td>Soft fail \u2014 treat as suspicious but do not reject<\/td>\n<\/tr>\n<tr>\n<td><code>?all<\/code><\/td>\n<td>Neutral \u2014 no assertion at all<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<h3>Four rules that decide whether it works<\/h3>\n<p><strong>One SPF record per domain, without exception.<\/strong> Two TXT records both beginning <code>v=spf1<\/code> do not combine. They produce a permanent error, and the practical result is that SPF fails altogether. Adding a sender means editing the existing record, never adding a second one. This is the most common SPF fault in the wild.<\/p>\n<p><strong>Ten DNS lookups, maximum.<\/strong> The <code>include<\/code>, <code>a<\/code>, <code>mx<\/code>, <code>ptr<\/code>, <code>exists<\/code> and <code>redirect<\/code> terms each cost a DNS lookup, and nested includes count too \u2014 a single <code>include:<\/code> of a provider that itself includes three others spends four. Exceed ten and the result is a permanent error and a failed check, no matter how correct the record looks. <code>ip4:<\/code>, <code>ip6:<\/code> and <code>all<\/code> cost nothing, which is why replacing an include with the explicit ranges it resolves to \u2014 flattening \u2014 is the standard remedy. The trade-off is real: flattened records go stale silently when a provider changes its infrastructure. The specification also asks that no more than two lookups return nothing at all, so includes pointing at records that no longer exist are a liability of their own.<\/p>\n<p><strong>SPF checks the envelope, not the visible From: address.<\/strong> The check runs against the <code>MAIL FROM<\/code> address \u2014 the Return-Path \u2014 which is the address bounces return to, and which is frequently the sending platform&#8217;s domain rather than the visible one. A marketing platform can therefore pass SPF perfectly while the recipient sees a completely different domain in the From: field. This gap is precisely what DMARC alignment exists to close, and it is why SPF alone has never been sufficient.<\/p>\n<p><strong>SPF does not survive forwarding.<\/strong> When a recipient auto-forwards a message, the forwarding server becomes the sender, and it is almost certainly not on the original domain&#8217;s authorised list. SPF fails on the forwarded copy through no fault of the configuration. This is not a defect to fix \u2014 it is the structural reason DKIM is needed as well.<\/p>\n<h3>Choosing the closing mechanism<\/h3>\n<p><code>-all<\/code> is the correct end state. It is also the mechanism that rejects legitimate mail from any sender omitted from the inventory.<\/p>\n<p>The safe order is to publish with <code>~all<\/code> while confirming from real report data that every legitimate source passes, then tighten to <code>-all<\/code> once the list is provably complete. Starting at <code>-all<\/code> on an incomplete inventory produces exactly the outcome the exercise was meant to prevent, and the mail lost in the meantime is rarely noticed until someone asks why an invoice never arrived.<\/p>\n<h2>DKIM: signing the message itself<\/h2>\n<p>DKIM \u2014 <strong>DomainKeys Identified Mail<\/strong> \u2014 takes a different approach. Rather than describing which servers may send, it proves the domain actually signed a specific message and that the signed parts have not been altered since.<\/p>\n<p>It works on a key pair. The private key sits on the sending mail server and signs a hash of the message body and a selected set of headers. The matching public key is published in DNS. A receiving server reads the signature, fetches the public key, and verifies the two agree.<\/p>\n<h3>The record<\/h3>\n<p>DKIM is published at a name built from a <strong>selector<\/strong>:<\/p>\n<p><code>&lt;selector&gt;._domainkey.&lt;domain&gt;<\/code><\/p>\n<p>For a selector of <code>s1<\/code> on <code>example.com<\/code>, the record name is <code>s1._domainkey.example.com<\/code>. The selector is chosen by the sending provider and appears inside every signature it generates, which is how a receiver knows which key to fetch.<\/p>\n<p>The value, published as TXT:<\/p>\n<p><code>v=DKIM1; k=rsa; p=MIIBIjANBgkqhkiG9w0BAQEFA...<\/code><\/p>\n<p>Selectors are the reason multiple providers can sign for one domain at the same time. A mailbox provider on <code>google._domainkey<\/code> and a marketing platform on <code>mktg._domainkey<\/code> coexist without conflict, each holding its own key.<\/p>\n<h3>CNAME is usually the better option<\/h3>\n<p>Many providers publish DKIM as a <strong>CNAME<\/strong> pointing at a key they host, rather than a TXT record holding the key itself:<\/p>\n<p><code>s1._domainkey.example.com<\/code> \u2192 <code>s1.dkim.provider.net<\/code><\/p>\n<p>This is worth accepting whenever it is offered. It lets the provider rotate the underlying key without anyone editing DNS, which in practice means the key actually gets rotated rather than sitting untouched for years.<\/p>\n<h3>Key length and the 255-character trap<\/h3>\n<p>Use <strong>2048-bit<\/strong> keys. The specification sets 1024 as the floor and 2048 as the recommendation, and 1024-bit keys are increasingly treated as weak.<\/p>\n<p>A 2048-bit public key does not fit in a single DNS string, because a TXT record is limited to 255 characters per string. Longer values are published as several quoted strings that resolvers join back together. Most control panels handle the split automatically; some do not, and a record split at the wrong point resolves to a key that looks present in the panel and fails every verification. If DKIM fails immediately after publishing a 2048-bit key, this is the first thing to check.<\/p>\n<h3>What breaks a valid signature<\/h3>\n<p>DKIM survives ordinary forwarding, which is its main advantage over SPF. It does not survive modification of the signed content. A mailing list that appends a footer or prefixes the subject line invalidates the signature it passes through, which is why discussion lists routinely break authentication for perfectly legitimate messages.<\/p>\n<h2>DMARC: the policy that ties the two together<\/h2>\n<p>DMARC \u2014 <strong>Domain-based Message Authentication, Reporting and Conformance<\/strong> \u2014 is a DNS record like the others, but its payload is a policy rather than an address. Instead of describing infrastructure, it instructs receiving providers what to do with mail claiming to be from the domain that fails the checks, and asks them to report back on what they saw.<\/p>\n<h3>Where it goes<\/h3>\n<p><strong>A DMARC record is published at <code>_dmarc.&lt;domain&gt;<\/code>, not at the domain root.<\/strong> For <code>example.com<\/code> the record name is <code>_dmarc.example.com<\/code>.<\/p>\n<p>This is the single most common DMARC configuration failure. Published at the root, the record is syntactically valid, visible in the control panel, and completely inert, because nothing ever queries that name for a policy.<\/p>\n<h3>The record<\/h3>\n<p>A starting policy:<\/p>\n<p><code>v=DMARC1; p=none; rua=mailto:dmarc@example.com;<\/code><\/p>\n<p>An enforcing one:<\/p>\n<p><code>v=DMARC1; p=reject; sp=reject; adkim=s; aspf=s; rua=mailto:dmarc@example.com;<\/code><\/p>\n<h3>The tags<\/h3>\n<div class=\"table-wrap\">\n<table>\n<thead>\n<tr>\n<th>Tag<\/th>\n<th>Purpose<\/th>\n<th>Notes<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td><code>v=DMARC1<\/code><\/td>\n<td>Version<\/td>\n<td>Required, must be first<\/td>\n<\/tr>\n<tr>\n<td><code>p=<\/code><\/td>\n<td>Policy for the domain<\/td>\n<td>Required, must be second. <code>none<\/code>, <code>quarantine<\/code> or <code>reject<\/code><\/td>\n<\/tr>\n<tr>\n<td><code>sp=<\/code><\/td>\n<td>Policy for subdomains<\/td>\n<td>Defaults to the value of <code>p=<\/code> if omitted<\/td>\n<\/tr>\n<tr>\n<td><code>rua=<\/code><\/td>\n<td>Where to send aggregate reports<\/td>\n<td>The tag that makes DMARC useful<\/td>\n<\/tr>\n<tr>\n<td><code>ruf=<\/code><\/td>\n<td>Where to send failure reports<\/td>\n<td>Largely vestigial \u2014 see below<\/td>\n<\/tr>\n<tr>\n<td><code>adkim=<\/code><\/td>\n<td>DKIM alignment mode<\/td>\n<td><code>r<\/code> relaxed (default) or <code>s<\/code> strict<\/td>\n<\/tr>\n<tr>\n<td><code>aspf=<\/code><\/td>\n<td>SPF alignment mode<\/td>\n<td><code>r<\/code> relaxed (default) or <code>s<\/code> strict<\/td>\n<\/tr>\n<tr>\n<td><code>pct=<\/code><\/td>\n<td>Percentage of failing mail the policy applies to<\/td>\n<td>Being removed from the specification<\/td>\n<\/tr>\n<tr>\n<td><code>ri=<\/code><\/td>\n<td>Aggregate report interval, in seconds<\/td>\n<td>Defaults to 86400. Most receivers send daily regardless<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<h3>The three policies<\/h3>\n<p><strong><code>p=none<\/code><\/strong> \u2014 take no action on failures, but send reports. Nothing changes about how mail is treated; the value is entirely in the visibility. This is where every deployment starts.<\/p>\n<p><code>v=DMARC1; p=none; rua=mailto:dmarc@example.com;<\/code><\/p>\n<p><strong><code>p=quarantine<\/code><\/strong> \u2014 treat failing mail as suspicious, in practice by filing it in the junk folder.<\/p>\n<p><code>v=DMARC1; p=quarantine; rua=mailto:dmarc@example.com;<\/code><\/p>\n<p><strong><code>p=reject<\/code><\/strong> \u2014 refuse failing mail outright, at the point of delivery. This is the end state, and the only policy that actually stops a domain being spoofed.<\/p>\n<p><code>v=DMARC1; p=reject; rua=mailto:dmarc@example.com;<\/code><\/p>\n<h3>Alignment is the part that matters<\/h3>\n<p>DMARC does not simply ask whether SPF or DKIM passed. It asks whether the domain that passed is <strong>the same domain the recipient sees in the From: field<\/strong>. That is alignment, and it is the concept that makes the whole mechanism coherent.<\/p>\n<p>A message passes DMARC if <strong>either<\/strong> of these is true:<\/p>\n<ol>\n<li>SPF passes <strong>and<\/strong> the Return-Path domain aligns with the From: domain<\/li>\n<li>DKIM passes <strong>and<\/strong> the signing domain in the signature aligns with the From: domain<\/li>\n<\/ol>\n<p>Only one is needed. This is deliberate: it means a forwarded message that fails SPF can still pass DMARC on its intact DKIM signature.<\/p>\n<p>Alignment has two modes. <strong>Relaxed<\/strong> \u2014 the default \u2014 requires only that the organisational domains match, so a Return-Path of <code>bounce.example.com<\/code> aligns with a From: of <code>example.com<\/code>. <strong>Strict<\/strong> requires an exact match, and rejects that same pair.<\/p>\n<p>The practical consequence is the one that catches people out. A marketing platform sending with its own Return-Path passes SPF against <em>its<\/em> domain, not the customer&#8217;s. SPF is green, DMARC still fails, and the message is treated as unauthenticated. The fix is either a custom Return-Path on the sending domain, or a properly configured DKIM signature with <code>d=example.com<\/code>. This is why &#8220;SPF is passing, so why is DMARC failing?&#8221; is such a common question, and why the answer is almost always alignment.<\/p>\n<h3>The reporting tags, honestly<\/h3>\n<p><code>rua=<\/code> is the reason to deploy DMARC at all before enforcing anything. It asks every participating receiver to send a daily XML summary of the mail they saw claiming to be from the domain, and how it authenticated. That data is what turns the sending inventory from a guess into a fact, and it is the only reliable way to discover the forgotten invoicing system before a policy starts rejecting it.<\/p>\n<p><code>ruf=<\/code> \u2014 failure reports, sometimes called forensic reports \u2014 asks for a copy of individual failing messages. It should be understood as largely dead. Google, Microsoft and Yahoo do not send them, primarily for privacy reasons, since the reports contain recipient data. A record can carry <code>ruf=<\/code> harmlessly, but it should not be relied on for anything, and a deployment plan that depends on failure reports is a plan built on data that will not arrive.<\/p>\n<p>One detail that quietly breaks reporting: if the <code>rua<\/code> address is on a <strong>different domain<\/strong> from the one being reported on, that other domain must authorise it by publishing a TXT record at <code>&lt;reporteddomain&gt;._report._dmarc.&lt;reportingdomain&gt;<\/code> containing <code>v=DMARC1<\/code>. Without it, conforming receivers refuse to send the reports. Anyone collecting reports for several domains into one mailbox needs this, and its absence looks identical to nobody reporting.<\/p>\n<h3>The <code>pct<\/code> tag, accurately<\/h3>\n<p><code>pct=<\/code> was designed to apply the policy to a sample of failing mail during a phased rollout. It is widely misdescribed, including in most explanations of it.<\/p>\n<p><code>v=DMARC1; p=reject; pct=60; rua=mailto:dmarc@example.com;<\/code><\/p>\n<p>This does <strong>not<\/strong> mean 60% of failing mail is rejected and 40% is delivered untouched. It means 60% is rejected and the remaining 40% falls back to the <strong>next lower policy<\/strong> \u2014 quarantine, in this case. With <code>p=quarantine; pct=60<\/code>, the other 40% falls back to none.<\/p>\n<p>Two further cautions. Receiver support was always uneven, so the actual split is not dependable. And the tag is being removed in the revision of the DMARC specification working through the IETF. Treat <code>pct<\/code> as legacy: the sound way to phase a rollout is to move the policy itself, deliberately, with report data justifying each step.<\/p>\n<h3>Do not forget subdomains<\/h3>\n<p>If <code>sp=<\/code> is omitted, subdomains inherit whatever <code>p=<\/code> says, which is usually correct. Setting <code>p=reject<\/code> without a matching <code>sp=<\/code> is fine; setting <code>p=none<\/code> leaves every subdomain unprotected, and non-existent subdomains are a favourite vector precisely because nobody monitors them. An explicit <code>sp=reject<\/code> on a domain still testing at <code>p=none<\/code> protects subdomains from day one at no risk to production mail, since nothing legitimate sends from them.<\/p>\n<h2>What MX records do, and do not do<\/h2>\n<p>MX records are frequently pulled into these conversations and do not belong to this part of the system at all.<\/p>\n<p>An MX record names the servers that accept mail <strong>sent to<\/strong> the domain. It carries a priority \u2014 a lower number meaning higher precedence \u2014 and it must point to a hostname with its own A or AAAA record, never to an IP address and never to a CNAME.<\/p>\n<div class=\"table-wrap\">\n<table>\n<thead>\n<tr>\n<th>Provider<\/th>\n<th>MX record<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>Google Workspace, current<\/td>\n<td><code>1 smtp.google.com<\/code><\/td>\n<\/tr>\n<tr>\n<td>Google Workspace, legacy set<\/td>\n<td><code>1 aspmx.l.google.com<\/code>, plus four <code>alt<\/code> records at priorities 5, 5, 10 and 10<\/td>\n<\/tr>\n<tr>\n<td>TK WebHosts mail<\/td>\n<td><code>10 pixel.tkwebhosts.com<\/code><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<p>Both Google forms are valid and in service; the single-record version simply replaced the five-record set for new configurations.<\/p>\n<p>The point to hold on to: <strong>MX is inbound only.<\/strong> It has no role in sending, and no role in SPF, DKIM or DMARC. Changing MX records does not affect whether outbound mail is authenticated, and does not fix mail landing in spam, because the MX record was never consulted on that journey.<\/p>\n<h2>The rollout order<\/h2>\n<p>Sequence matters more than any individual record. This order gives visibility before enforcement, which is what makes it safe.<\/p>\n<ol>\n<li><strong>Inventory every sender.<\/strong> Every system that sends mail as the domain. This is the step that gets skipped and the step that causes the damage.<\/li>\n<li><strong>Publish SPF with <code>~all<\/code>.<\/strong> One record, at the root, covering every authorised sender, inside the ten-lookup limit.<\/li>\n<li><strong>Enable DKIM on every sending platform.<\/strong> A distinct selector for each. Prefer the CNAME form where the provider offers it, and use 2048-bit keys.<\/li>\n<li><strong>Publish DMARC at <code>p=none<\/code> with <code>rua=<\/code>.<\/strong> Nothing changes for recipients. Reports begin arriving within a day or two.<\/li>\n<li><strong>Read the reports for at least two weeks.<\/strong> Longer for a business with monthly or quarterly sending cycles. The objective is a full picture of every source, authenticating or not.<\/li>\n<li><strong>Fix what the reports expose.<\/strong> Usually a forgotten sender, and usually an alignment failure on a platform that passes SPF against its own Return-Path.<\/li>\n<li><strong>Move to <code>p=quarantine<\/code>.<\/strong> Keep reading the reports.<\/li>\n<li><strong>Move to <code>p=reject<\/code>, and tighten SPF to <code>-all<\/code>.<\/strong> Only once the reports show every legitimate source authenticating and aligning.<\/li>\n<\/ol>\n<p>Steps 5 and 6 are the ones under time pressure, and they are the ones that cannot be compressed. Everything before them is reversible; everything after them affects real mail.<\/p>\n<h2>Common configuration mistakes<\/h2>\n<div class=\"table-wrap\">\n<table>\n<thead>\n<tr>\n<th>Mistake<\/th>\n<th>What actually happens<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr>\n<td>Two SPF records on one domain<\/td>\n<td>Permanent error. SPF fails entirely, rather than combining<\/td>\n<\/tr>\n<tr>\n<td>More than ten DNS lookups in SPF<\/td>\n<td>Permanent error. The record is correct and useless<\/td>\n<\/tr>\n<tr>\n<td>DMARC published at the root instead of <code>_dmarc<\/code><\/td>\n<td>Valid, visible, and never queried. No policy is in force<\/td>\n<\/tr>\n<tr>\n<td><code>-all<\/code> before the inventory is complete<\/td>\n<td>Legitimate mail rejected, usually noticed weeks later<\/td>\n<\/tr>\n<tr>\n<td>Straight to <code>p=reject<\/code> with no monitoring<\/td>\n<td>Mail lost with no report data to diagnose which source was missed<\/td>\n<\/tr>\n<tr>\n<td>Assuming an SPF pass satisfies DMARC<\/td>\n<td>It does not, unless the Return-Path aligns with the From: domain<\/td>\n<\/tr>\n<tr>\n<td><code>p=none<\/code> with no <code>sp=<\/code><\/td>\n<td>Every subdomain left open to spoofing<\/td>\n<\/tr>\n<tr>\n<td>A 2048-bit DKIM key split incorrectly<\/td>\n<td>Record present in the panel, verification fails every time<\/td>\n<\/tr>\n<tr>\n<td>Relying on <code>ruf=<\/code> for diagnostics<\/td>\n<td>The major receivers do not send failure reports<\/td>\n<\/tr>\n<tr>\n<td><code>rua=<\/code> on another domain with no <code>_report._dmarc<\/code> authorisation<\/td>\n<td>Conforming receivers silently decline to send reports<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/div>\n<h2>How to verify<\/h2>\n<p>Every record involved is publicly queryable, so verification costs nothing and should follow every change.<\/p>\n<ul>\n<li><code>dig +short TXT example.com<\/code> \u2014 the SPF record, among other TXT records<\/li>\n<li><code>dig +short TXT _dmarc.example.com<\/code> \u2014 the DMARC policy<\/li>\n<li><code>dig +short TXT s1._domainkey.example.com<\/code> \u2014 the DKIM public key for selector <code>s1<\/code><\/li>\n<li><code>dig +short MX example.com<\/code> \u2014 inbound mail servers and priorities<\/li>\n<\/ul>\n<p>Adding <code>@1.1.1.1<\/code> to any of these bypasses a local cache that may still be holding an old answer.<\/p>\n<p>The definitive test is a real message. Send one to an address at a major provider and read the <code>Authentication-Results<\/code> header on what arrives \u2014 it states the SPF, DKIM and DMARC verdicts as that provider computed them, including whether alignment held. That header is the ground truth; a control panel showing green ticks is not.<\/p>\n<h2>What authentication does not do<\/h2>\n<p>Worth stating plainly, because it is routinely oversold: <strong>correctly configured SPF, DKIM and DMARC do not guarantee that mail reaches the inbox.<\/strong><\/p>\n<p>Authentication establishes identity. It proves a message genuinely comes from the domain it claims, and it stops that domain being spoofed. What it cannot do is make a receiving provider want the mail. Placement is decided afterwards, on reputation \u2014 complaint rates, bounce rates, sending volume and consistency, list quality, and message content.<\/p>\n<p>Authentication is a prerequisite, not an outcome. Without it, mail from a domain sending at any volume is now filtered or rejected by the largest providers as published policy. With it, the domain has earned the right to be judged on its reputation instead of dismissed on its identity. Where mail is still going astray after authentication is sound, the causes are covered in <a href=\"https:\/\/www.tkwebhosts.com\/why-are-my-emails-going-to-spam\" target=\"_blank\" rel=\"noopener\">why emails go to spam<\/a>.<\/p>\n<h2>Frequently asked questions<\/h2>\n<h3>Where exactly does the DMARC record go?<\/h3>\n<p>At <code>_dmarc.&lt;domain&gt;<\/code> \u2014 so <code>_dmarc.example.com<\/code> for <code>example.com<\/code> \u2014 published as a TXT record. Putting it at the domain root instead is the most common DMARC mistake, because the record is syntactically valid and displays correctly in the control panel while never being queried, so no policy is actually in force.<\/p>\n<h3>Do I need all three records, or is one enough?<\/h3>\n<p>All three, and they are not interchangeable. SPF alone fails on any forwarded message and checks an address the recipient never sees; DKIM alone publishes no policy so nothing acts on a failure; DMARC alone has no results to act on. Since February 2024 Google and Yahoo have required bulk senders to publish all three with alignment, and Microsoft applied comparable requirements from May 2025.<\/p>\n<h3>Why is my SPF passing but DMARC still failing?<\/h3>\n<p>Almost certainly alignment. SPF is checked against the Return-Path address rather than the visible From: address, and sending platforms commonly use their own domain as the Return-Path \u2014 so SPF passes for the platform&#8217;s domain while the recipient sees yours, and DMARC treats that as unaligned. The fix is either a custom Return-Path on your own domain or a DKIM signature whose signing domain matches the From: domain.<\/p>\n<h3>How long should I stay at p=none before enforcing?<\/h3>\n<p>At least two weeks of aggregate report data, and longer for any business whose sending follows monthly or quarterly cycles \u2014 an annual invoicing run that nobody thought of will not appear in a fortnight of reports. The purpose of the waiting period is to see every legitimate sender at least once before a policy starts acting on failures, so the calendar that matters is the sending calendar, not a fixed number of days.<\/p>\n<h3>What is the SPF ten-lookup limit and how do I get under it?<\/h3>\n<p>SPF permits a maximum of ten DNS lookups when evaluating a record, counting <code>include<\/code>, <code>a<\/code>, <code>mx<\/code>, <code>ptr<\/code>, <code>exists<\/code> and <code>redirect<\/code> terms including everything nested inside them; exceeding it is a permanent error that makes SPF fail regardless of how correct the record looks. Getting under it usually means removing senders that no longer send, or replacing an <code>include<\/code> with the explicit <code>ip4<\/code> ranges it resolves to, which cost no lookups \u2014 at the price of the record going stale silently if that provider changes infrastructure.<\/p>\n<h3>Should I use ~all or -all at the end of my SPF record?<\/h3>\n<p>Finish on <code>-all<\/code>, but not until aggregate reports confirm every legitimate sender is authorised. <code>~all<\/code> is the correct setting while the inventory is still being proved, since it marks unauthorised mail as suspicious without rejecting it; <code>-all<\/code> published over an incomplete list rejects real mail, and the loss is typically discovered only when someone asks why a message never arrived.<\/p>\n<h3>Does changing my MX records fix email going to spam?<\/h3>\n<p>No. MX records govern mail arriving <em>at<\/em> the domain and play no part in sending or authentication, so they were never involved in the journey of a message that landed in someone else&#8217;s spam folder. Outbound placement is determined by SPF, DKIM, DMARC and sending reputation, none of which an MX record touches.<\/p>\n<h3>Can I use one DMARC report address for several domains?<\/h3>\n<p>Yes, but each reported domain must be authorised by the domain hosting the mailbox, which publishes a TXT record at <code>&lt;reporteddomain&gt;._report._dmarc.&lt;reportingdomain&gt;<\/code> containing <code>v=DMARC1<\/code>. Without that authorisation conforming receivers decline to send the reports, and the symptom is indistinguishable from no one reporting at all.<\/p>\n<h2>Sources<\/h2>\n<ul>\n<li>Sender Policy Framework (SPF), RFC 7208: <code>https:\/\/www.rfc-editor.org\/rfc\/rfc7208<\/code><\/li>\n<li>DomainKeys Identified Mail (DKIM) Signatures, RFC 6376: <code>https:\/\/www.rfc-editor.org\/rfc\/rfc6376<\/code><\/li>\n<li>Cryptographic Algorithm and Key Usage Update to DKIM, RFC 8301: <code>https:\/\/www.rfc-editor.org\/rfc\/rfc8301<\/code><\/li>\n<li>Domain-based Message Authentication, Reporting and Conformance (DMARC), RFC 7489: <code>https:\/\/www.rfc-editor.org\/rfc\/rfc7489<\/code><\/li>\n<li>Google Workspace Admin Help \u2014 Email sender guidelines: <code>https:\/\/support.google.com\/a\/answer\/81126<\/code><\/li>\n<li>Yahoo Sender Hub \u2014 Sender requirements and recommendations: <code>https:\/\/senders.yahooinc.com\/best-practices\/<\/code><\/li>\n<li>Microsoft Tech Community \u2014 Strengthening email ecosystem: Outlook.com sender requirements: <code>https:\/\/techcommunity.microsoft.com\/blog\/microsoft-defender-for-office-365-blog\/strengthening-email-ecosystem-outlook-coms-new-requirements-for-high%C2%A0volume-send\/4399730<\/code><\/li>\n<\/ul>\n<p><script type=\"application\/ld+json\">\n{\n  \"@context\": \"https:\/\/schema.org\",\n  \"@graph\": [\n    {\n      \"@type\": \"FAQPage\",\n      \"mainEntity\": [\n        {\n          \"@type\": \"Question\",\n          \"name\": \"Where exactly does the DMARC record go?\",\n          \"acceptedAnswer\": {\"@type\": \"Answer\", \"text\": \"At _dmarc.<domain> \u2014 so _dmarc.example.com for example.com \u2014 published as a TXT record. Putting it at the domain root instead is the most common DMARC mistake, because the record is syntactically valid and displays correctly in the control panel while never being queried, so no policy is actually in force.\"}\n        },\n        {\n          \"@type\": \"Question\",\n          \"name\": \"Do I need all three records, or is one enough?\",\n          \"acceptedAnswer\": {\"@type\": \"Answer\", \"text\": \"All three, and they are not interchangeable. SPF alone fails on any forwarded message and checks an address the recipient never sees; DKIM alone publishes no policy so nothing acts on a failure; DMARC alone has no results to act on. Since February 2024 Google and Yahoo have required bulk senders to publish all three with alignment, and Microsoft applied comparable requirements from May 2025.\"}\n        },\n        {\n          \"@type\": \"Question\",\n          \"name\": \"Why is my SPF passing but DMARC still failing?\",\n          \"acceptedAnswer\": {\"@type\": \"Answer\", \"text\": \"Almost certainly alignment. SPF is checked against the Return-Path address rather than the visible From: address, and sending platforms commonly use their own domain as the Return-Path \u2014 so SPF passes for the platform's domain while the recipient sees yours, and DMARC treats that as unaligned. The fix is either a custom Return-Path on your own domain or a DKIM signature whose signing domain matches the From: domain.\"}\n        },\n        {\n          \"@type\": \"Question\",\n          \"name\": \"How long should I stay at p=none before enforcing?\",\n          \"acceptedAnswer\": {\"@type\": \"Answer\", \"text\": \"At least two weeks of aggregate report data, and longer for any business whose sending follows monthly or quarterly cycles \u2014 an annual invoicing run that nobody thought of will not appear in a fortnight of reports. The purpose of the waiting period is to see every legitimate sender at least once before a policy starts acting on failures, so the calendar that matters is the sending calendar, not a fixed number of days.\"}\n        },\n        {\n          \"@type\": \"Question\",\n          \"name\": \"What is the SPF ten-lookup limit and how do I get under it?\",\n          \"acceptedAnswer\": {\"@type\": \"Answer\", \"text\": \"SPF permits a maximum of ten DNS lookups when evaluating a record, counting include, a, mx, ptr, exists and redirect terms including everything nested inside them; exceeding it is a permanent error that makes SPF fail regardless of how correct the record looks. Getting under it usually means removing senders that no longer send, or replacing an include with the explicit ip4 ranges it resolves to, which cost no lookups \u2014 at the price of the record going stale silently if that provider changes infrastructure.\"}\n        },\n        {\n          \"@type\": \"Question\",\n          \"name\": \"Should I use ~all or -all at the end of my SPF record?\",\n          \"acceptedAnswer\": {\"@type\": \"Answer\", \"text\": \"Finish on -all, but not until aggregate reports confirm every legitimate sender is authorised. ~all is the correct setting while the inventory is still being proved, since it marks unauthorised mail as suspicious without rejecting it; -all published over an incomplete list rejects real mail, and the loss is typically discovered only when someone asks why a message never arrived.\"}\n        },\n        {\n          \"@type\": \"Question\",\n          \"name\": \"Does changing my MX records fix email going to spam?\",\n          \"acceptedAnswer\": {\"@type\": \"Answer\", \"text\": \"No. MX records govern mail arriving at the domain and play no part in sending or authentication, so they were never involved in the journey of a message that landed in someone else's spam folder. Outbound placement is determined by SPF, DKIM, DMARC and sending reputation, none of which an MX record touches.\"}\n        },\n        {\n          \"@type\": \"Question\",\n          \"name\": \"Can I use one DMARC report address for several domains?\",\n          \"acceptedAnswer\": {\"@type\": \"Answer\", \"text\": \"Yes, but each reported domain must be authorised by the domain hosting the mailbox, which publishes a TXT record at <reporteddomain>._report._dmarc.<reportingdomain> containing v=DMARC1. Without that authorisation conforming receivers decline to send the reports, and the symptom is indistinguishable from no one reporting at all.\"}\n        }\n      ]\n    }\n  ]\n}\n<\/script><\/p>\n<section class=\"cta-band\">\n<div class=\"container cta-band__inner\">\n<div>\n<p class=\"eyebrow\">Authentication not holding?<\/p>\n<h2>Get SPF, DKIM and DMARC configured and monitored properly.<\/h2>\n<\/div>\n<div style=\"flex-shrink:0;\"><a class=\"btn btn--accent\" style=\"white-space:nowrap;\" href=\"https:\/\/www.tkwebhosts.com\/email-deliverability\">See email deliverability<\/a><\/div>\n<\/div>\n<\/section>\n","protected":false},"excerpt":{"rendered":"<p>The DNS records that authenticate a sending domain \u2014 what SPF, DKIM and DMARC each prove, the exact syntax and record locations, DMARC alignment, and the rollout order from p=none to p=reject without losing legitimate mail.<\/p>\n","protected":false},"author":1,"featured_media":60,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[7],"tags":[],"class_list":["post-61","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-domains"],"_links":{"self":[{"href":"https:\/\/www.tkwebhosts.com\/blog\/wp-json\/wp\/v2\/posts\/61","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.tkwebhosts.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.tkwebhosts.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.tkwebhosts.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.tkwebhosts.com\/blog\/wp-json\/wp\/v2\/comments?post=61"}],"version-history":[{"count":1,"href":"https:\/\/www.tkwebhosts.com\/blog\/wp-json\/wp\/v2\/posts\/61\/revisions"}],"predecessor-version":[{"id":63,"href":"https:\/\/www.tkwebhosts.com\/blog\/wp-json\/wp\/v2\/posts\/61\/revisions\/63"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.tkwebhosts.com\/blog\/wp-json\/wp\/v2\/media\/60"}],"wp:attachment":[{"href":"https:\/\/www.tkwebhosts.com\/blog\/wp-json\/wp\/v2\/media?parent=61"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.tkwebhosts.com\/blog\/wp-json\/wp\/v2\/categories?post=61"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.tkwebhosts.com\/blog\/wp-json\/wp\/v2\/tags?post=61"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}