Dr.Who
← blog

MTA-STS policy not found or not enforced: the three pieces senders check

· mta-sts · smtp · tls · email-security · dns

mta-stssmtptlsemail-securitydns

If your MTA-STS policy is "not found" or silently not being enforced, one of three required pieces is broken: the _mta-sts.<domain> TXT record is missing or carries a stale id, the policy file is not reachable at https://mta-sts.<domain>/.well-known/mta-sts.txt over valid TLS, or that file is served with the wrong Content-Type. A sending mail server (RFC 8461) needs all three to agree before it will hold mail to your MX servers to a strict TLS standard. Miss any one and the sender quietly falls back to opportunistic TLS.

The TXT record advertises the policy and its version

Senders first look up a TXT record at _mta-sts.<domain>. It declares that you publish a policy and gives it a version id:

_mta-sts.example.com.  IN  TXT  "v=STSv1; id=20260622T120000"

The id is an opaque string — many people use a timestamp — and it is the cache key. A sender that already fetched your policy keeps using its cached copy until the id changes. This is the most common reason an "updated" policy is not being enforced: you edited the policy file but left the old id, so senders never re-fetch. Bump the id (any new value) every time you change the policy file.

If this TXT record is absent or malformed, the sender concludes you have no MTA-STS policy and stops there.

The policy file must be served over valid HTTPS

Next the sender fetches the actual policy over HTTPS — never HTTP — from a fixed location on a dedicated host:

https://mta-sts.example.com/.well-known/mta-sts.txt

Two things break here constantly. First, the mta-sts.example.com host needs a valid, trusted TLS certificate covering that exact name; an expired, self-signed, or wrong-host certificate makes the fetch fail and the policy is treated as absent. Second, the body must be served as Content-Type: text/plain — an HTML error page, a redirect to a login wall, or text/html from a misconfigured static host all cause senders to reject the policy.

A correct policy file looks like this:

version: STSv1
mode: enforce
mx: mail.example.com
mx: *.mail.example.com
max_age: 604800

Each mx line must match a hostname in your actual MX records (wildcards are allowed for one label). max_age is in seconds — 604800 is one week — and tells the sender how long to cache. The mode line is none, testing, or enforce; only testing and enforce cause senders to act on the policy.

Check your MTA-STS setup end to end →

Quick checklist when it is "not found"

  • TXT at _mta-sts.<domain> exists, parses as v=STSv1; id=..., and the id is new since your last policy edit.
  • https://mta-sts.<domain>/.well-known/mta-sts.txt returns 200 over a valid, non-expired certificate for that exact host.
  • The response Content-Type is text/plain with no redirect.
  • Every mx line in the file maps to a real MX hostname.

Further reading