egressif.

Resources / Transport Security

TLS-RPT (RFC 8460): SMTP TLS reporting explained

TLS-RPT is the feedback channel for SMTP transport security. Senders mail you a daily JSON summary of how many TLS sessions succeeded or failed against your domain and why. This page covers the _smtp._tls TXT record, the report schema, every failure result-type, and how to use reports to roll out MTA-STS and DANE safely - per RFC 8460.

Last checked: June 22, 2026

SMTP TLS Reporting (TLS-RPT, RFC 8460, September 2018) solves a specific problem with enforced transport security: when MTA-STS or DANE blocks a delivery, the failure happens at the sender, not at you. A misconfigured certificate, a stripped 250 STARTTLS, or a botched TLSA record all look the same from your side - mail simply does not arrive, or arrives later. As RFC 8460 puts it, “because such ‘downgrade attacks’ are not necessarily apparent to the receiving MTA, this document defines a mechanism for sending domains to report on failures at multiple stages of the MTA-to-MTA conversation.”

The 60-second version

  • Publish one DNS record: a TXT record at _smtp._tls.<domain> with a rua (reporting address).
  • Cooperating senders mail (or POST) you a daily JSON report - one per UTC day - summarising TLS sessions to your MX hosts.
  • Each report carries a success count (a heartbeat that reporting works) and, for failures, a result-type that names the cause: STARTTLS missing, certificate expired, MTA-STS policy invalid, DNSSEC invalid, and so on.
  • TLS-RPT itself enforces nothing. It is pure observability - the instrument you watch while rolling out MTA-STS and DANE.
  • Deploy it first, before turning any policy to enforcing.
RECEIVER_smtp._tls TXTrua=mailto:…readSENDING DOMAINSTLS sessionssuccess / faildailyDAILY JSONresult-typesession countsOPERATORreads
Senders read the _smtp._tls record and mail a daily JSON report of TLS successes and failures back for the operator to review.

The record

; mailto: destination
_smtp._tls.example.com. IN TXT "v=TLSRPTv1; rua=mailto:tlsrpt@example.com"

; or an HTTPS endpoint
_smtp._tls.example.com. IN TXT "v=TLSRPTv1; rua=https://reporting.example.com/v1/tlsrpt"

The record lives at the label _smtp._tls under the Policy Domain - for example.com, that is _smtp._tls.example.com. It has two fields:

FieldRequiredValue
vYesTLSRPTv1
ruaYesA comma-separated list of mailto: and/or https: destinations for reports

Parsing follows the same discipline as the other records: senders discard any _smtp._tls record not starting v=TLSRPTv1;, and “if the number of resulting records is not one, senders MUST assume the recipient domain does not implement TLSRPT.” You can list more than one rua; a reporter may try each, and the report is considered delivered once any endpoint accepts it.

How reports arrive

Reports can come two ways:

  • Email (mailto:). The report is a multipart/report; report-type="tlsrpt" message containing a human-readable text/plain part and a machine-readable application/tlsrpt+json part (usually gzipped as application/tlsrpt+gzip). It carries two headers, TLS-Report-Domain and TLS-Report-Submitter, and must be DKIM-signed by the reporting domain. Crucially, emailed reports “MUST NOT use the ‘l=’ attribute” (so nothing can be appended without breaking the signature) and SHOULD declare the DKIM service type s=tlsrpt.
  • HTTPS (https:). The report is POSTed to the URI; success is an HTTP 200 or 201. Report submitters “MAY ignore certificate validation errors when submitting reports via HTTPS POST” - because a misconfigured SMTP server often means a misconfigured HTTPS server, and the report needs to get through anyway.

A defining rule: when reports are emailed, the sender “MUST deliver reports despite any TLS-related failures” for that report’s own delivery - otherwise a TLS problem would suppress the very report that describes it.

Other delivery facts from RFC 8460:

  • A report SHOULD cover a full UTC day (00:0024:00) and be sent after a delay (the spec illustrates a random delay of up to four hours) to avoid thundering-herd load.
  • The report SHOULD be gzip-compressed; a commonly observed receiver limit is ten megabytes.
  • On a delivery failure the sender SHOULD retry for up to 24 hours, ideally with exponential backoff. Reports are optional, so non-delivery is tolerated.
  • The recommended filename is sender!policy-domain!begin-timestamp!end-timestamp!unique-id.json.gz.

The JSON report schema

Reports are Internet JSON (I-JSON, RFC 7493). The shape is small and stable:

{
  "organization-name": "Company-X",
  "date-range": {
    "start-datetime": "2026-06-01T00:00:00Z",
    "end-datetime": "2026-06-01T23:59:59Z"
  },
  "contact-info": "sts-reporting@company-x.example",
  "report-id": "5065427c-23d3-47ca-b6e0-946ea0e8c4be",
  "policies": [{
    "policy": {
      "policy-type": "sts",
      "policy-string": ["version: STSv1", "mode: testing",
        "mx: *.mail.company-y.example", "max_age: 86400"],
      "policy-domain": "company-y.example",
      "mx-host": "*.mail.company-y.example"
    },
    "summary": {
      "total-successful-session-count": 5326,
      "total-failure-session-count": 303
    },
    "failure-details": [{
      "result-type": "certificate-expired",
      "sending-mta-ip": "2001:db8:abcd:0012::1",
      "receiving-mx-hostname": "mx1.mail.company-y.example",
      "failed-session-count": 100
    }, {
      "result-type": "starttls-not-supported",
      "sending-mta-ip": "2001:db8:abcd:0013::1",
      "receiving-mx-hostname": "mx2.mail.company-y.example",
      "receiving-ip": "203.0.113.56",
      "failed-session-count": 200
    }]
  }]
}

The key fields:

FieldWhat it tells you
organization-name, contact-info, report-idWho sent the report and a unique id to deduplicate
date-rangeThe reporting window (a full UTC day)
policies[].policy.policy-typeWhich policy was applied: sts, tlsa, or no-policy-found
policies[].policy.policy-stringThe literal policy seen (the MTA-STS lines, or the TLSA records)
policies[].policy.policy-domain, mx-hostThe domain and MX the policy applies to
summary.total-successful-session-countThe heartbeat - sessions that negotiated policy-compliant TLS
summary.total-failure-session-countSessions that failed
failure-details[]One entry per failure type, with result-type, sending IP, receiving MX, and a failed-session-count

Each failure-details entry can also carry receiving-ip, receiving-mx-helo, an additional-information URI, and a free-text failure-reason-code (for example an OpenSSL error string). Note that “the failure types are non-exclusive” - one session hitting several errors can appear under several types, so the failure counts are not a clean partition of the failure total.

The failure result-types

This is the part you actually act on. RFC 8460 defines the initial set in three groups.

Negotiation failures (the TLS handshake or certificate itself):

result-typeMeaning
starttls-not-supportedThe MX did not offer STARTTLS at all
certificate-host-mismatchThe certificate did not match any identity required by the policy (no matching SAN)
certificate-expiredThe presented certificate has expired
certificate-not-trustedUntrusted/unknown CA, chain errors, name-constraint failures, and similar
validation-failureA general failure that does not fit a category above (use failure-reason-code for detail)

DANE-specific policy failures:

result-typeMeaning
tlsa-invalidNone of the TLSA records in the RRset validated against the certificate
dnssec-invalidNo valid (DNSSEC-validated) records were returned by the resolver
dane-requiredThe sender requires DANE for this destination but no DNSSEC-validated TLSA record was present

MTA-STS-specific policy failures:

result-typeMeaning
sts-policy-fetch-errorThe MTA-STS policy could not be fetched (for example, the policy host was unreachable)
sts-policy-invalidThe overall MTA-STS policy failed validation
sts-webpki-invalidThe MTA-STS policy could not be authenticated via PKIX (Web PKI)

One deliberate omission: transient errors like TCP timeouts and too-busy networks “are not required to be reported,” so the reports stay focused on TLS and policy problems rather than ordinary network noise.

How to read a report

A practical reading order:

  1. Check the heartbeat. A healthy total-successful-session-count with zero or near-zero failures means senders are negotiating TLS with you as expected.
  2. Triage by result-type. certificate-expired or certificate-host-mismatch is your own certificate or MX config. sts-webpki-invalid or sts-policy-fetch-error is an MTA-STS problem (a bad cert on the mta-sts host, or an unreachable policy endpoint). dnssec-invalid or tlsa-invalid is a DANE/DNSSEC problem.
  3. Correlate with the IPs and MX hosts. sending-mta-ip plus receiving-mx-hostname tell you whether a problem is one sender, one of your MXes, or everyone.
  4. Watch for the attack signature. A sudden cluster of starttls-not-supported against an MX that normally offers STARTTLS, especially from many senders at once, is the fingerprint of an active downgrade attempt - exactly what RFC 8460 was written to make visible.

Why TLS-RPT and DNSSEC go together

There is a chicken-and-egg risk: an adversary who can downgrade your TLS can often also suppress the _smtp._tls TXT lookup, hiding the evidence of their own attack. RFC 8460 therefore advises that “administrators are thus encouraged to deploy TLSRPT TXT records with a large TTL … or to deploy DNSSEC on the deploying zone.” A signed zone makes the reporting record itself tamper-evident.

Common confusion

  • “TLS-RPT encrypts or enforces something.” It does neither. It only reports. Enforcement is MTA-STS and DANE; TLS-RPT is the dashboard.
  • “No report means everything is fine.” No report can also mean no sender supports TLS-RPT, or your record is wrong, or the report was suppressed. Confirm you are receiving reports from at least the large providers before you trust the silence.
  • “Reports are real-time.” They are daily aggregates, intentionally delayed by hours. TLS-RPT is for trend and incident detection, not live alerting.
  • “A certificate-expired report is a sender problem.” It is almost always your certificate (or your MX’s) that expired - the report is describing what senders saw when they connected to you.

What this means for you, and what Egressif does

We treat TLS-RPT as the prerequisite for any enforced transport security, not an afterthought. On the domains we operate we publish the _smtp._tls record before switching MTA-STS to enforce or turning on DANE, so a misconfiguration shows up as a failure report instead of as quietly delayed mail. We monitor the result-type mix the same way we watch DMARC aggregate reports: a rise in certificate-expired is a renewal we missed, a burst of sts-webpki-invalid points at the mta-sts host’s certificate, and a spike in starttls-not-supported from many senders is treated as a possible downgrade attack until proven otherwise. We keep the record on a signed zone where the domain is DNSSEC-enabled, so the reporting channel cannot be quietly cut off by the same attacker it is meant to expose.

Tell us what you run today.

Domains, rough volume, current providers, and what hurts. You will get a straight answer on fit, and a real number, in one conversation.

Talk to our team