uCheckeruChecker

TLS-RPT Generator

The most harmless record in mail security: it forbids nothing and changes nothing about delivery, it simply asks for reports about failed attempts to encrypt a connection when delivering mail to your domain.

Where to send reports

Either a mail address or an https endpoint. Reports arrive daily and describe failed attempts to establish an encrypted connection to your server.

Generated record

v=TLSRPTv1; rua=mailto:
How to publish it
TypeNameTTL
TXT_smtp._tls3600

What TLS-RPT is and why you want it

TLS-RPT (SMTP TLS Reporting, RFC 8460) tells you how other servers connect to yours. Servers that deliver mail to your domain send a daily summary: how many connections to your MX hosts went over TLS, how many failed, and why. It covers inbound mail, not the mail you send.

Those failures are invisible from the inside. A certificate expires, the name in it stops matching the server, an intermediate hop strips STARTTLS, and the sender delivers the message unencrypted or not at all, and you never find out. A downgrade attack looks the same. Someone in the middle deletes the “250 STARTTLS” line from the server's response, and the receiving server may not notice. TLS-RPT turns that blind spot into a daily report. It matters most alongside MTA-STS: the policy demands TLS, and the reports show who could not comply.

Where to publish it and what the record contains

As a TXT record at _smtp._tls.yourdomain. In most DNS panels the name field only needs _smtp._tls. Both underscores are required, and the order matters: nobody will look for a record at _tls._smtp.

v=TLSRPTv1; rua=mailto:tlsrpt@example.com,https://tlsrpt.example.com/report

There are two tags. v=TLSRPTv1 sets the version and comes first. rua= says where reports go: mailto:, or https: for delivery by POST, with several addresses separated by commas. A sender may deliver to just one of them, so put the main address first. Unlike DMARC, another domain does not have to authorise receiving reports. RFC 8460 considers the abuse risk lower here.

There must be exactly one record starting with v=TLSRPTv1. With two, senders treat the domain as not using TLS-RPT at all. To check the published record:

dig +short TXT _smtp._tls.example.com

Who sends the reports

Not everyone does. According to URIports as of August 2024, the largest senders of reports are Google, Microsoft, Comcast, Mail.ru and Mimecast. The same source notes that Microsoft delivers a report only to the first address in rua, which the standard permits.

By the standard, a report email carries the sender's DKIM signature, and an unsigned report should be ignored. It is delivered even when TLS fails, which means sometimes unencrypted, since otherwise nobody could report that encryption is broken.

What the JSON report contains

A report covers one UTC day and arrives a few hours later, usually gzip-compressed. A shortened example:

{
  "organization-name": "Example Sender",
  "date-range": {
    "start-datetime": "2026-09-16T00:00:00Z",
    "end-datetime": "2026-09-16T23:59:59Z"
  },
  "policies": [{
    "policy": { "policy-type": "sts", "policy-domain": "example.com" },
    "summary": {
      "total-successful-session-count": 1285,
      "total-failure-session-count": 3
    },
    "failure-details": [{
      "result-type": "certificate-expired",
      "sending-mta-ip": "198.51.100.7",
      "receiving-mx-hostname": "mail.example.com",
      "receiving-ip": "203.0.113.10",
      "failed-session-count": 3
    }]
  }]
}
  • organization-name names the reporter, and date-range shows which day the report covers.
  • policy-type shows which rule the connection was checked against: sts for MTA-STS, tlsa for DANE, or no-policy-found when there is none.
  • total-successful-session-count and total-failure-session-count in the summary block count successful and failed sessions. Those are the numbers to chart.
  • failure-details holds a line per cause: the failure type, the sender's IP, your MX name and IP, and the number of failed sessions in failed-session-count.

Failure types and what to do about them

  • starttls-not-supported: the MX did not offer STARTTLS. If it is a backup server, fix it too, since mail goes there whenever the primary is down.
  • certificate-expired: the MX certificate has expired, usually because auto-renewal failed.
  • certificate-host-mismatch: the name in the certificate does not match the MX name, for example an MX of mail.example.com with a certificate issued for example.com.
  • certificate-not-trusted: the certificate does not chain to a trusted authority, most often because it is self-signed.
  • validation-failure: a catch-all for anything else. The sender adds details in failure-reason-code, and you can see what your server presents in the SMTP test.
  • sts-policy-fetch-error, sts-policy-invalid, sts-webpki-invalid: the MTA-STS policy could not be fetched or parsed, or the policy site has a certificate problem.
  • tlsa-invalid, dnssec-invalid, dane-required are DANE failures: a bad TLSA record, an invalid DNSSEC answer, or no TLSA where the sender requires DANE.

The standard does not require reporting transient failures such as timeouts, so every line in a report deserves a look.

What to look at first

Isolated failures happen: networks, somebody's broken relay. The warning sign looks different: a steady share of failures from one sender, or certificate-expired rising everywhere at once, which usually means a certificate on your MX that failed to renew.

Reports also catch starttls-not-supported from hosts you believed were protected. The usual culprit is a gateway or anti-spam proxy stripping STARTTLS from the server's response. And then there is the backup MX: the primary is configured perfectly, the secondary has lived with an old certificate for years, and the errors only show up when the primary is unavailable.

How to process the reports

For the first few weeks, reading reports by hand works fine. This command prints the domain, the totals and the list of failures for each report:

gunzip -c report.json.gz | jq -c '.policies[] | {
  domain: .policy."policy-domain", summary,
  failures: [."failure-details"[]? | {type: ."result-type",
    mx: ."receiving-mx-hostname", n: ."failed-session-count"}]}'

After that, either send reports to an analysis service such as URIports or Mailhardener (just put its address in rua) or set up a rule: a message with a non-zero total-failure-session-count goes to a separate folder and the rest is ignored.

No reports at all is a signal too. If a week passes without a single report from Google or Microsoft, the record is probably at the wrong name, or there are two of them.

The order to roll out transport security

TLS-RPT goes first, because it is the only piece that cannot break anything. Reports accumulate and delivery stays the same. A week of observation gives you a baseline: how many connections use TLS at all, and from whom.

Next comes MTA-STS in testing mode: the reports show where the policy and reality disagree, and before you switch to enforce you can see which MX host will fail validation. Only after a clean week do you move to enforce, built in the MTA-STS generator. The reverse order means mail stops arriving and you have no data to tell you why.

Sources

Questions

Nearby

Channel reports are not list quality

TLS-RPT tells you about connection problems, not about half your list being dead addresses. uChecker checks that before you send, and the first 100 addresses are free.

Check your list