In the first week of January 2026, a scan of the top one million domains found 7,377 of them publishing an MTA-STS policy. That is 0.7 percent, and roughly one in five of those policies did not actually work. Compare that with SPF and DMARC, which most organizations of any size have had in place for years.

The gap is not an accident. SPF, DKIM and DMARC are the records people get told to publish, and all three do the same job: they authenticate the sender. SPF checks whether the connecting IP is authorized to send for the envelope domain. DKIM verifies a signature over the message. DMARC ties those results to the visible From domain and tells receivers what to do when they fail. Every one of those checks happens after the message arrives. None of them says anything about how it got there.

Two records cover the trip itself. Almost nobody publishes them.

Opportunistic TLS and the silent fallback

Server-to-server SMTP still starts in the clear. The sending server opens a TCP connection on port 25, sends EHLO, and reads back a list of extensions the receiving server supports. One of those lines advertises STARTTLS. If the client sees it, it issues STARTTLS, the server answers 220, and a TLS handshake begins. If the client does not see it, the client sends the message in plaintext.

That is the whole mechanism, and the weakness is right there in the original specification. RFC 3207 states plainly that a man-in-the-middle attack can be launched by deleting the STARTTLS response from the server, which would cause the client not to try to start a TLS session. The same section names a second variant: let the server advertise STARTTLS, then alter the client's request and the server's response so the negotiation fails. Everything exchanged before the handshake is cleartext and, in the RFC's words, may be modified by an active attacker.

RFC 7672, which specifies DANE for SMTP, is blunter about what this means. The server's indication of TLS support can be easily suppressed by an attacker in the middle. Pre-DANE SMTP TLS security can therefore be subverted by simply downgrading a connection to cleartext. No TLS security feature can prevent this, because the attacker can simply disable TLS.

The reason this is dangerous rather than merely theoretical is that opportunistic means opportunistic. The sending server does not treat a missing STARTTLS as an error. It delivers anyway. There is no bounce, no warning, no log entry that anyone reads. The message goes out in the clear and the sender's monitoring shows a successful delivery.

This happens at scale. A 2015 measurement of Gmail's inbound traffic identified 41,405 servers across 4,714 autonomous systems and 193 countries showing evidence of corrupted STARTTLS negotiation. In Tunisia, 96.13 percent of messages arriving at Gmail had STARTTLS stripped. Seven countries exceeded 20 percent. The same study found roughly 14,600 publicly reachable DNS servers returning falsified MX records, which is the other half of the problem: without DNSSEC, the MX lookup that decides where mail goes is itself unauthenticated.

What the _mta-sts TXT record actually does

MTA-STS, specified in RFC 8461, lets a receiving domain publish a policy that says: my mail servers support STARTTLS, here are their names, and if you cannot get an authenticated TLS session to one of them, do not deliver.

Discovery starts with one TXT record at the _mta-sts label, so for a domain it lives at _mta-sts followed by the domain name, and it carries a version of STSv1 plus an id. Only two fields matter. The version field must be first and must be STSv1. The id field is one to thirty-two alphanumeric characters, and it is not a version number in any meaningful sense. It is an opaque change token. If a resolver returns multiple TXT records at that name, records not beginning with the STSv1 version tag are discarded, and if the result is not exactly one syntactically valid record, senders must assume the domain has no policy at all.

The TXT record carries no policy. It is a pointer plus a cache-invalidation signal, and that design is deliberate: a sender with a cached policy can check whether it is stale using a single DNS lookup, without an HTTPS request.

The policy file

The policy itself is fetched by HTTPS GET from a fixed location. The policy host name is built by prepending mta-sts to the domain, and the path is /.well-known/mta-sts.txt.

Several rules around that fetch trip people up. The certificate presented by the policy host must be valid for the policy host name and chain to a root the sending server trusts. Only an HTTP 200 response counts as a valid policy. HTTP 3xx redirects must not be followed. HTTP caching must not be used. Senders should check that the media type is text/plain.

The file is a set of key and value pairs, one per line. Google's live policy for its own domain is a good short example: version STSv1, mode enforce, three mx entries covering its inbound hosts, and a max_age of 86400. Microsoft publishes an equally terse one: mode enforce, a single wildcard mx entry covering its protection endpoints, and a max_age of 604800.

Each MX pattern needs its own mx key on its own line. Patterns are either fully specified names or a wildcard prefix, and the wildcard stands for exactly one leftmost label, so a wildcard at the third level matches a host one label deeper and no further.

The three modes

  • enforce — sending servers must not deliver to hosts that fail MX matching, fail certificate validation, or do not support STARTTLS.
  • testing — senders that also implement TLS reporting send a failure report, but the message may be delivered as though nothing failed.
  • none — senders treat the domain as having no active policy. This is the clean opt-out path, not a mistake.

One safety valve is worth knowing. When a message fails under an enforce policy, a compliant sender must not permanently fail delivery before checking DNS for an updated policy id, and should treat the failure as transient and retry. That is what makes it possible to fix a bad policy on a live domain without losing mail outright.

max_age is the security parameter

The max_age value is a non-negative integer in seconds with a ceiling of 31557600, about one year. The RFC expects real values to be in the range of weeks or greater, and Google suggests 604800 to 1209600 while a domain is in testing mode.

The reason to prefer long values is that the cache is the defense. First contact is trust on first use. An attacker who can block DNS responses can make a protected domain look unprotected, and the natural time to attempt that is when a sender has never mailed the domain before or when its cached policy is about to expire. RFC 8461 says implementers should prefer max_age values as long as is practical and should not wait for expiry to refresh. A background refresh running daily or weekly forces an attacker to suppress discovery consistently across the entire cache lifetime rather than winning once.

TLS-RPT: the record that tells you whether any of this works

MTA-STS gives you no feedback on its own. RFC 8460 adds that with a second TXT record at the _smtp._tls label, carrying a version of TLSRPTv1 and an rua destination. The rua field accepts mailto and https URIs and a comma-separated list of them. With https, reports arrive as an HTTP POST. With mailto, reports must carry a valid DKIM signature from the reporting domain, must not use the body-length tag, and are ignored if unsigned. Senders must deliver reports despite TLS failures, which means the report about your broken TLS may itself arrive unencrypted.

Reports are JSON, normally covering a full UTC day, usually delayed by a few hours to spread load, and typically compressed with a filename built from the sender, the policy domain, the window timestamps and a unique ID.

The fields that carry the real information are these. Each entry has a policy object with a policy-type of sts, tlsa, or the literal string no-policy-found, plus policy-string, policy-domain and mx-host. Then a summary with total-successful-session-count and total-failure-session-count. Then failure-details, which is where diagnosis happens: result-type, sending-mta-ip, receiving-mx-hostname, receiving-mx-helo, receiving-ip, failed-session-count, additional-information and failure-reason-code.

The result-type values are what you actually read. The negotiation failures are starttls-not-supported, certificate-host-mismatch, certificate-expired, certificate-not-trusted, and validation-failure as a catch-all. The MTA-STS-specific ones are more useful for debugging your own deployment:

  • sts-policy-fetch-error — the sender could not retrieve the policy, for instance because the policy host was unreachable. This points at your web host, not your mail server.
  • sts-policy-invalid — the policy was retrieved but did not parse or validate.
  • sts-webpki-invalid — the policy could not be authenticated by certificate validation, meaning the certificate on the policy host failed.

Two readings matter most in practice. A policy-type of no-policy-found tells you a sender looked and found neither DANE nor MTA-STS, which usually means your TXT record is not resolving the way you think. And total-successful-session-count is explicitly designed as a heartbeat: a report arriving with successes proves the reporting path works, which is the only way to distinguish no failures from nobody is reporting.

Where DANE fits, and why most organizations skip it

DANE for SMTP publishes TLSA records in DNS and authenticates them with DNSSEC. RFC 8461 describes the two as solving the same problem by different means: DANE requires DNSSEC for authentication, while MTA-STS instead relies on certification authorities and does not require DNSSEC, at a cost of risking malicious downgrades.

That cost is real. Because a DNSSEC-validating resolver can prove the absence of a record, DANE resists the make-it-look-like-there-is-no-policy attack in a way MTA-STS cannot. RFC 8461 concedes the point directly, describing resistance to that class of downgrade as a feature of DANE, due to its use of DNSSEC for policy discovery.

Organizations still reach for MTA-STS, for two practical reasons. First, MTA-STS needs no DNSSEC on either side, so a domain owner can deploy it without the registrar, DNS host and mail provider all signing. Second, MTA-STS has testing mode. DANE has no per-domain soft-launch; the closest equivalent is publishing TLSA records for only some MX hosts, which is a different and coarser thing. If both are deployed, senders implementing both must not let an MTA-STS policy override a failing DANE validation.

Sender-side support is now the easy part. Google states that Gmail messages comply with MTA-STS when sent to external servers with a policy in enforce mode. Microsoft's documentation, updated in July 2026, says all messages sent outbound from Exchange Online to MTA-STS-protected recipients are validated against the standard's TLS enforcement and certificate checks, with nothing for administrators to do. Since March 2026, Exchange Online outbound connectors also expose per-connector modes, with Opportunistic as the default, Mandatory for SMTP DANE, and None to disable validation for a specific partner path.

The traps

The failure modes here are quiet, which is why the invalid-policy rate stays around one in five. The most common causes found in that January 2026 scan were missing DNS records at 34 percent, HTTPS certificate problems at 25 percent, and TLS validation failures at 6 percent.

Publishing the TXT record without the policy file. This is the big one, and the specification makes it silent by design: if a valid TXT record is found but no policy can be fetched over HTTPS for any reason, and there is no valid cached policy, senders must continue delivery as though the domain never implemented MTA-STS. You get an authoritative-looking DNS record, zero protection, and no error anywhere.

Bumping the policy without bumping the id. Senders compare the id in the TXT record against their cached copy to decide whether to re-fetch. Leave the id unchanged and they keep enforcing the old policy for the full max_age, which you probably set to a week or more. Add a new MX and forget the id, and enforce-mode senders will refuse to deliver to the host you just added, for as long as the cache lives.

Updating in the wrong order. Publish the new policy file first, then change the TXT record id. Do it the other way around and a sender that sees the new id may fetch and cache the old policy body, locking in exactly the version you were trying to replace.

Getting the policy host certificate wrong. The certificate must be valid for the mta-sts host name, not for the apex and not for www. And because 3xx redirects must not be followed, pointing the policy host at a redirect to your main website breaks the policy without breaking anything a browser would show you.

Letting the mx list drift. Every host that receives your mail has to appear in the policy. Insert a filtering gateway, add a backup MX, migrate providers, and any host missing from the policy becomes undeliverable to enforce-mode senders.

Removing MTA-STS by deleting the records. Deleting the TXT record and the policy file leaves cached enforce policies in force at every sender that has one. The supported path is to publish mode none with a short max_age, change the id so senders fetch it, wait for previously served policies to expire, and only then remove the endpoints.

One structural point is worth ending on, because it changes how the records get prioritized. An MTA-STS policy protects mail arriving at your domain, not mail leaving it. What you publish constrains other people's sending servers. Your own outbound protection is a property of whoever runs your mail platform and whether it honors other domains' policies, which is a procurement and configuration question rather than a DNS one. TLS-RPT is the only place those two halves meet, because the reports describe what other senders observed on the wire when they tried to reach you. That is the one signal in this entire stack that comes from outside your own infrastructure, and it is the reason the reporting record is worth publishing even before the policy is in enforce mode.