Email authentication

MTA-STS checker

Read a domain’s MTA-STS record and policy file, and check every mx pattern against its live MX records.

Free, no accountLive check

Try

Result

The verdict appears here once you press Check MTA-STS policy.

What this is

This MTA-STS checker reads the three things that have to agree before a sender will require TLS for your mail: the TXT record at "_mta-sts", the policy file served at "mta-sts." plus your domain, and the MX records your domain publishes right now - which is the pair that quietly stops matching after a provider change.

MTA-STS (RFC 8461) is how a receiving domain tells sending servers that mail must arrive over TLS, to a host it has named in advance. It is published in two places at once: a small TXT record at "_mta-sts.<domain>" carrying a version and a policy id, and a policy file fetched over HTTPS from the fixed path "/.well-known/mta-sts.txt" on the host "mta-sts.<domain>".

The policy file names the hosts allowed to receive the mail, with one "mx:" line each, and a "mode" that says what a sender does when a host fails that check - refuse delivery, report it, or ignore the policy altogether. Because the list of allowed hosts is written down separately from the MX records themselves, the two can drift apart, and nothing in DNS notices when they do.

How to read the result

"Live MX hosts against the policy" is the table to read first. Each host the domain publishes is shown with the policy pattern that covers it, or "no match" - and a "no match" at mode enforce is a host that senders honouring MTA-STS will refuse to deliver to, however healthy the host itself is.

The discovery facts above it say what was found where: the exact TXT record, the policy id inside it, the URL the policy was fetched from and the HTTP status it answered with. A 404 or a redirect there is a complete failure of the policy even though the TXT record looks perfect, because RFC 8461 §3.3 only accepts a 200 and forbids following redirects.

Common mistakes

What goes wrong most often, and how to tell.

  • Changing mailbox provider and leaving the old mx lines in the policyNew MX records go into DNS, the policy file keeps naming the previous provider’s hosts, and every sender that honours an enforce policy stops delivering - while senders that ignore MTA-STS carry on, so the domain appears to be receiving mail from some places and not others.
  • Editing the policy file without changing the idThe id in the TXT record is the only signal a sender has that the file is worth fetching again. Correct the file but leave the id alone and senders holding a cached copy keep applying the old policy until its max_age runs out, which the RFC expects to be weeks.
  • Serving the policy from a redirect or the wrong hostThe policy host is "mta-sts." prepended to the domain and the path is fixed, and RFC 8461 §3.3 says redirects must not be followed. A rule that sends the apex and all its subdomains to one canonical host turns a valid policy into no policy at all.
  • Going straight to mode enforceTesting mode exists so a sender reports a policy failure instead of refusing the message, which is how you find a host you forgot to list before it costs you mail. Publishing a TLS-RPT record first is what makes those reports reach you.

Questions

What people ask about this tool.

  • Because the policy file lists the hosts allowed to receive your mail by name, and a migration changes your MX records without touching that file. At mode enforce, a sender must not deliver to a host that matches no "mx" line, so the new provider’s hosts are refused until the policy is updated and its id changed.
  • It identifies one revision of the policy file, in 1 to 32 letters and digits. A sender keeps the policy it fetched and compares the id in DNS against the one it cached, so changing the id is what tells every sender to fetch the file again - and not changing it is why a corrected policy appears to do nothing.
  • No. RFC 8461 §4.1 allows "*" only as the entire left-most label, so "*.example.com" matches mail.example.com but neither example.com itself nor foo.bar.example.com. A host two labels deep needs its own pattern or its own wildcard.
  • No, and that gap is listed under the limits on every result. Checking that would mean opening an SMTP connection to each host and inspecting the certificate it presents, which this page deliberately never does; it checks what is published in DNS and over HTTPS.

Sources

Every fixed value here comes from the provider’s own documentation. These pages change, so each says the day it was last read.

Use it from the API

The same check, as one request.

Request
curl -X POST https://resellerhq.com/api/tools/mta-sts-checker \
  -H "Content-Type: application/json" \
  -d '{"domain":"enforced.example"}'
Response
{
  "tool": "mta-sts-checker",
  "input": {
    "domain": "enforced.example"
  },
  "result": {
    "verdict": {
      "tone": "success",
      "headline": "MTA-STS is enforced for enforced.example",
      "summary": "The record, the policy file and the MX records the domain publishes all agree."
    },
    "findings": [
      {
        "id": "policy-lifetime",
        "severity": "info",
        "title": "Senders may cache this policy for about 7 days",
        "detail": "max_age is 604800 seconds, counted from each sender's last fetch (RFC 8461 §5.1). The RFC expects this value \"typically be in the range of weeks or greater\", because a short lifetime means more refetches and each refetch is a chance for an attacker to interfere."
      },
      {
        "id": "sts-record-found",
        "severity": "pass",
        "title": "MTA-STS record published",
        "detail": "_mta-sts.enforced.example publishes \"v=STSv1; id=20260901120000Z;\". The \"id\" in it is what lets a sender tell a cached policy from a new one without fetching the file again (RFC 8461 §3)."
      },
      {
        "id": "mode-enforce",
        "severity": "pass",
        "title": "Mode is enforce, so TLS is required",
        "detail": "RFC 8461 §5 says a sender applying an enforce policy must not deliver to a host that fails MX matching or certificate validation, or that does not offer STARTTLS. Mail to enforced.example from a sender honouring MTA-STS either goes over verified TLS to a listed host or does not go."
      },
      {
        "id": "policy-mx-matches",
        "severity": "pass",
        "title": "Every MX host for enforced.example matches the policy",
        "detail": "All 2 published hosts match one of the policy's patterns under RFC 8461 §4.1 matching, where \"*\" stands for exactly one left-most label."
      }
    ],
    "parts": [
      {
        "kind": "facts",
        "title": "Policy discovery",
        "rows": [
          [
            "Record",
            "v=STSv1; id=20260901120000Z;"
          ],
          [
            "Policy id",
            "20260901120000Z"
          ],
          [
            "Policy file",
            "https://mta-sts.enforced.example/.well-known/mta-sts.txt"
          ],
          [
            "HTTP status",
            "200"
          ],
          [
            "Mode",
            "enforce"
          ],
          [
            "max_age",
            "604800 seconds (about 7 days)"
          ],
          [
            "mx patterns",
            "mx1.enforced.example, mx2.enforced.example"
          ]
        ]
      },
      {
        "kind": "table",
        "title": "Live MX hosts against the policy",
        "columns": [
          "Priority",
          "MX host",
          "Matching policy pattern"
        ],
        "rows": [
          [
            "10",
            "mx1.enforced.example",
            "mx1.enforced.example"
          ],
          [
            "20",
            "mx2.enforced.example",
            "mx2.enforced.example"
          ]
        ],
        "mono": [
          0,
          1,
          2
        ],
        "note": "Matching follows RFC 8461 §4.1: \"*.\" replaces exactly one left-most label, so \"*.example.com\" matches mail.example.com but not example.com."
      },
      {
        "kind": "text",
        "title": "The policy file as served",
        "body": "version: STSv1\n\nmode: enforce\n\nmx: mx1.enforced.example\n\nmx: mx2.enforced.example\n\nmax_age: 604800"
      }
    ],
    "lookups": [
      {
        "label": "TXT for _mta-sts.enforced.example",
        "value": "Cloudflare: 1 record"
      },
      {
        "label": "GET https://mta-sts.enforced.example/.well-known/mta-sts.txt",
        "value": "HTTP 200"
      },
      {
        "label": "MX for enforced.example",
        "value": "Cloudflare: 2 records"
      }
    ],
    "limits": [
      "Nothing here opens a TLS connection to a mail server, so the certificate those hosts present - the thing an enforcing sender actually checks against the policy, and which RFC 8461 §3.3 requires to be valid for the MX name, non-expired and chained to a trusted root - cannot be verified from this page.",
      "A sender may still be applying a cached copy of an older policy for up to its max_age (RFC 8461 §5.1), so a policy corrected a minute ago is not yet the one every sender is using.",
      "RFC 8461 §3.2 sets a maximum max_age of 31557600 seconds and no minimum at all - it says only that the value is \"expected to be in the range of weeks or greater\" - so a short lifetime is reported here, never called wrong."
    ]
  }
}

This example uses a name RFC 2606 reserves for documentation, ending in .example, .test, .invalid or .localhost. None of them is a real domain, and nobody can register one.

Resell mailbox licences for the domains you just checked, under your own brand.

Get started

Company names and logos are trademarks of their owners, shown only to identify each service.