← Back to Learning Hub

Email Delivery • Intermediate • 6 min read

MTA-STS and TLS-RPT: Enforce Encrypted Email Delivery

Set up MTA-STS to force TLS on inbound SMTP and TLS-RPT to receive failure reports. Covers the policy file, _mta-sts and _smtp._tls records, and a safe rollout.

MTA-STS lets your domain tell other mail servers: "always use TLS with a valid certificate when you deliver mail to me, and refuse to fall back to plaintext." It closes a real gap in SMTP, where encryption between servers has historically been opportunistic and therefore strippable by an attacker. TLS-RPT is its companion: a DNS record that asks reporting senders to mail you daily JSON summaries of every TLS success and failure, so you can see problems instead of guessing. This guide covers both pieces, the exact records and policy file, the safe rollout from testing to enforce, and how to read the reports.

The downgrade problem MTA-STS solves

When one mail server delivers to another, it issues a STARTTLS command to upgrade the plaintext SMTP session to an encrypted one. The weakness is that STARTTLS is advertised in cleartext first. A machine-in-the-middle can strip the STARTTLS offer, and by default the sending server will shrug and deliver over plaintext, or it will accept an invalid or expired certificate. MTA-STS removes that fallback by publishing a policy that says TLS is mandatory and the certificate must be valid and match a listed MX host.

The two pieces of MTA-STS

MTA-STS is deliberately split into a small DNS record for discovery and a policy file served over HTTPS. The HTTPS requirement is the point: an attacker who can tamper with your DNS still cannot forge the policy, because fetching it requires a valid web PKI certificate for the mta-sts subdomain.

PieceLocationPurpose
Discovery TXT record_mta-sts.example.comSignals that a policy exists and carries an id that changes when the policy changes.
Policy filehttps://mta-sts.example.com/.well-known/mta-sts.txtThe actual rules: mode, allowed MX hosts, cache lifetime.
TLS-RPT TXT record_smtp._tls.example.comWhere senders mail aggregate TLS reports.

Step 1: publish the discovery record

The discovery record is a TXT record at the _mta-sts host. The id is any string you choose that is unique per policy version; a timestamp is the common convention. Senders cache your policy and only re-fetch it when the id changes, so you must update the id every time you edit the policy file.

_mta-sts.example.com. IN TXT "v=STSv1; id=20261007T090000Z"

Step 2: serve the policy file

Create the mta-sts subdomain, point it at a web host, and give it a valid HTTPS certificate. Serve a plain-text file at the exact well-known path below with Content-Type: text/plain. The mode field is where you control strictness, mx lists every hostname allowed to receive your mail (wildcards are permitted for one label), and max_age is how long senders may cache the policy, in seconds.

# https://mta-sts.example.com/.well-known/mta-sts.txt
version: STSv1
mode: testing
mx: mail.example.com
mx: *.mail.example.com
max_age: 604800

The three modes behave very differently, and choosing the wrong one too early is the main way MTA-STS causes an outage:

  • none removes the policy; use it to retire MTA-STS cleanly.
  • testing enforces nothing but makes senders send you TLS-RPT reports as if enforcing. This is where every deployment should start.
  • enforce makes a compliant sender refuse to deliver if TLS cannot be negotiated or the certificate does not validate against a listed MX. This is the protective mode and the one to reach only after reports are clean.

Step 3: turn on TLS-RPT first

Set up reporting before you enforce anything, so you have visibility during the rollout. TLS-RPT is a single TXT record at _smtp._tls. The rua tag lists where reports go; it accepts a mailto: address or an https: endpoint.

_smtp._tls.example.com. IN TXT "v=TLSRPTv1; rua=mailto:tls-reports@example.com"

The safe rollout sequence

  1. Publish the TLS-RPT record and let reports accumulate for a week.
  2. Stand up the mta-sts HTTPS host and publish the policy in mode: testing, plus the discovery TXT record.
  3. Watch the reports. Confirm that every legitimate sender negotiates TLS successfully and that your certificate and MX list are correct.
  4. When testing is clean, change the policy to mode: enforce and bump the id in the discovery record so caches refresh.
  5. Keep watching reports for new failures after enforcement.

Lowering the DNS TTL on the discovery record before a change helps senders pick up the new id faster, but remember that the real cache control for the policy itself is max_age inside the file.

Validating the records

# Confirm the discovery record
$ dig +short TXT _mta-sts.example.com
"v=STSv1; id=20261007T090000Z"

# Confirm the policy is served over valid HTTPS as text/plain
$ curl -sI https://mta-sts.example.com/.well-known/mta-sts.txt | grep -i content-type
content-type: text/plain

$ curl -s https://mta-sts.example.com/.well-known/mta-sts.txt
version: STSv1
mode: enforce
mx: mail.example.com
max_age: 604800

# Confirm the reporting record
$ dig +short TXT _smtp._tls.example.com
"v=TLSRPTv1; rua=mailto:tls-reports@example.com"

How to read a TLS-RPT report

Reports arrive as JSON, usually gzip-compressed, one per sending organization per day. The useful fields are the policy that was evaluated, a count of successful sessions, and a breakdown of failures by type. A trimmed example looks like this:

{
  "organization-name": "Example Sender Inc.",
  "date-range": { "start-datetime": "2026-10-06T00:00:00Z",
                  "end-datetime": "2026-10-06T23:59:59Z" },
  "policies": [{
    "policy": { "policy-type": "sts", "policy-domain": "example.com" },
    "summary": { "total-successful-session-count": 4821,
                 "total-failure-session-count": 3 },
    "failure-details": [{
      "result-type": "certificate-expired",
      "sending-mta-ip": "203.0.113.24",
      "receiving-mx-hostname": "mail.example.com",
      "failed-session-count": 3
    }]
  }]
}

Watch the result-type values. Common ones include certificate-expired, certificate-host-mismatch (the MX certificate does not match the hostname), validation-failure, and sts-policy-fetch-error (senders could not retrieve your policy file, often a web-server or certificate problem on the mta-sts host itself). A sudden spike in failures after a certificate renewal usually means the new certificate is missing an intermediate or the hostname no longer matches a listed MX.

Where this fits with your other email records

MTA-STS protects the transport between servers; SPF, DKIM, and DMARC authenticate the message itself. They are complementary layers, not substitutes, and a hardened domain runs all of them. MTA-STS depends only on the web PKI, which makes it easier to deploy than DANE but means it cannot protect senders who ignore policies; it is still the broadly supported baseline for inbound TLS enforcement.

Support and operational notes

The large mailbox providers honor MTA-STS on outbound delivery, so publishing a policy meaningfully protects mail flowing to you from Google, Microsoft, Yahoo, and other major senders. Smaller or legacy servers may ignore it, which is exactly why TLS-RPT matters: the reports show you which senders are policy-aware and which are not, rather than leaving you to assume. Keep the following operational points in mind:

  • Treat the mta-sts host like production. If its HTTPS certificate expires or the web server goes down, policy-aware senders may fall back to their last cached copy until max_age elapses, and a fresh sender cannot fetch the policy at all. Monitor that certificate alongside your mail certificates.
  • Pick a sensible max_age. A week (604800 seconds) is a common starting value. Longer caching is more resilient to a brief outage of the policy host but slows how quickly a change propagates.
  • Always bump the id when you edit the policy. Senders only re-fetch when the discovery record's id changes, so an edit without a new id will go unnoticed until caches expire naturally.
  • Keep the mx list in sync. Any time you add, rename, or retire an MX host, update both the DNS MX records and the mx lines in the policy, or enforcing senders will reject mail to the host you forgot.

Before you flip to enforce, run your _mta-sts and _smtp._tls records through the Valla DNS propagation checker to confirm they have published everywhere, and read the related SPF, DKIM, and DMARC walkthroughs in our /learn/ hub so the authentication layer is solid before you harden the transport layer.

Troubleshooting box

If results look inconsistent, compare authoritative nameservers first, then recursive resolvers by region. Capture snapshots every 10 minutes for deterministic incident timelines.

Try VallaDNS free →