Check the DNSbehind your email.

Read your domain's public mail records, check supported rules and inspect suggested repairs with their sources. A failed DNS lookup stays unverified. DKIM uses the selector from a message you sent, or a list of common names. These checks do not predict inbox placement or prove that a particular message is authenticated.

  • 7 record types read
  • findings with rule references
  • 0 €, no account
  • runs entirely in your browser

Your domain. Seven checks. Public records you can inspect.

The checks run one after another and appear as each answer arrives, so the MX and SPF reading is on screen long before the last DKIM selector has been tried.

fn MailDoctor.runChecks(domain)
your browser, public DNS, no server of ours

For a known DKIM key, use the s= value from a sent message's DKIM-Signature header and its d= signing domain above. Leave the selector blank to try common names. Finding no key does not prove that DKIM is absent.

DNS questions go directly to the public resolvers. Cloudflare receives the domain you enter, with Google as the fallback. New share links keep the domain after #, outside the page request. This tool does not load analytics.

    Type a domain above and press Check. Nothing is sent anywhere: this page has no backend, and the reading is done by mail.mjs running in this tab.

    Three parts of email authentication to check.

    Nothing about them is a matter of taste. Each one is a published standard, each one has a rule that either holds or does not, and the failures below are the ones that cost real delivery.

    1. SPF says who may send.

      One line in DNS listing the machines allowed to use your address. Two lines instead of one is a permanent error and both are ignored. So is an eleventh DNS lookup, and the count includes everything inside every include you wrote, which is why a record breaks on a day you changed nothing.

    2. DKIM signs the message.

      A signature your sending service adds, checked against a public key in DNS. It survives forwarding, which SPF does not. A key published with an empty p= is revoked, a key under 1024 bits must be refused, and a key still carrying t=y tells receivers to ignore its failures.

    3. DMARC says what to do when both fail.

      And, far more usefully, it asks every receiver in the world to send you a daily report of who has been sending mail as you. At p=none nothing changes for a forged message, which is the right place to start and the wrong place to stay.

    DNS answers in, findings out. No model, no server, no guess.

    Every rule in mail.mjs is a deterministic reading of a published standard against a real record: RFC 7208 for SPF, RFC 6376 and 8301 for DKIM, RFC 7489 for DMARC, RFC 8461 for MTA-STS, RFC 8460 for TLS-RPT. Where the standard says should rather than must, the finding says so instead of calling it an error.

    mail.mjs 0 dependencies
    import { analyse, runChecks } from './mail.mjs';
    
    // pure: DNS answers in, findings out, no network
    const report = analyse('example.com', zone);
    
    // or stream, one area at a time, over DNS over HTTPS
    for await (const ev of runChecks('example.com')) { /* … */ }
    
    // one finding
    {
      "severity": "critical",
      "title":    "11 DNS lookups, and the limit is 10",
      "record":   { name, type, text },  // what we read
      "rule":     "An implementation must limit…",
      "rfc":      "RFC 7208 section 4.6.4",
      "level":    "must" | "should" | "optional",
      "suggest":  { name, type, value, why }  // copy it
    }

    The checks run in your browser. It opens DNS over HTTPS connections directly to Cloudflare, with Google as a fallback. Those DNS providers receive the questions. The tool sends no form values to an ARLing service and loads no analytics. Share links created here store the checked domain in the URL fragment.

    The SPF lookup count is the part most checkers get wrong. This one walks every include and redirect to the end, counts in the order a receiver reads the terms, stops at all because nothing after it is ever evaluated, and ignores a redirect when the record also has all, exactly as RFC 7208 section 5.1 requires. It then lists every term that cost a lookup, so you can check the count rather than trust it.

    Suggested records depend on your actual sending services. Check those services and message headers before publishing a change. An MX record names the receiving provider, which may differ from your sending provider. Having a report address alone is not evidence that tightening DMARC is safe; first inspect reports showing your legitimate senders.

    One check cannot tell you who is sending mail as you.

    This is the honest limit of everything on this page, and of every other one time checker.

    Free, and it stays free.

    No account, no payment, no usage limit. It is a static page that runs in your browser, so there is no server for us to pay for and no reason to meter it. If it tells you something wrong, write to andrej@arling.sk with the domain and we will fix the rule, because a checker that gives wrong advice about mail authentication is worse than no checker at all.

    What a shop owner actually asks.

    In words that do not assume you run a mail server.

    What is SPF, in plain words?

    SPF is a public list of the machines allowed to send mail with your address on it. You publish it in DNS as one line of text starting v=spf1. When a message arrives claiming to be from you, the receiving server looks up that list and checks whether the machine that just connected is on it. If you have no list, there is nothing to check, and the receiver has to fall back on guessing.

    The most common way to get SPF wrong is to have two of these lines instead of one, usually because a new service was added without noticing the old line. That is not a smaller problem than having none: the standard says a receiver must treat two records as a permanent error and ignore both.

    What is DKIM?

    DKIM is a signature your sending service puts on every message, made with a private key it keeps and checked against a public key you publish in DNS. It survives forwarding, which SPF does not: when someone forwards your newsletter, SPF breaks because the forwarding server is not on your list, but the DKIM signature still verifies.

    The public key lives at a name like google._domainkey.yourdomain.com, and the part in the middle is called the selector. Your sending service chooses it, and DNS gives no way to list the selectors a domain uses, which is why this page tries the names the common senders use rather than discovering them.

    What is DMARC, and why does everyone say to start at p=none?

    DMARC is the instruction you give receivers for what to do with a message that claims to be from you and passes neither SPF nor DKIM: nothing (p=none), put it in spam (p=quarantine) or refuse it (p=reject). It also asks receivers to send you a daily report of every machine that sent mail as you.

    Start at p=none because on day one you do not know all of your own senders. Almost every company discovers a forgotten invoice tool, a shop plugin or an old newsletter service in the first month of reports. Move to quarantine only once the reports show every legitimate sender passing, or you will be the one blocking your own mail.

    Why can this page not find my DKIM key?

    Because there is no way to ask DNS which selectors exist under a domain: you can only ask about a name you already know. This page tries the selectors that the common senders use, and lists which ones it tried. Services that generate a selector per customer, such as HubSpot, Klaviyo and some Amazon SES setups, cannot be found this way by anyone.

    To find yours, open a message you have actually sent, look at the raw headers, and read the s= value out of the DKIM-Signature header. That is the selector.

    All three records pass and my mail still goes to spam. What now?

    Authentication is the entry ticket, not the whole judgement. Once SPF, DKIM and DMARC line up, what decides the inbox is reputation: how many people open your mail, how many mark it as spam, whether your sending address and your link domains are old enough to be known, and whether you send a burst of a thousand messages from an address that sent none last week.

    These DNS checks cannot rule out authentication problems in a particular message. Inspect its Authentication-Results and DKIM-Signature headers to check actual results and alignment. This tool does not test message content, reputation or receiver policy.

    Is the domain I type sent to your servers?

    Domains entered in this form go directly to Cloudflare's public DNS resolver, with Google as a fallback. Those providers receive the DNS question. New share links keep the domain after #, which is not sent in the page request. Older links containing ?domain= already sent that query to the page host before opening; this page converts them locally to fragment links.

    This tool does not load analytics or send checked domains to an ARLing service.

    Why does an SPF record that worked for years suddenly break?

    Because the ten DNS lookup limit is spent on the whole tree, not just on your own line. Every include you write is followed, and everything inside it is followed too. When a provider you include adds one include of their own inside their record, your total goes up by one, and nothing changed on your side.

    If you were sitting at ten, you are now at eleven, which is a permanent error, and a permanent error means the whole record is thrown away, including the parts that were fine. That is why this page counts the tree and names every term that costs a lookup.

    Should I end my SPF record with -all or ~all?

    -all is the destination and ~all is the safe road to it. -all tells a receiver that anything not on your list is definitely not you, which is the strongest statement you can make. It is also the statement that gets a forgotten sender rejected the moment you publish it. ~all asks the receiver to accept the message and mark it, which loses nothing while you are still finding your own senders.

    This page always suggests ~all when it suggests tightening a record, and tells you when moving to -all is the next step.