Mail in transit

MTA-STS and TLS-RPT: how to require TLS for mail to your domain

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:

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:

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:

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:

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.

  1. Publish TLS-RPT. Reports start arriving before the policy exists.
  2. Publish the policy in testing mode with max_age: 86400 (1 day), and the MTA-STS record with a fresh id.
  3. 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 mx pattern that does not match.
  4. Switch to enforce. Edit mode, change the id, and raise max_age to at least 1 week (604800).
  5. Raise max_age over 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:

  1. Add the new provider's MX patterns to the policy file, keep the old ones, and change the id.
  2. Wait at least max_age seconds, so every sender's cache includes the new hosts.
  3. Switch the MX records to the new provider.
  4. Keep both sets of patterns in the policy for at least max_age more, so mail still in flight is accepted.
  5. Remove the old patterns and change the id again.

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.

  1. Publish a policy with mode: none and a new id.
  2. Keep serving it for at least max_age.
  3. Remove the policy file and the _mta-sts TXT record.

Mistakes that break mail or quietly turn the policy off

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.

Check your MTA-STS and TLS-RPT

Free, no sign-up: a 0 to 100 score and the exact record for each fix in about three seconds.

Related guides

Check your domain, then watch it

Add a domain to a free account and we re-check it every day and read its DMARC reports. Free for one domain.