emailmarketing.net

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.

Foundationalesp-operatorsender

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_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.

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 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 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.
#transport-security#mta-sts#tls#starttls#dns#https#rfc8461