TLS-RPT: get told when inbound TLS fails
SMTP TLS Reporting (RFC 8460) sends you daily JSON summaries of failed TLS sessions. How to publish the record and read the reports that come back.

On this page(10 sections)
If a sending server fails to establish TLS with your mail servers, you would normally never know. The sender either falls back to plain text or gives up quietly, and nothing tells you.
SMTP TLS Reporting, defined in RFC 8460, fixes that by asking senders to mail you a daily summary of how their TLS connections to your domain went.
What TLS-RPT is for
TLS-RPT is a reporting companion to the policies that make SMTP encryption strict: MTA-STS (RFC 8461) and DANE for SMTP (RFC 7672). Both of those tell senders to refuse insecure delivery. When something goes wrong, such as an expired certificate, an MX host missing from your policy, or an attacker interfering with the connection, mail gets deferred. TLS-RPT is how you find out.
It is also useful on its own, without MTA-STS or DANE. Senders that support TLS-RPT will report on their connections to you even if you publish no strict policy, which gives you visibility into whether inbound mail is reaching you encrypted.
Publishing the record
TLS-RPT uses a single TXT record at _smtp._tls under your domain:
_smtp._tls.example.com. TXT "v=TLSRPTv1; rua=mailto:[email protected]"
v=TLSRPTv1identifies the record.rualists where reports should go. It acceptsmailto:addresses andhttps:URLs, separated by commas.
_smtp._tls.example.com. TXT "v=TLSRPTv1; rua=mailto:[email protected],https://reports.example.com/tlsrpt"
An HTTPS endpoint receives reports as POST requests. A mailbox is simpler to start with.
There is no authorization step equivalent to DMARC's external destination check, so you can send reports to an address at another domain, such as a reporting service, without extra DNS records on their side.
When reports arrive
Senders that support TLS-RPT typically aggregate results over a 24-hour period and send one report per day per recipient domain. Reports sent by email arrive as attachments, usually gzip-compressed JSON with a .json.gz extension. The emails themselves have a specific content type so they can be filtered automatically.
Only senders that implement TLS-RPT will report, and not every mail operator does. Large mailbox providers are the most common reporters, which is useful because they also carry most of the traffic.
Anatomy of a report
A report is a JSON document. Here is a trimmed example:
{
"organization-name": "Receiver Example",
"date-range": {
"start-datetime": "2026-09-30T00:00:00Z",
"end-datetime": "2026-09-30T23:59:59Z"
},
"report-id": "2026-09-30T00:00:00Z_example.com",
"policies": [{
"policy": {
"policy-type": "sts",
"policy-string": ["version: STSv1", "mode: enforce", "mx: mx1.example.com", "max_age: 604800"],
"policy-domain": "example.com"
},
"summary": {
"total-successful-session-count": 5230,
"total-failure-session-count": 4
},
"failure-details": [{
"result-type": "certificate-expired",
"sending-mta-ip": "203.0.113.17",
"receiving-mx-hostname": "mx2.example.com",
"failed-session-count": 4
}]
}]
}
The fields that matter
- organization-name and date-range: who is reporting and for which day.
- policy-type:
stsfor MTA-STS,tlsafor DANE, orno-policy-foundwhen you publish neither. - policy-string: the policy the sender actually applied. Comparing it with what you think you published catches stale caches.
- summary: counts of successful and failed TLS sessions.
- failure-details: one entry per distinct failure, with a result type, the MX host involved and a count.
Failure result types
RFC 8460 defines a set of result types. The ones you will most likely see:
| Result type | Typical cause | Where to look |
|---|---|---|
starttls-not-supported |
An MX host did not offer STARTTLS | MX server TLS configuration |
certificate-expired |
Certificate past its validity date | Renewal automation |
certificate-host-mismatch |
Certificate does not cover the MX hostname | Certificate SANs |
certificate-not-trusted |
Self-signed or untrusted chain | Certificate authority, intermediate chain |
validation-failure |
General validation failure | Sender logs if available |
sts-policy-fetch-error |
Sender could not retrieve the MTA-STS policy | Policy host HTTPS, redirects |
sts-policy-invalid |
Policy file malformed | Policy file syntax |
sts-webpki-invalid |
Policy host certificate invalid | Certificate on mta-sts. host |
tlsa-invalid, dnssec-invalid |
DANE record or DNSSEC problems | DNS and DNSSEC configuration |
A handful of failures from a single sender IP can be noise, for example a sender with an outdated trust store. A failure type that appears across many reporters, or a jump in failure counts, is a real problem on your side.
Reading reports efficiently
Opening a compressed JSON file each day does not scale. Options:
- A small script that decompresses each attachment and prints the summary and failures. Twenty lines of Python is enough to start.
- A reporting service that ingests TLS-RPT along with DMARC reports and shows trends.
- An HTTPS endpoint you run, which receives POSTed reports and writes them to your logging or metrics system.
A minimal summarizer:
import gzip, json, sys
for path in sys.argv[1:]:
r = json.load(gzip.open(path))
for p in r["policies"]:
s = p["summary"]
print(r["organization-name"], p["policy"]["policy-type"],
"ok", s["total-successful-session-count"],
"fail", s["total-failure-session-count"])
for f in p.get("failure-details", []):
print(" ", f["result-type"], f.get("receiving-mx-hostname"), f["failed-session-count"])
Turn the failure count into a metric and alert when it rises above a small baseline.
Telling noise from real problems
Not every failure in a report is yours to fix. A sender running an outdated trust store may report certificate-not-trusted for a perfectly valid certificate, and a single misbehaving sender IP can produce a small, steady trickle of failures that never changes. The useful questions are: does the same failure type appear in reports from several unrelated organizations, did it start on a specific day, and does it name a specific MX host? A yes to all three almost always means a change on your side, such as a renewal that installed the wrong certificate or a new MX host that was never added to your policy.
How TLS-RPT fits into an MTA-STS rollout
TLS-RPT is what makes MTA-STS testing mode useful. In testing mode, senders evaluate your policy and report failures but still deliver mail. Running in testing mode for a couple of weeks while reading TLS-RPT reports shows you whether your certificates, MX list and policy host are correct before you switch to enforce and risk deferring real mail.
After you enforce, keep reading reports. Certificate renewals fail, MX hosts change, and policy hosts get caught up in website migrations. TLS-RPT is often the first signal.
Checklist
- Publish
_smtp._tlswithv=TLSRPTv1and at least oneruadestination. - Make sure the reporting mailbox accepts compressed attachments.
- Parse reports automatically and track failure counts per day.
- Investigate any failure type that appears across multiple reporters.
- Compare
policy-stringin reports with your published policy. - Keep TLS-RPT enabled permanently, not just during rollout.
Key takeaways
- TLS-RPT gives you daily JSON reports on TLS connections that senders made, or failed to make, to your mail servers.
- One TXT record at
_smtp._tlsenables it; reports go tomailto:orhttps:destinations. - Failure result types point directly at causes: expired or mismatched certificates, missing STARTTLS, policy fetch problems.
- It is essential for an MTA-STS rollout and valuable even without one.
Start with Koltrix
Your domain, one inbox, and an API that sends.
A team inbox where AI sorts and drafts (nothing is sent without your click), plus the transactional API and SMTP relay your product sends with. 7 days free, no card.

