Skip to main content
All fixes

Email deliverability, DNS, SPF/DKIM/DMARC

Fix Missing MTA-STS Policy on Receiving Domain

MTA-STS (RFC 8461) forces TLS on inbound SMTP. Without it, attackers can downgrade connections and read mail in transit. Publish a policy file and TXT record.

What's happening

MTA-STS, defined in RFC 8461, is the SMTP equivalent of HSTS for HTTPS. It tells sending MTAs that mail to your domain MUST use TLS with a valid certificate, and that downgrade attacks (where an attacker strips STARTTLS) should be rejected rather than silently accepted.

Implementation has two parts. A TXT record at _mta-sts. announces the policy version. The policy itself is served as a flat text file at https://mta-sts./.well-known/mta-sts.txt over HTTPS with a valid certificate. Both parts must be in place for the policy to take effect.

Without MTA-STS, opportunistic TLS is the default — sending MTAs try STARTTLS but fall back to cleartext if it fails. An on-path attacker can strip the STARTTLS response and force cleartext, then read or modify mail. Combined with TLS-RPT, MTA-STS provides both enforcement and visibility into TLS failures.

Why it matters

Mail in transit is at risk. Active attackers (state-level adversaries, compromised network paths, malicious ISPs) can read inbound mail by downgrading TLS. Sensitive content — password resets, internal corporate mail, customer support — is exposed.

Compliance gap. NIST SP 800-177 recommends MTA-STS for sensitive systems; CISA's Binding Operational Directive 18-01 requires it for federal agencies. Enterprise security questionnaires increasingly include MTA-STS as a checklist item.

Brand impersonation defense incomplete. SPF, DKIM, and DMARC protect against spoofed sender identity but not against in-transit modification. MTA-STS is the missing layer for transport-level protection.

Common causes

  • MTA-STS not on the operator's radar — newer than SPF/DKIM/DMARC.
  • TXT record published but policy file missing or vice versa.
  • Policy file served over HTTP instead of HTTPS, or with an invalid certificate.
  • Policy file content does not match the RFC 8461 grammar (wrong line endings, missing fields).
  • id= value in the TXT record does not match the policy file's contents.

Detect this on your site

Run a quick scan with the Email Checker. The tool surfaces this exact issue with the records and context needed to apply the fix below.

Open Email Checker

How to fix it

  1. 1

    Inventory inbound MX hosts

    Run dig +short MX example.com. List every target hostname. Each must support TLS with a valid certificate matching the hostname. If any MX target uses a wildcard cert or a generic provider hostname, ensure the cert is valid for that exact name.

  2. 2

    Create the policy file

    The policy file is a flat text document with line-endings as CRLF. Required fields: version: STSv1, mode: testing|enforce|none, mx:, max_age:. Repeat mx: lines for each MX target. Use mode: testing for two weeks before switching to enforce.

  3. 3

    Serve the policy at https://mta-sts./.well-known/mta-sts.txt

    Add a subdomain mta-sts.example.com pointing to a host that serves HTTPS with a valid TLS certificate (Let's Encrypt is fine). The policy file must be at /.well-known/mta-sts.txt. Many operators use Cloudflare Workers, Netlify, or a small Nginx instance for this.

  4. 4

    Publish the TXT record

    Add a TXT record at _mta-sts.example.com with value v=STSv1; id=. The id must change every time the policy file changes — receivers cache the policy until the id changes or max_age expires. Use a date-based id like 2026042901 for clarity.

  5. 5

    Verify with dig and curl

    Run dig +short TXT _mta-sts.example.com — confirm the v=STSv1 record. Run curl -v https://mta-sts.example.com/.well-known/mta-sts.txt and confirm 200 OK with valid TLS and the policy content. Use the EFF STARTTLS test or hardenize.com for a full check.

  6. 6

    Move from testing to enforce after observation

    Run mode: testing for two weeks. Pair with TLS-RPT (separate fix) to receive failure reports. If reports show no legitimate-mail TLS failures, update the policy file to mode: enforce, bump the id, and republish. Receivers will now reject downgraded connections.

Example

; TXT record advertising the policy
_mta-sts.example.com. 86400 IN TXT "v=STSv1; id=2026042901"

; Policy file served at https://mta-sts.example.com/.well-known/mta-sts.txt
version: STSv1
mode: enforce
mx: aspmx.l.google.com
mx: alt1.aspmx.l.google.com
mx: alt2.aspmx.l.google.com
max_age: 604800

MTA-STS TXT record plus the HTTPS-served policy file for a Google Workspace inbound setup.

Frequently asked

Yes — RFC 8461 specifies mta-sts. as the required hostname for the policy. The subdomain must serve HTTPS with a valid certificate. The policy file is small (a few hundred bytes) so a static-hosting setup like Netlify Cloudflare Pages or a tiny S3 + CloudFront stack works well.

Start with mode: testing for at least two weeks. Pair it with TLS-RPT to receive failure reports. Only switch to mode: enforce after reports show no legitimate-mail failures. Going straight to enforce risks blocking mail from senders whose TLS configuration has hidden problems.

Both protect SMTP TLS. DANE (RFC 7672) uses DNSSEC to publish TLSA records that pin certificates. MTA-STS uses HTTPS-served policy files. They can coexist; receivers prefer DANE if both are present. DANE requires DNSSEC; MTA-STS does not making it accessible to more domains.

Related fixes