SPF, DKIM and DMARC stop others forging your name (you can check your DMARC record), but none of them stops a sending server from delivering mail to you in plaintext. MTA-STS lets you publish a policy saying your mail servers support authenticated TLS, and TLS-RPT tells you when senders could not get it. You can deploy both with two DNS records and one text file, and you can start in a mode that is meant for soft deployment.
What STARTTLS leaves open
Server-to-server mail encryption uses the STARTTLS extension, and it is opportunistic. RFC 8461 describes the weak point: an attacker who can delete the "250 STARTTLS" response from the SMTP session, or redirect it by overwriting the resolved MX record, can force a downgrade or intercept the session.
DANE is the other fix, defined in RFC 7672, but it requires DNSSEC. MTA-STS relies on certification authorities instead and does not need DNSSEC, "at a cost of risking malicious downgrades" in the RFC's own words. If you already run DANE, the two do not conflict: senders implementing MTA-STS must not let it override a failing DANE validation.
The NCSC guidance on email security says your service should be capable of sending and receiving email using TLS, and that you should protect all your domains, including those at cloud providers such as Google G Suite and Microsoft O365.
Step one: the policy, in testing mode
MTA-STS has two parts. A TXT record at _mta-sts.example.com announces that a policy exists and which version it is:
_mta-sts.example.com. IN TXT "v=STSv1; id=20250101000000Z;"
The id is letters and digits, up to 32 characters, and must uniquely identify this version of the policy. There is no implied ordering, so a timestamp is a habit rather than a requirement. Publish exactly one such record: senders discard records not starting with v=STSv1;, and if the count is not one afterwards they assume you have no policy.
The policy itself is fetched over HTTPS from a fixed address, built by putting mta-sts in front of your domain:
https://mta-sts.example.com/.well-known/mta-sts.txt
Serve it as text/plain, because senders are told to check the media type. The file looks like this:
version: STSv1
mode: testing
mx: mail.example.com
mx: *.example.net
max_age: 604800
Each mx: line is its own entry, either a full hostname or a wildcard suffix such as *.example.net. List every host in your live MX records, including a cloud provider's.
The three modes are enforce, testing and none. The RFC describes testing as an optional mode that enables soft deployments to detect policy failures, which is why you start there.
The max_age is in seconds, up to 31557600, and 604800 (one week) is the RFC's own example. The RFC expects production values typically in the range of weeks or greater. My advice: keep it at a week or less while testing, so a corrected policy reaches senders quickly, and raise it once enforce has been stable.
Step two: turn on TLS-RPT
Detection only works if senders tell you what they saw. You publish a TXT record at _smtp._tls.example.com:
_smtp._tls.example.com. IN TXT "v=TLSRPTv1;rua=mailto:tlsrpt@example.com"
The rua can also be an https URI, in which case senders POST the report to it, and a comma-separated list is allowed. As with the MTA-STS record, exactly one TXT record must start with v=TLSRPTv1;, otherwise senders assume you do not implement it.
If you choose mailto, use a dedicated mailbox. Senders deliver these reports even when TLS fails, so a report may arrive unencrypted. Reports sent by email must carry a valid DKIM signature from the reporting domain, and the RFC says recipients must ignore those without one. Discard unsigned reports rather than acting on them.
Check what senders see
Query both records and fetch the policy file from outside your network:
dig TXT _mta-sts.example.com
dig TXT _smtp._tls.example.com
curl -si https://mta-sts.example.com/.well-known/mta-sts.txt
The dig output should show one record each, with the v= prefix first. The curl output should show a 200, Content-Type: text/plain and the policy body, so check that mode and every mx: line are what you intended. Fix any certificate error curl reports before you publish the TXT record.
Reading the reports
Reports are JSON files covering a time frame, with a delivery summary of success and failure counts. The RFC groups failures into negotiation, policy, general and transient failures. Reports may arrive compressed (the RFC defines application/tlsrpt+gzip), so unpack one first:
gzip -dc report.json.gz | jq .
The field names are defined in section 4.4 of RFC 8460. Read the summary counts first, then the failure entries.
A report with high success and no failures is what you want to see. The RFC notes that a report can act as a heartbeat showing TLS is negotiated as expected, and a steady run of clean reports is your evidence for moving on. Failures that name one of your own MX hosts point at a certificate or mx pattern you need to fix. One sender with a broken stack is their problem.
A jump in STARTTLS failures that you cannot tie to a change should go to whoever handles incidents, or to our incident response team if you have no one.
Moving to enforce
Wait until the reports are clean across your normal mail patterns, including quiet senders such as monthly invoicing systems. Then change mode: testing to mode: enforce and change the id in the TXT record, because senders compare it with their cached copy to learn that something changed.
Senders may cache a policy for up to max_age from the last fetch, so a mistake can linger. Deleting the TXT record does not remove a cached policy either, as the RFC points out. RFC 8461 section 8.3 covers removal, and you should read it before you need it.
Where to start
- List your live MX hosts, including any cloud provider's, and confirm each presents a valid certificate that matches its name.
- Set up the
mta-stshost over HTTPS and serve the policy file astext/plainwithmode: testing. - Publish the single
_mta-stsTXT record with a freshid, then run thedigandcurlchecks above. - Publish the
_smtp._tlsTXT record pointing to a dedicated mailbox or HTTPS endpoint, and check your overall setup with our email security checker. - Review reports for at least one full business cycle, including month-end runs (for most organisations, a month). Fix every failure you own, then switch to
enforceand change theid.
