EMAIL SECURITY

MTA-STS & TLS-RPT Checker — Validate Your Email TLS Policy

Enforced, testing, broken, or not configured? One scan walks the DNS record, the HTTPS policy file, the cert SAN, and MX alignment — and flags the policy-ID drift pattern that silently keeps your latest edits from taking effect.

Tested against: google.com · microsoft.com · gov.uk · github.com

Check MTA-STS for any domain

Unified MTA-STS + TLS-RPT + MX cross-check, policy-ID drift detection, and named-failure labels — in one scan.

Try:
What this checks
  • MTA-STS + TLS-RPT + MX, in one pass

    All three signals in a single scan — no tab-hopping between tools while you're chasing a policy-fetch failure.

  • Policy-ID drift coach

    SHA-256 of your published policy body, surfaced next to your id= — so you catch the "forgot to bump the ID" silent failure before senders cache the old policy.

  • MX-to-policy match-up

    Live MX records vs. your policy mx: entries — with wildcard support for Microsoft 365 and Google Workspace patterns.

What this doesn't do (v1): parse inbound TLS-RPT aggregate reports — no free tool does this yet. For continuous policy-ID drift monitoring across sessions, SSLMate is the paid option.

Quick summary

  • 1Is MTA-STS enforced? The DNS TXT record at _mta-sts.{domain} and the HTTPS policy file together have to say mode: enforce, and every live MX host has to match a policy mx: entry.
  • 2Is the policy file reachable? HTTPS only, no redirects, valid cert whose SAN covers mta-sts.{domain}. About 30% of broken deployments fail here.
  • 3Is TLS-RPT reporting on? Without a _smtp._tls.{domain} record, broken MTA-STS policies fail silently for you. Publish both.

MTA-STS adoption is under 1% globally as of 2026 per URIports' survey — a clean "not configured" result isn't a red flag, it's the default state. We render it in neutral grey. We only go amber when something is actively broken.

What you'll see in the result

MTA-STS failures are silent on the sender side and silent on your side too — without TLS-RPT you have no signal at all. The checker walks every gate a compliant sender walks. Five things to look for:

1

Four states, not pass/fail.

Enforced, testing, broken, or not configured. Testing isn't a failure — it's a deliberate safe-deploy pattern. Not-configured is the global default (under 1% adoption per URIports' 2026 survey) — neutral grey, no alarm. We only go amber when something is actively broken.

2

A check for the “forgot to bump the id=” failure.

We hash your published policy body and surface the hash right next to your id= tag. If you edited the policy but forgot to rotate the ID, senders keep caching the old one until max_age expires — a silent failure we catch before it costs you a deploy window.

3

Failure labels written the way you'd google them.

“Stale policy ID.” “MX wildcard missing.” “Max-age below 86400 (Google ignores this policy).” “Cert SAN mismatch.” Copy the label into your help desk and the right answer is already on the first page.

4

MX-to-policy match-up with wildcard support.

Your actual MX records, lined up against the mx: entries in your policy, with ✓/✗ per row. Handles *.mail.protection.outlook.com and Google Workspace's numbered variants — so an Office 365 setup doesn't falsely flag as broken.

5

Copy-paste fix blocks, with the copy button right there.

A suggested DNS TXT line and a suggested policy body, ready to drop into your DNS provider. No bouncing out to a separate MTA-STS generator tool.

What is MTA-STS? RFC 8461 in 90 seconds

MTA-STS (Mail Transfer Agent Strict Transport Security, RFC 8461) is a DNS-and-HTTPS mechanism that lets a domain owner declare that inbound SMTP must use validated TLS. The policy is advertised via a TXT record at _mta-sts.{domain} and a companion policy file at https://mta-sts.{domain}/.well-known/mta-sts.txt. TLS-RPT (RFC 8460) is its paired telemetry layer — a DNS TXT record at _smtp._tls.{domain} with a rua= URI where remote mail servers send JSON reports of TLS negotiation failures. A correctly deployed domain publishes both, rotates the MTA-STS id= on every policy-body change, and lists every live MX host in the policy's mx: entries.

The problem MTA-STS solves is STARTTLS downgrade. Plain SMTP starts in cleartext and upgrades to TLS opportunistically via the STARTTLS verb. A network attacker between two MTAs can strip the STARTTLS advertisement from the 220 greeting, and the sender happily falls back to cleartext — unauthenticated, unencrypted, and undetectable from the sender's side. MTA-STS publishes a signed commitment from the receiver: “I require TLS, and here are the MX hosts I consider valid.” Compliant senders consult the policy before delivery and refuse to fall back.

Adoption in 2026 is under 1% globally per URIports' survey, with UK government at 20.6% because of a Cabinet Office mandate and US at 1.7%. Microsoft Exchange Online enforces inbound MTA-STS since 2024–2025; Google Workspace supports it since 2019 but Gmail recommends rather than mandates. If you run email infrastructure and your domain isn't subject to the EU / gov MTA-STS-or-DANE regulatory regime, shipping MTA-STS today is a low-regret deliverability and security signal.

How the MTA-STS checker works

The tool runs five independent probes in parallel:

  1. A DNS TXT lookup at _mta-sts.{domain} to get the policy pointer (version + id).
  2. An HTTPS fetch of https://mta-sts.{domain}/.well-known/mta-sts.txt with a 5-second timeout and no redirects (RFC 8461 §3.3).
  3. A TLS handshake against mta-sts.{domain}:443 to inspect the cert chain — issuer, subject, SAN list, validity dates.
  4. A DNS MX lookup for the apex domain, sorted by priority.
  5. A DNS TXT lookup at _smtp._tls.{domain} for the TLS-RPT record.

All five probes run inside one Promise.all — a typical scan finishes in well under a second for configured domains. The policy file body is hashed with SHA-256, and that hash is surfaced in the UI next to your DNS id= value — so you can spot policy-ID drift (body changed, ID not rotated) at a glance.

The rate limit is deliberately tight: 3 requests per 10 minutes per IP. The HTTPS policy fetch turns this endpoint into a potential scan amplifier if abused, so we cap generously but firmly. If you're scripting against the public API, cache results for at least five minutes on your side.

Why do you need TLS-RPT alongside MTA-STS?

MTA-STS without TLS-RPT is a one-way door. You publish a policy saying “require TLS,” compliant senders start honoring it, and when anything breaks — a cert expiration, a new MX host you forgot, a load-balancer that terminates TLS incorrectly — senders start rejecting your mail, and you have no telemetry of it. TLS-RPT gives every remote MTA a JSON-report endpoint to send structured diagnostics to: when did they attempt delivery, what did they see, what did they reject.

The record itself is trivial. One TXT record at _smtp._tls.{domain} with value like v=TLSRPTv1; rua=mailto:[email protected]. You can list multiple rua= endpoints, and they can be either mailto: addresses or https:// POST targets. Aggregate reports arrive daily.

Two pragmatic notes. First, pointing rua= at a real inbox you read is better than a fancy ingestion pipeline you don't — most domains never parse these reports, they just want to know someone is failing. Second, expect reports to include your admin email in public sender-side logs; for privacy, use a dedicated forwarding address rather than your personal one. This checker redacts the mailto: local-part in the UI so we don't leak it from your result page.

Testing or enforce — which should you publish?

RFC 8461 gives you three modes, but operationally only two matter. Testing is the safe rollout. Enforce is the production target. “None” is a deliberate opt-out you use during a migration to tell senders “please stop honoring my old policy.”

AspectTestingEnforce
Rejects mail on mismatch?NoYes — hard bounce
TLS-RPT reportsYes — what would have happenedYes — what actually happened
When to useFirst 2+ weeks after publishingAfter reports are clean
Breakage riskZero — read-onlyReal — test before flipping
Typical mistakeForgetting to flip to enforce eventuallyFlipping too early, before reports clean

Common MTA-STS failures & fixes

Most MTA-STS deployments fail for one of five named reasons: (1) Policy file HTTPS unreachable (~30% — wrong path, bot-protection block, expired HTTPS cert), (2) Stale policy ID (~25% — id= not rotated after the policy body changed; senders cache the old policy for up to max_age seconds), (3) MX wildcard missing (~20% — hosted providers like Microsoft 365 require *.outlook.com-style wildcards), (4) Cert SAN mismatch (~15% — the policy host's HTTPS cert doesn't list the hostname), and (5) Premature enforce mode (~10% — skipped testing phase). A bonus failure worth flagging: max_age below 86,400 seconds is silently ignored by Google.

  1. 1

    Policy file HTTPS unreachable (~30%)

    Wrong path, HTTP→HTTPS redirect followed by crawlers but not by MTA-STS senders, Cloudflare bot protection blocking the fetch, expired HTTPS cert on `mta-sts.{domain}`. Fix: serve the file at the literal RFC-required URL with a valid public cert and no redirects.

  2. 2

    Stale policy ID (~25%)

    You edited the policy body but didn't rotate the `id=` in the DNS TXT record. Compliant senders cache the previous policy by `id=` for up to `max_age` seconds; your change doesn't take effect until they re-fetch. Fix: bump `id=` on every body change — a Unix timestamp works.

  3. 3

    MX wildcard missing (~20%)

    Your policy `mx:` lines don't match the live MX records. Hosted providers like Microsoft 365 need wildcards (`*.mail.protection.outlook.com`); Google Workspace needs the explicit `aspmx.l.google.com` plus the four `aspmxN.googlemail.com` fallbacks. Fix: add the wildcard or the explicit host, rotate `id=`.

  4. 4

    Cert SAN mismatch (~15%)

    The HTTPS cert on `mta-sts.{domain}` doesn't list the hostname in its SAN. Senders validate the cert against `mta-sts.{domain}` during the policy fetch; a SAN mismatch aborts the entire fetch. Fix: reissue a cert that covers `mta-sts.{domain}` — Let's Encrypt is fine.

  5. 5

    Premature enforce mode (~10%)

    Someone flipped `mode: testing` to `mode: enforce` before cleaning up reported mismatches. Legitimate senders start bouncing real mail. Fix: flip back to `testing`, fix every mismatch the TLS-RPT reports flag, and only return to `enforce` when the reports are clean for at least a week.

Manual verification

curl -I https://mta-sts.example.com/.well-known/mta-sts.txt
dig TXT _mta-sts.example.com
dig TXT _smtp._tls.example.com

MTA-STS vs. DANE vs. STARTTLS Everywhere

Three overlapping mechanisms, three different trust anchors. Pick the one your context supports; run both MTA-STS and DANE if you can.

AspectMTA-STSDANESTARTTLS Everywhere
Trust anchorPublic Web PKI (HTTPS cert)DNSSEC-signed TLSA recordCurated policy list (EFF, 2017)
PrerequisiteHTTPS on `mta-sts.{domain}`DNSSEC-signed zoneInclusion in the EFF list
Where it's bigUS + hosted providers (Gmail, M365)EU (DE, NL, gov.uk, Forum Standaardisatie)Effectively retired
Adoption 2026<1% global; 20.6% UK gov~5% .de / .nl; <1% .comNegligible
Failure modeHTTPS unreachable, ID drift, MX mismatchDNSSEC broken, TLSA rotationStale list entry

Rule of thumb: if your domain is DNSSEC-signed, run DANE for SMTP and MTA-STS side by side — they don't conflict, and compliant senders will use whichever they find first. If you can't or won't run DNSSEC (check via our DNSSEC checker), MTA-STS is the pragmatic single choice.

How do you rotate your policy ID safely?

Rotating the id= is the single most-important thing operators forget. Here's the minimum viable choreography:

  1. Edit the policy file body. Save.
  2. Deploy the new body to https://mta-sts.{domain}/.well-known/mta-sts.txt — verify it's live with curl -I https://mta-sts.{domain}/.well-known/mta-sts.txt.
  3. Update the DNS TXT record at _mta-sts.{domain} — rotate id= to something new (a Unix timestamp works: id=2026041801).
  4. Wait for the DNS TTL on the TXT to expire globally (usually a few minutes to an hour).
  5. Re-run this checker and confirm the new hash matches the new ID.

The common mistake is doing step 1-2 but forgetting step 3. Compliant senders keep caching the old policy — they have no reason to re-fetch, because the ID they already saw is still current. Your change effectively doesn't exist for them until max_age expires. That can be a week of confused support tickets before it corrects itself. The fix is automation: every time your CI deploys a new policy body, bump the ID in the same commit.

Common mistakes

  • Don't flip to enforce without reading your TLS-RPT reports first. Testing mode is there to surface the MX hosts, cert SAN issues, and wildcard gaps you forgot. Flip too early and legitimate senders start bouncing real mail.

  • Don't edit the policy body without rotating the id=. Senders cache by ID for up to max_age seconds. Your change effectively doesn't exist for them until the cache expires — could be a week of confused tickets.

  • Don't set max_age below 86,400. Google's ingestion silently ignores policies under one day. RFC 8461 §3.2 recommends at least one week (604,800 seconds).

  • Don't follow redirects from the policy file endpoint. MTA-STS senders don't follow them (RFC 8461 §3.3). Serve the file at the literal well-known URL with a valid SAN cert, or the whole fetch aborts.

Get help & support

Frequently Asked Questions

Ten questions, sourced from Reddit, Suped, and "People Also Ask" — the stuff MTA-STS operators actually google.

Still have questions about MTA-STS?

Contact Support