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.