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.
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, 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 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_ageseconds from the last fetch. - Before permanently failing a delivery under an
enforcepolicy, check DNS for a newer policy (changedid) — 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.
Operational playbook
Deploying:
- Ensure every MX presents a valid CA-signed cert with matching SAN and offers STARTTLS.
- Publish the policy file first, then the
_mta-stsTXT record (senders seeing a new TXT id must not cache a stale policy). - Start with
mode: testingand a modestmax_age; enable TLS-RPT and watch reports. - Move to
mode: enforceand lengthenmax_ageonce 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:
- Publish a policy with
mode: noneand a smallmax_age(e.g., one day). - 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 on your own domains is a trust signal consistent with the authentication posture mailbox providers now demand (see DMARC) and protects mail you receive (including DMARC/TLS reports and reply traffic) from interception.