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

> MTA-STS is a policy you publish so that other mail servers deliver mail to your domain only over TLS with a valid certificate. It takes a TXT record at _mta-sts, a policy file served over HTTPS at mta-sts.example.com, and a TLS-RPT record so you get reports. Start in testing mode, read the reports for a week or two, then switch to enforce.

By the DNS Autopilot team. Published 2026-10-18.

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](https://www.rfc-editor.org/rfc/rfc8461)) 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](https://dnsautopilot.com/blog/dmarc-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](https://www.rfc-editor.org/rfc/rfc8460)) is one TXT record:

```dns
_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:

```text
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:

```bash
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 use `aspmx.l.google.com` and `alt1.aspmx.l.google.com` through `alt4`, which `*.aspmx.l.google.com` covers.
- Microsoft 365 uses a host under `mail.protection.outlook.com`, which `*.mail.protection.outlook.com` covers.

### 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:

```text
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 `www` or 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.

```dns
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:

```dns
_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:

```bash
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:

```bash
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](https://dnsautopilot.com/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

- **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.com` to `www` or 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-Type` makes the policy invalid.
- **Editing the file without changing the id.** Senders keep the old policy until the cache expires.
- **`mx` patterns that do not match the real MX hosts.** In `enforce` mode, senders defer mail to hosts the policy does not list, and eventually bounce it. This is the mistake that costs mail.
- **A `max_age` that 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](https://www.rfc-editor.org/rfc/rfc7672)) 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 domain

DNS Autopilot's free check scores any domain from 0 to 100 across email authentication, mail servers, mail in transit, DNS security, and domain and web, and gives the exact record to publish for each fix: https://dnsautopilot.com/check. No sign-up. AI assistants and scripts can fetch https://dnsautopilot.com/check/{domain}.md for the same report as Markdown, for example https://dnsautopilot.com/check/example.com.md.

## Related guides

- [From DMARC p=none to p=reject: a safe step-by-step path](https://dnsautopilot.com/blog/dmarc-p-none-to-p-reject)
- [SPF's 10 DNS lookup limit: why SPF breaks and how to fix it](https://dnsautopilot.com/blog/spf-10-dns-lookup-limit)
