Email between servers is encrypted only when both sides agree to it, and nothing forces them to. MTA-STS lets you publish a rule that says: mail for my domain must arrive over TLS, to these servers, with a valid certificate. TLS-RPT tells you when senders could not follow that rule.
This guide covers what MTA-STS protects, the exact records and policy file to publish, a rollout that does not risk your mail, and the mistakes that break delivery. If your domain check flagged "MTA-STS missing" or "TLS-RPT missing", this is the fix.
What MTA-STS protects against
Mail servers deliver to each other with SMTP. They start in plaintext and offer an upgrade to TLS with a command called STARTTLS. That upgrade is opportunistic: if it fails, the sending server usually carries on without encryption.
That gives an attacker on the network path two options:
- Downgrade. The attacker removes the STARTTLS offer from the conversation. The sender sees no TLS support and delivers the message in plaintext.
- Fake certificate. The attacker presents a certificate that does not belong to your mail server. Most senders accept it anyway, because rejecting it would mean bounced mail.
MTA-STS (MTA Strict Transport Security, RFC 8461) closes both gaps. You publish a policy that lists your real mail servers and says TLS is required. A sender that supports MTA-STS fetches the policy over HTTPS, then refuses to deliver if the connection cannot be encrypted with a valid certificate for a listed server. Gmail and Microsoft 365 both honor MTA-STS when they send.
What it does not cover
MTA-STS protects mail sent to your domain, and only from senders that support it. It does nothing for mail you send. Your mail provider decides how your outbound connections behave.
It also does not prove who sent a message. That is the job of SPF, DKIM, and DMARC. If you have not enforced those yet, read DMARC from p=none to p=reject too. The two solve different problems: DMARC stops someone from pretending to be you, and MTA-STS stops someone from reading or tampering with mail on its way to you.
How MTA-STS and TLS-RPT fit together
You publish three things:
| Piece | Where it lives | What it does |
|---|---|---|
| MTA-STS TXT record | _mta-sts.example.com (DNS) |
Announces that a policy exists and gives its version id |
| Policy file | https://mta-sts.example.com/.well-known/mta-sts.txt |
States the mode, the allowed mail servers, and the cache time |
| TLS-RPT TXT record | _smtp._tls.example.com (DNS) |
Tells senders where to send daily reports about TLS failures |
The DNS record is a signal. The policy file is the actual policy. Senders look for the record, fetch the file, cache it, and check the record's id on later deliveries to see whether the policy changed.
Step 1: publish the TLS-RPT record
Start with reporting, so you have data from the first day of testing. TLS-RPT (RFC 8460) is one TXT record:
_smtp._tls.example.com. 3600 IN TXT "v=TLSRPTv1; rua=mailto:tls-reports@example.com"
Use a mailbox or alias you will actually read, or one that feeds a tool. An https: URL also works as the rua target if you have an endpoint that accepts reports.
Supporting senders, including large providers such as Google and Microsoft, send one JSON report per day, usually gzipped. Each report counts successful and failed TLS sessions and names the failure types, for example:
- an expired or mismatched certificate on your mail server
- STARTTLS not offered
- a policy that could not be fetched or was invalid
Reports show up only after a sender has delivered mail to you, so expect the first ones within a day or two.
Step 2: write the policy file
The policy is a plain text file with four kinds of lines. Start in testing mode:
version: STSv1
mode: testing
mx: mx1.example.net
mx: *.example.net
max_age: 86400
| Field | Meaning |
|---|---|
version |
Always STSv1. |
mode |
enforce, testing, or none (see the table below). |
mx |
One line per allowed MX host name. Repeat the line as needed. |
max_age |
How long senders may cache the policy, in seconds. The maximum is 31557600 (about a year). |
Get the mx lines from your own MX records
The mx lines must match the host names in your MX records. List them:
dig +short MX example.com
A *. wildcard covers exactly one label on the left, so *.example.net matches mx1.example.net but not a.b.example.net. The wildcard does not match example.net itself.
Some provider examples, to show the pattern. Check your own records rather than trusting this list, because providers change hosts:
- Google Workspace domains set up recently use
smtp.google.com. Older ones useaspmx.l.google.comandalt1.aspmx.l.google.comthroughalt4, which*.aspmx.l.google.comcovers. - Microsoft 365 uses a host under
mail.protection.outlook.com, which*.mail.protection.outlook.comcovers.
The three modes
| Mode | What senders do | When to use it |
|---|---|---|
testing |
Deliver even if TLS fails, and report the failure through TLS-RPT | First 1 to 2 weeks, and any time you change providers |
enforce |
Deliver only over TLS with a valid certificate to a listed MX; otherwise defer, then bounce | Once reports show no failures from legitimate senders |
none |
Treat the policy as withdrawn | Only when you are removing MTA-STS |
Testing mode is the one that makes MTA-STS safe to adopt. Nothing is blocked, and the reports tell you what would have been.
Step 3: serve the file over HTTPS
Senders fetch the policy from one fixed address:
https://mta-sts.example.com/.well-known/mta-sts.txt
The server must meet all of these conditions:
- A valid certificate that covers
mta-sts.example.com. - Status 200 with the file as the body.
- No redirects. Senders must not follow them, so a redirect to
wwwor to another path fails. Content-Type: text/plain.
You need a web host for the mta-sts subdomain with automatic HTTPS. Any static host that supports a custom domain and a managed certificate works, for example GitHub Pages, Cloudflare Pages, or Netlify. You can also use your existing web server or CDN. In most cases you point mta-sts.example.com at the host with a CNAME record.
mta-sts.example.com. 3600 IN CNAME your-site.pages.example.net.
Put the file in a folder named .well-known at the root of that site. Some static site builders skip folders that start with a dot, so check that the file is really published.
Step 4: publish the MTA-STS record
Once the file loads, add the TXT record that tells senders to look for it:
_mta-sts.example.com. 3600 IN TXT "v=STSv1; id=20261018T120000;"
The id is 1 to 32 letters and digits. A timestamp works well. Change it every time the policy file changes. Senders compare the id to the one they cached, and a changed id is their only cue to fetch the file again. If you edit the file and keep the old id, senders keep using the old policy.
Step 5: check it by hand
Before you wait for reports, confirm all three pieces:
dig +short TXT _mta-sts.example.com
curl -sS -i https://mta-sts.example.com/.well-known/mta-sts.txt
dig +short TXT _smtp._tls.example.com
In the curl output, look for HTTP/2 200, a content-type: text/plain header, and no location: header. If dig is not available, DNS over HTTPS works:
curl -s 'https://dns.google/resolve?name=_mta-sts.example.com&type=TXT' | jq -r '.Answer[].data'
You can also run the free domain check. It tests mail in transit as one of five areas of the domain health score: STARTTLS by mail provider, MTA-STS, TLS-RPT, and DANE. For MTA-STS it fetches the policy file, checks that it is valid, and compares the mx lines to your MX records. For each fix it gives you the exact records, and the policy file, to publish. No sign-up is needed.
A safe rollout
Move in this order, and do not skip the waiting.
- Publish TLS-RPT. Reports start arriving before the policy exists.
- Publish the policy in
testingmode withmax_age: 86400(1 day), and the MTA-STS record with a fresh id. - Read the reports for 1 to 2 weeks. Look for failures from senders you care about. Fix an expired certificate, a missing STARTTLS offer, or an
mxpattern that does not match. - Switch to
enforce. Editmode, change theid, and raisemax_ageto at least 1 week (604800). - Raise
max_ageover time. Once things are stable, use several weeks. A longer value protects senders from a downgrade of the policy itself, but it also means a mistake lingers longer.
A short max_age during testing means a bad policy expires from sender caches quickly. That is the point of the 1 day value.
Changing mail providers with MTA-STS enforced
This is where enforce mode bites. Senders cache your policy for max_age seconds. If the cached policy lists only your old mail hosts, senders refuse to deliver to the new ones, and mail is deferred and eventually bounced.
Do it in this order:
- Add the new provider's MX patterns to the policy file, keep the old ones, and change the
id. - Wait at least
max_ageseconds, so every sender's cache includes the new hosts. - Switch the MX records to the new provider.
- Keep both sets of patterns in the policy for at least
max_agemore, so mail still in flight is accepted. - Remove the old patterns and change the
idagain.
Removing MTA-STS
Do not just delete the file. Senders with a cached enforce policy would keep demanding TLS to hosts that may no longer exist.
- Publish a policy with
mode: noneand a newid. - Keep serving it for at least
max_age. - Remove the policy file and the
_mta-stsTXT record.
Mistakes that break mail or quietly turn the policy off
- A certificate that does not cover
mta-sts.example.com. Senders cannot fetch the policy and ignore it, or use a stale cached copy. A wildcard or a dedicated certificate for the subdomain both work, as long as it is valid and unexpired. - A redirect. Sending
mta-sts.example.comtowwwor forcing a trailing-slash redirect makes the fetch fail. - An HTML page instead of the file. A catch-all error page, a login wall, or a wrong
Content-Typemakes the policy invalid. - Editing the file without changing the id. Senders keep the old policy until the cache expires.
mxpatterns that do not match the real MX hosts. Inenforcemode, senders defer mail to hosts the policy does not list, and eventually bounce it. This is the mistake that costs mail.- A
max_agethat is too long, too early. If you set a year on day one and then find a mistake, senders keep the bad policy for months. Raise the value in steps. - Letting the certificate expire. The policy fetch fails, and the mail server certificate is a separate thing that can also expire. Both need renewal.
The last mistake is easy to miss, because nothing breaks right away: senders keep using the cached policy until it expires. A free DNS Autopilot account re-checks your domain every day, which catches an expired certificate on the mta-sts host, or an MX change that the policy no longer matches, before senders do.
MTA-STS and DANE
DANE for SMTP (RFC 7672) is the other way to require TLS. You publish TLSA records that pin the certificate of your mail servers. It needs DNSSEC on your domain and on the domain of your MX hosts, which is not always something you control when a provider hosts your mail.
MTA-STS needs no DNSSEC, only HTTPS. You can use both. A sender that supports DANE uses it, and one that supports only MTA-STS uses that.
FAQ
Do I need MTA-STS if my mail provider already uses TLS?
Yes, if you want TLS to be required rather than likely. Your provider's TLS support is opportunistic, so an attacker who strips STARTTLS can still force plaintext delivery from senders. MTA-STS makes supporting senders refuse that downgrade for mail sent to you.
What is the difference between MTA-STS testing and enforce mode?
In testing mode, senders deliver mail even when TLS fails, and report the failure through TLS-RPT. In enforce mode, they deliver only over TLS with a valid certificate to a host in your mx list, and defer or bounce the message otherwise. Start with testing and move to enforce after 1 to 2 weeks of clean reports.
Do I need TLS-RPT to use MTA-STS?
No, but you should publish it. MTA-STS works without TLS-RPT, but you would not see failures, so you could not tell whether enforce mode is safe. The TLS-RPT record is a single TXT record at _smtp._tls.example.com.
Does MTA-STS protect the mail I send?
No. It protects mail delivered to your domain by senders that support it. How your outgoing mail is encrypted depends on your mail provider and on the policies of the domains you write to.
Where do I host the mta-sts.txt file?
Host it on any web server that serves https://mta-sts.example.com/.well-known/mta-sts.txt with a valid certificate. A static host such as GitHub Pages, Cloudflare Pages, or Netlify is enough, as is your existing web server or CDN. The file must return status 200 as text/plain with no redirects.
How do I change an MTA-STS policy safely?
Edit the policy file, then change the id in the _mta-sts TXT record. The new id tells senders to fetch the file again. If the change adds a new mail provider, publish the new mx patterns and wait for max_age before you switch the MX records.