# MTA-STS (SMTP MTA Strict Transport Security, RFC 8461)

> How receiving domains publish an enforceable TLS policy via a DNS TXT record plus an HTTPS policy file, and how sending MTAs discover, cache, and apply it.

Source: emailmarketing.net — https://emailmarketing.net/learn/transport-security/mta-sts

MTA-STS (RFC 8461) lets a receiving domain declare that it supports TLS for inbound SMTP and that sending MTAs should refuse to deliver to it over insecure channels. It closes the classic STARTTLS weakness: because STARTTLS is negotiated in cleartext, an active attacker can strip it (downgrade) or impersonate the MX. MTA-STS gives senders an out-of-band, cached policy to detect both.

Unlike [DANE for SMTP](https://emailmarketing.net/learn/transport-security/dane-smtp), MTA-STS does **not** require DNSSEC. It leans on the Web PKI (CA-signed certificates) and HTTPS instead — easier to deploy, but weaker against attackers who can tamper with DNS on first contact (see Security model below).

## Roles

- **Policy Domain** — the recipient domain publishing the policy (the RFC5321 mail domain, i.e. the part after `@`).
- **Sending MTA** — discovers, caches, and applies the policy when delivering to that domain.

## Policy discovery: the DNS TXT record

The presence (and version) of a policy is signaled by a TXT record at `_mta-sts.<policy-domain>`:

```
_mta-sts.example.com. IN TXT "v=STSv1; id=20160831085700Z;"
```

| Field | Required | Value |
|---|---|---|
| `v` | yes | `STSv1` (only defined version) |
| `id` | yes | 1–32 alphanumeric chars uniquely identifying this policy instance; senders compare it against their cached policy's id to detect updates |

Processing rules:
- Fields are semicolon-separated key/value pairs; unknown fields are ignored.
- If multiple TXT records are returned, discard any not beginning with `v=STSv1;`. If more than one valid record remains, the result is ambiguous (misconfiguration).
- Multiple character-strings in one record are treated as concatenated.
- CNAMEs at `_mta-sts.<domain>` are followed normally (this enables delegation — see below).

The TXT record only *announces* a policy and its version. The policy content itself lives at the HTTPS endpoint.

## Policy retrieval: the HTTPS well-known endpoint

The policy is fetched with an HTTPS GET from a "Policy Host" formed by prepending the literal label `mta-sts` to the Policy Domain:

```
https://mta-sts.example.com/.well-known/mta-sts.txt
```

Fetch requirements:

| Requirement | Rule |
|---|---|
| Certificate | Valid X.509 for the `mta-sts` DNS-ID (e.g. `mta-sts.example.com`), chained to a root CA trusted by the sender, non-expired; wildcard match only for the complete left-most label |
| HTTP status | Must be 200; **redirects must not be followed** |
| HTTP caching | Must not be used (freshness is governed by `max_age`, not HTTP cache headers) |
| Content-Type | `text/plain` recommended; `charset=utf-8` or `charset=us-ascii` accepted |
| Timeout | Suggested: 1 minute |
| Max policy size | Suggested: 64 KB |
| Failed-fetch rate limit | At most one attempt per 5 minutes per policy version id |

## Policy file format

CRLF-separated `key: value` pairs:

```
version: STSv1
mode: enforce
mx: mail.example.com
mx: *.example.net
mx: backupmx.example.com
max_age: 604800
```

| Field | Required | Value |
|---|---|---|
| `version` | yes | `STSv1` |
| `mode` | yes | `enforce` \| `testing` \| `none` |
| `max_age` | yes | Cache lifetime in seconds, max `31557600` (1 year); expected to be weeks or greater |
| `mx` | for enforce/testing (optional for none) | One pattern per `mx:` line; either a fully specified host (`mail.example.com`) or a wildcard for the left-most label only (`*.example.net`); IDNs must be Punycode A-labels |

Parsing: unknown fields are ignored (extensibility); for duplicated non-repeatable fields (everything except `mx`), only the first occurrence counts.

### MX matching rules

A candidate MX host is valid if its MX record name matches one of the `mx` patterns (RFC 6125 rules, wildcard restricted to the entire left-most label):

| Pattern | Matches | Does not match |
|---|---|---|
| `*.example.com` | `mail.example.com` | `example.com`, `foo.bar.example.com` |
| `example.com` | `example.com` | anything else |

## The three modes

| Mode | Sender behavior |
|---|---|
| `enforce` | MUST NOT deliver to hosts that fail MX matching, fail certificate validation, or don't offer STARTTLS. Failing messages are treated as **transient** errors (retry), and the sender must re-check DNS for an updated policy before permanently failing a message |
| `testing` | Deliver even on validation failure, but report failures via [TLS-RPT](https://emailmarketing.net/learn/transport-security/tls-rpt) if implemented. This is the safe on-ramp: exercise the full validation path and read reports before flipping to enforce |
| `none` | Treat the domain as having no active policy; used for graceful opt-out |

## Sender-side requirements

- MUST support TLS 1.2 or higher.
- MUST support the TLS SNI extension.
- The receiving MTA's certificate MUST be non-expired, MUST chain to a root CA trusted by the sender, and MUST contain a SAN DNS-ID matching the host per RFC 6125. Revocation MAY be checked (OCSP, CRLs).

## Caching and refresh

- Cache a fetched policy for up to `max_age` seconds from the last fetch.
- Before permanently failing a delivery under an `enforce` policy, check DNS for a newer policy (changed `id`) — the recipient may have fixed a broken policy.
- SHOULD refresh proactively (e.g., a daily background fetch) rather than waiting for expiry — this shrinks the window in which an attacker can block discovery.
- If the TXT record is found but the policy fetch fails **and no valid cached policy exists**: continue delivery as if MTA-STS were not implemented (fail open on first contact).
- If no live policy is discoverable but a valid, unexpired cached policy exists: apply the cached policy (this is the core downgrade protection).

## Security model

MTA-STS is **trust on first use**: until a sender has cached a policy, an attacker who can block DNS responses or the HTTPS fetch can make the domain appear policy-free. Once cached, the policy protects deliveries for `max_age` — hence the RFC's guidance that `max_age` SHOULD be "as long as is practical".

DoS vector: an attacker who can modify a recipient domain's DNS can publish a malicious policy (long `max_age`, wrong `mx` constraints) that senders cache. Recovery relies on senders re-checking DNS before permanent failure.

Contrast with DANE: DANE (DNSSEC-backed) is more downgrade-resistant; MTA-STS trades that for deployability (no DNSSEC needed). Per RFC 8461: senders implementing both **MUST NOT allow MTA-STS validation to override a failing DANE validation** — see [DANE for SMTP](https://emailmarketing.net/learn/transport-security/dane-smtp).

## Operational playbook

**Deploying:**
1. Ensure every MX presents a valid CA-signed cert with matching SAN and offers STARTTLS.
2. Publish the policy file first, then the `_mta-sts` TXT record (senders seeing a new TXT id must not cache a stale policy).
3. Start with `mode: testing` and a modest `max_age`; enable [TLS-RPT](https://emailmarketing.net/learn/transport-security/tls-rpt) and watch reports.
4. Move to `mode: enforce` and lengthen `max_age` once reports are clean.

**Updating (e.g. changing MX hosts):** update the HTTPS policy body **before** the TXT `id`. Keep old policies working for delivery during the transition window (up to the old `max_age`) or risk delays.

**Removing MTA-STS gracefully:**
1. Publish a policy with `mode: none` and a small `max_age` (e.g., one day).
2. After previously cached policies have expired, remove the TXT record and the HTTPS endpoint.

**Delegating to a provider:** CNAME `_mta-sts.<yourdomain>` to the provider's TXT record, and point the `mta-sts.<yourdomain>` host at the provider (CNAME/IP or reverse proxy). The catch: the policy endpoint's certificate must validate for **your** Policy Host name (`mta-sts.yourdomain.com`), not the provider's — the provider must provision a cert for your name.

## Why deliverability senders care

MTA-STS is a *receiving-domain* control, but senders are on both sides of it:

- As a **sending platform**, honoring recipient MTA-STS policies (and not delivering through failing paths) is increasingly expected of reputable infrastructure, and failures show up in the recipient's TLS-RPT data.
- As a **domain owner**, publishing MTA-STS + [TLS-RPT](https://emailmarketing.net/learn/transport-security/tls-rpt) on your own domains is a trust signal consistent with the authentication posture mailbox providers now demand (see [DMARC](https://emailmarketing.net/learn/authentication/dmarc)) and protects mail you *receive* (including DMARC/TLS reports and reply traffic) from interception.
