Blog · Dkim

Unknown DKIM and SPF Records in Your DNS: How to Identify Them and Remove Them Safely

Unknown DKIM and SPF Records in Your DNS: How to Identify Them and Remove Them Safely

An unfamiliar DKIM or SPF record in your DNS is not clutter. It is a standing permission to send mail as your domain, and it is still in force until you remove it. This post shows you how to work out which service each unknown record belongs to, how to tell a harmless dead record from one that has changed hands, and the order to remove things in so you do not break a service that is still sending.

Consider the case that usually triggers the question. An MSP engineer logs into a client's registrar to add an SPF record for Google Workspace and finds two entries nobody recognizes:

CNAME  fde._domainkey.client.com  ->  dkim.bm1lmh.fm72.fdske.com
CNAME  fdesp.client.com           ->  spf.bm1lmh.fm72.fdske.com

The first name sits under _domainkey, so it is a DKIM selector. The second is a subdomain the vendor chose, most likely for the bounce and return-path handling. The target belongs to a marketing platform the client used two years ago and dropped last year. The engineer's instinct is to delete both. That instinct is right about one of them and dangerous about the other.

There is a method, and it has an order. Identify the record, classify what it actually grants, prove whether it is still needed, then revoke before you remove.

The short answer

Four steps, in this order.

1. Read the target, not the name. The record name tells you the shape. The target tells you who owns it.
2. Classify what it grants. A DKIM selector CNAME, an SPF CNAME subdomain, an include: of a third party, or a deliberately blank key. Each one has a different removal rule.
3. Prove it is still needed. A record that nobody recognises is not automatically dead. DMARC aggregate reports are the only reliable evidence of which sources are actually sending mail for your domain right now, and DMARCFlow aggregates exactly that, so you can check an unfamiliar record against real sending activity instead of against somebody's memory.
4. Revoke, then remove. Stop the service sending, blank the DKIM key, then take the record away. Deleting first is how you break something that is still live.

The rest of this post expands each step, and the order is not negotiable.

The four record shapes you will find

Almost every unfamiliar record in an email zone is one of these four. Knowing which one you are looking at tells you who owns it and what breaks if it goes away.

RecordWhere it livesWhat it grantsWhat breaks if you delete it while it is live
------------
DKIM selector CNAME._domainkey.example.comThe vendor holds a key and signs mail as your domainSignatures using that selector stop verifying, and DMARC loses the fallback for that sender
SPF CNAME subdomainspf.example.com CNAME vendor.exampleThe vendor's SPF policy is consulted when the envelope sender domain (MAIL FROM) is that subdomainBounce handling and SPF alignment for that vendor stop working
include: of a third partyInside your own v=spf1 TXT recordA third party's SPF policy is consulted for every send from your domainThat vendor loses authorization to send as you
Blank DKIM key._domainkey.example.com, TXT, empty p=Nothing. It is a revocation markerNothing breaks. Signatures that use the selector fail on purpose

The fourth shape is the one people misread most often, so it is worth being precise about it. RFC 6376 stores every DKIM key under the _domainkey subdomain, and the key itself is a DNS TXT record. A DKIM key is not a CNAME. The CNAME delegation pattern that every sending platform hands you is a widespread convention, and RFC 6376 does not mention CNAME anywhere. That is why admins are surprised when they go looking for a key inside their own zone and find nothing: the key lives at the vendor, and your zone holds a pointer.

Only one of those four rows costs anything at evaluation time. The include: is a DNS lookup, and it counts against the ten-lookup cap. A DKIM selector CNAME and a blank key cost nothing during SPF evaluation, and the blank key is a TXT lookup that only happens when a verifier resolves a signature. So when you are hunting for lookup budget, the SPF record is where it goes.

The fourth shape, the blank key, is the opposite case. RFC 6376, on the p= tag: "An empty value means that this public key has been revoked." The same section says a signer whose provider contract ended may want to "explicitly state that it knows about the selector, but all messages using that selector should fail verification", and that verifiers "SHOULD return an error code for any DKIM-Signature header field with a selector referencing a revoked key." A blank key is a door that is deliberately locked. A deleted key is a doorframe that is no longer there.

Why an unknown record is more than clutter

A CNAME hands the right to authorize senders to someone else

This is the part that makes these records worth your attention.

When you point a name at another domain with a CNAME, DNS resolution follows the pointer. Any lookup of your name is answered by the target's data. So if fdesp.client.com is a CNAME to spf.bm1lmh.fm72.fdske.com, then evaluating SPF for fdesp.client.com reads the TXT record at the target, and that record is controlled by whoever owns fdske.com.

The owner of the target can list any IP address in that record. Your zone delegates the choice to them.

The case that passes DMARC even under p=reject

Now follow the chain to its end. Suppose the client cancels the marketing platform and never removes the CNAME. Later, the target domain lapses and is registered by someone else. That new owner publishes an SPF record naming their own mail servers, and sends from those servers using an envelope sender at your subdomain.

Your SPF evaluation for that subdomain follows the CNAME, reads the new owner's record, finds the sending IP authorized, and returns Pass. The From address is your domain, and in relaxed alignment mode, which is the default, the SPF-authenticated domain and the From domain only need to share an Organizational Domain, so a subdomain counts as aligned. DMARC passes on SPF alignment. The message clears a policy of p=reject, because from the receiving server's point of view it came from an authorized source.

One qualification, because it changes who is exposed. RFC 7489, Section 3.1.2: in strict mode only an exact match between the two fully qualified domain names counts, so a subdomain envelope sender would not align. A policy that sets aspf=s or adkim=s is therefore harder to abuse this way. The default of r for both is the common case, and the common case is the exposed one.

Your DMARC policy was never misconfigured. It was faithfully evaluating a record that no longer belongs to you.

A dead include: can turn your own SPF record into permerror

The second consequence is quieter and hits more domains. Look at what RFC 7208 says happens when an include: points somewhere that no longer publishes an SPF record. Section 5.2 gives the result of the recursive check on the include target:

Result of the included domain's SPF checkWhat the include: does
------
passMatches
fail, softfail, neutralDoes not match, evaluation continues
temperrorThe parent returns temperror
permerrorThe parent returns permerror
noneThe parent returns permerror

That last row is the one that catches people. If your SPF record contains include:newsletter-vendor.example and that vendor shut down without an SPF record, the include returns none, which makes the parent return permerror.

Your SPF record now fails to evaluate for every sender on your domain. DMARC still passes if DKIM is aligned, so nothing looks broken. But the SPF fallback is gone, and the next time a DKIM key rotates, a sending path is added, or a stricter receiver starts enforcing, there is no second line of defence left.

Every dead include: burns one of your ten DNS lookups

RFC 7208, Section 4.6.4: "SPF implementations MUST limit the total number of those terms to 10 during SPF evaluation, to avoid unreasonable load on the DNS. If this limit is exceeded, the implementation MUST return permerror."

The terms that cost a lookup are include, a, mx, ptr, exists and the redirect modifier. all, ip4, ip6 and exp are free. Each include: is one slot, and a nested include: inside a vendor's policy costs more than one when it is evaluated.

So a zone carrying nine dead include: entries has almost no room left for the service you add next month. Cleaning up is not housekeeping here. It is reclaiming capacity you need.

How to identify who owns an unknown record

Step 1: read the target, not the name

The record name tells you what shape it is. The target tells you who owns it. Most admins read the name, get stuck on _domainkey, and conclude the record is mysterious. It is not. It is a pointer, and pointers say where they point.

dig CNAME fde._domainkey.client.com +short
dig CNAME fdesp.client.com +short

If the record is a TXT record rather than a CNAME, read it directly:

dig TXT client.com +short
dig TXT _dmarc.client.com +short

Step 2: the target hostname usually names the vendor

In the example, the target reads dkim.bm1lmh.fm72.fdske.com and spf.bm1lmh.fm72.fdske.com. The pattern is the giveaway. It is a purpose-built sending domain, with dkim and spf subdomains and a random-looking parent that is the vendor's own infrastructure.

Look at the registrable part. fdske.com is owned by somebody, and somebody else's mail is being authorized by your zone. A vendor's documentation page for "add these DNS records" is the next step.

Step 3: check the vendor's own DNS setup documentation

Search the target domain together with the shape of the record. Vendors publish the exact hostnames they ask customers to point at, so the target is usually searchable. The record will turn out to belong to the email marketing platform, the CRM, the helpdesk or the transactional sender the team used before, and the vendor's own setup page will confirm which selector and which subdomain they delegate.

That is the moment to check whether the service is still in use. Look for a login to the vendor account, a billing entry, a sending activity log, or a record of anyone still receiving mail from it.

Step 4: confirm the record is still needed, do not assume it

Here is where DNS alone stops being enough and the DMARC data takes over. Your DMARC aggregate reports are the only reliable record of who is actually sending mail for your domain. Each report row carries the sending IP and the message count, which tells you which sources are live right now, not which ones were live when the record was created.

DMARCFlow's platform is built around exactly this. It aggregates the reports and shows you who is sending messages on behalf of your email domain, so an unfamiliar record can be checked against real sending activity. The reports answer "is this still in use". They do not answer "should I delete this". That second question needs the removal order below.

One practical condition, and it catches people out. You only get reports if your DMARC record asks for them. A p=none policy with no rua= tag produces no reports at all, which leaves you with nothing to compare against. If you are in that position, adding a rua= address is a worthwhile first step, and you should expect to wait for a reporting cycle before the picture is complete.

Dangling is not the same as re-pointed

This is the distinction that most cleanup guides skip, and it decides how urgent the job is.

How to tell the two apart

Dangling. The target does not resolve any more. The name is gone, the vendor shut down and dropped its DNS, or the domain lapsed and nobody claimed it.

dig CNAME fdesp.client.com +short

no output, or the target returns NXDOMAIN

The risk here is mostly wasted permission and a wasted lookup slot. A dangling target cannot authorize anyone because there is no record to authorize anything. It still costs you a lookup in some evaluation paths, and it is still noise.

Re-pointed. The target resolves, and it resolves to somebody else's infrastructure now. This is the case that matters, because the target owner controls the TXT records your zone will read.

dig CNAME fdesp.client.com +short

dkim.bm1lmh.fm72.fdske.com

dig TXT dkim.bm1lmh.fm72.fdske.com +short

"v=spf1 ip4:203.0.113.10 -all"

If the target resolves and publishes a policy that authorizes addresses you do not recognize, the record is no longer yours in any meaningful sense.

Why a re-pointed CNAME survives a resolve check

A simple "does this CNAME still resolve" test passes the re-pointed case, because the target is alive. It is the target's ownership that changed, not its existence.

Two signals separate the two cases in practice. The TTL and the infrastructure behind the target will look unfamiliar if the domain changed hands. More reliably, compare the target against what your vendor's documentation says. A target with three random subdomains under it and a bare registrable domain that has no relationship to your business is a red flag. A target that reads dkim.sendgrid.net or dkim1._domainkey.mailchimp.com is a vendor you can name.

The one that settles it is the DMARC report data. If reports show no traffic from a source that maps to that vendor, the record is not in active use, whatever the DNS says.

How to remove a record without breaking mail

The order matters

Remove in this sequence, and only this sequence. The first two steps are the ones that are usually skipped, and they are the ones that keep the record safe while you work.

Step 1: stop the service sending first. Turn off the sending account, the campaign schedule, the CRM sync, the transactional stream. Anything that can still emit a message signed with that selector must stop before you touch DNS. If the service is still live and you revoke underneath it, you break sending in a way that looks like a delivery problem rather than a configuration problem, and that costs days to diagnose.

Step 2: revoke the DKIM key with an empty p= tag. Do not delete the key record straight away. Replace the key material with an empty value, leaving the selector in place:

._domainkey.example.com.  TXT  "v=DKIM1; k=rsa; p="

RFC 6376 is explicit that an empty p= means the key is revoked, and that verifiers should return an error for any signature that uses a revoked selector. A signature that references a selector whose key record has been deleted may instead be reported as a DNS failure or a signature verification failure, which is a much noisier signal to chase.

RFC 6376 also notes that there is no defined semantic difference between a revoked key and a removed key. That is true cryptographically and false operationally. Revoking leaves a clean, intentional error behind. Removing leaves a lookup failure that looks identical to a broken mail path.

Step 3: remove the include: or the CNAME. Now take the record away. For an include: inside your SPF record, delete the term from the v=spf1 string and keep the rest of the record intact. For a CNAME, delete the record.

Do not delete the record and leave the SPF policy pointing at a domain that publishes nothing. That is the none to permerror case, and it turns a tidy-up into an outage for your SPF fallback.

Step 4: re-check SPF and DKIM afterwards. Confirm that your SPF record still evaluates, that the DKIM selectors you still use resolve, and that the DMARC policy is unchanged. If you removed an include:, count your remaining lookup terms while you are there.

What you must not delete

Do not delete a selector you cannot explain yet. A DKIM selector you have not traced to a service is the one record in the zone that might be signing your transactional mail. If you cannot identify the owner, leave the record in place, and use the report data to find out whether anything is signing with it. An unexplained selector with no signing activity is inert. An unexplained selector deleted out of curiosity may have been your invoice sender.

Do not delete a record that a live service depends on because the service's own website did not list it. Vendors add records over time, and a selector for a service that only sends on the first of every month will look completely idle the rest of the month.

What to do when the record belongs to a live service

If the service is still sending, the record stays. If the service is live but you want a different vendor, do not delete the old records on the same day you add the new ones. Add the new selector and the new include: first, watch the DMARC reports for a cycle to confirm the new path is aligned, then run the removal steps for the old one.

That sequencing is what keeps a migration invisible to your recipients, which is the only outcome that matters during a provider change.

How to stop new ones arriving

Change control on the zone

Every unknown record in your zone was added by someone. Usually they were a contractor, an agency, or a colleague following a setup screen, and usually nobody told them they were changing authentication.

The fix is not a rule about SPF and DKIM. It is a rule about who can publish TXT and CNAME records in the mail-related names of your zone. If DNS changes require a second pair of eyes for _dmarc, _domainkey and any include: term, unknown records stop arriving. That is a process change, and it is the only one that holds.

A recurring review rather than a one-off cleanup

Cleanups decay. A quarterly review of the authentication names in your zone, fifteen minutes with a checklist, is enough to catch the next one while it is still harmless. The checklist is short: list the _domainkey selectors, list the CNAMEs under the zone, list the include: terms in the SPF record, and check each against the report data.

A check you can run right now

If you want to look before you read further, DMARCFlow's DKIM Checker (https://dmarcflow.com/en/dkim-checker) verifies selectors, key length and TXT records for any domain in the browser, with no account and no login. The SPF Record Lookup (https://dmarcflow.com/en/spf-checker) does the same for the SPF side, and the DMARC Checker (https://dmarcflow.com/en/dmarc-checker) reads the DMARC record and the SPF and DKIM configuration together, which is how you spot a policy that is present but not doing anything.

If you want the ongoing view rather than a one-time check, the paid tiers start at 1 EUR per month for a single domain and 34.99 EUR for up to 25 domains, published on the pricing page, so you can start without a sales conversation.

Frequently asked questions

Is it safe to delete a DKIM record I do not recognize?

Not on its own. Deleting a selector that a live service still signs with breaks that service's DKIM immediately, and the failure shows up as a verification error in the recipient's message headers rather than as a clear "you deleted something". Revoke the key with an empty p= value first, stop the service sending, then remove the record.

What if the CNAME target no longer resolves at all?

That is the benign case. A target that does not resolve cannot authorize anyone, so the risk is low. You still want to remove it, because it occupies a DNS lookup and because a domain that lapses today can be registered by someone else tomorrow. Remove it as part of your normal tidy-up, no urgency required.

Can an unknown record really let someone send as my domain?

Yes, and this is the case worth acting on. If the target domain has changed owners, the new owner controls the SPF record your zone reads through the CNAME, and can authorize their own servers. Mail sent that way can align with your domain under the default relaxed alignment mode and pass DMARC, including a policy of p=reject. Nothing about your DMARC configuration is wrong. The problem is that you delegated the choice of sender to a domain you no longer control.

Do I need to check every subdomain?

Check every name that holds a mail record. A DKIM selector lives on a subdomain of _domainkey, and an SPF CNAME usually lives on a subdomain chosen by the vendor, so the records you are hunting are not on the zone apex. If you have a tool that discovers subdomains, use it here. If you do not, start with the records you can see in the zone view of your registrar, then check the senders your DMARC reports show as active.

Will removing an include: break my SPF record?

Only if you break it while editing. Removing the term from the v=spf1 string is safe, and it frees a lookup. The dangerous version is removing the record or the entire SPF entry. And check the target before you delete: if the included domain no longer publishes an SPF record, your own record is already returning permerror today, and removing that include: is the fix rather than the cause of the problem.

A fifteen-minute next step

Pick one domain you own. List the _domainkey selectors, list the CNAMEs, list the include: terms in the SPF record. For each one, write down the service it belongs to. Anything you cannot name goes on a list, not into the DNS. Pull the DMARC report data for the same domain and cross it against that list.

The records you can name and that show no sending activity are your cleanup list. The records you cannot name are your investigation list. Keep those two lists separate, because they need different actions and very different urgency.