The problem MTA-STS solves

SMTP between mail servers negotiates TLS with STARTTLS, and that negotiation happens in cleartext. An attacker positioned on the network can strip the STARTTLS advertisement out of the conversation, and both servers will fall back to delivering the message unencrypted — neither side treats it as an error, because opportunistic TLS is defined to degrade quietly. There is also nothing forcing the receiving server to present a certificate that validates. A sender will generally accept a self-signed or mismatched certificate rather than fail delivery.

MTA-STS fixes both halves. A domain publishes a policy saying “TLS is mandatory when delivering to me, the certificate must validate, and these are the only MX hostnames that count.” Senders that honour the policy cache it and refuse to deliver if those conditions aren’t met.

This is a different job from SPF, DKIM and DMARC. Those authenticate who a message claims to be from. MTA-STS protects the transport on the way in. A domain can have a perfect DMARC setup and still have its inbound mail read in transit.

The three pieces

MTA-STS is unusual among mail standards in that DNS alone isn’t enough. Three things have to exist and agree:

1. A TXT record at _mta-sts.<domain>

v=STSv1; id=20260829000000Z

This only announces that a policy exists and gives it a version id. It carries none of the actual policy.

2. A host at mta-sts.<domain> serving the policy over HTTPS

The file lives at exactly https://mta-sts.<domain>/.well-known/mta-sts.txt, served as text/plain, with no redirect — RFC 8461 forbids senders from following redirects, so a redirect is equivalent to serving nothing. The certificate must be valid for mta-sts.<domain> itself.

3. The policy file

version: STSv1
mode: enforce
mx: mx1.example.com
mx: mx2.example.com
max_age: 604800

mode is enforce, testing, or none. mx lists the permitted hostnames, one per line, optionally with a single leading wildcard (*.example.net matches exactly one label — mx1.example.net but not example.net and not a.b.example.net). max_age is how many seconds senders should cache the policy.

TLS-RPT

TLS-RPT is a single TXT record at _smtp._tls.<domain>:

v=TLSRPTv1; rua=mailto:[email protected]

Senders that support it send a daily JSON report of TLS negotiation outcomes for your domain — successes, failures, and why. Unlike DMARC’s rua, TLS-RPT also accepts an https:// endpoint.

It matters most in exactly the case MTA-STS itself can’t tell you about. In mode: testing, failures are silent by design: senders log the problem and deliver anyway. Without TLS-RPT, a testing-mode policy generates no evidence whatsoever, which means you have no basis for deciding whether it’s safe to move to enforce. That’s why the MTA-STS Checker reports on both together.

What actually goes wrong

The certificate doesn’t cover mta-sts.<domain>. This is the most common MTA-STS mistake by a wide margin. A certificate issued for example.com and www.example.com does not cover mta-sts.example.com, so the policy fetch fails certificate validation and every sender falls back to opportunistic TLS. The domain is now announcing protection it isn’t providing, and nothing about it is visible in normal mail flow.

The policy host doesn’t exist. The TXT record gets published, the policy file never gets deployed. Same outcome as above.

The mx list stops matching the MX records. This is the one that breaks mail rather than silently failing open. If you change mail providers, add a backup MX, or a provider adds a new hostname, and the policy still lists only the old hosts, then under mode: enforce every sender honouring MTA-STS refuses to deliver to the uncovered host. Mail bounces, and there is nothing in SPF, DKIM or DMARC to explain why — those all still pass. This is the specific cross-check the MTA-STS Checker exists to do.

The id doesn’t change after an edit. Senders keep a cached policy until max_age expires or the id in the TXT record changes. Fix the policy file without bumping the id and your fix doesn’t reach anyone who already has the old one — for up to max_age seconds.

Going straight to enforce. An enforcing policy with an incomplete mx list is a self-inflicted outage. Start in testing with TLS-RPT configured, read the reports for a couple of weeks, then switch. The MTA-STS Policy Generator defaults to testing mode for this reason.

MTA-STS and DANE

DANE (RFC 7672) solves a similar problem by publishing TLSA records in DNSSEC-signed DNS instead of an HTTPS-hosted policy. The two are not mutually exclusive and several large providers publish both. The practical difference is that DANE requires DNSSEC on your domain, while MTA-STS requires a web server with a valid certificate. DMARCLoop’s tools currently check MTA-STS and TLS-RPT, not DANE.

Turning it off

Don’t just delete the records. Senders hold cached policies for up to max_age, and if a cached enforcing policy outlives your MX records, mail bounces. Publish mode: none (bumping the id), leave it in place until the longest max_age you ever published has elapsed, and only then remove the records.