STARTTLS negotiation failures happen all the time. A misconfigured certificate, an expired root CA, a cipher suite mismatch, a downgrade attack. The sending server falls back to plaintext, the message goes through, and you never know it happened.

TLS-RPT (RFC 8460) gives you visibility into those failures. It's the STARTTLS equivalent of DMARC aggregate reports: sending mail servers that support TLS-RPT will send you JSON reports documenting when TLS negotiation with your MX hosts failed, what the failure mode was, and how many messages were affected.

Most organizations don't know it exists. If you're running email infrastructure, you should enable it.

How TLS-RPT Works

TLS-RPT is a feedback mechanism for SMTP TLS policy. When a sending mail server tries to deliver to your domain and encounters a TLS failure, it generates a report and sends it to the address you specify in your TLS-RPT DNS record.

The flow:

  1. Your domain publishes a TLS-RPT record at _smtp._tls.yourdomain.com with a reporting address.
  2. A sending mail server attempts TLS negotiation with your MX host.
  3. If negotiation fails (certificate error, protocol mismatch, connection timeout, etc.), the sender logs the failure.
  4. The sender aggregates failures and sends a daily JSON report to your designated address.

Reports arrive as email messages with a JSON attachment. The JSON contains detailed failure data: which policy was being enforced (MTA-STS or DANE), what went wrong, how many attempts failed, and during what time window.

Publishing a TLS-RPT Record

The DNS record is simple:

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

The rua (reporting URI aggregate) field specifies where reports should be sent. You can list multiple addresses separated by commas. HTTPS endpoints are also supported (rua=https://example.com/tls-rpt), but email is far more common.

Most organizations use a subdomain or dedicated mailbox for TLS reports. Parse the JSON with a script, log failures to your monitoring stack, or use a third-party service to aggregate and visualize the data.

You can verify your DNS record with the DNS lookup tool on mrdns.com, which supports TXT record queries for _smtp._tls records.

Reading the JSON Reports

TLS-RPT reports are verbose but structured. Here's a minimal example:

{
  "organization-name": "Sending MTA Inc",
  "date-range": {
    "start-datetime": "2026-04-27T00:00:00Z",
    "end-datetime": "2026-04-28T00:00:00Z"
  },
  "contact-info": "postmaster@sendingmta.example",
  "report-id": "2026-04-27-abc123",
  "policies": [
    {
      "policy": {
        "policy-type": "sts",
        "policy-string": ["version: STSv1","mode: enforce","mx: mail.example.com","max_age: 86400"],
        "policy-domain": "example.com"
      },
      "summary": {
        "total-successful-session-count": 1523,
        "total-failure-session-count": 7
      },
      "failure-details": [
        {
          "result-type": "certificate-expired",
          "sending-mta-ip": "203.0.113.45",
          "receiving-mx-hostname": "mail.example.com",
          "receiving-ip": "198.51.100.10",
          "failed-session-count": 4,
          "additional-information": "Certificate expired on 2026-04-25"
        },
        {
          "result-type": "starttls-not-supported",
          "sending-mta-ip": "203.0.113.67",
          "receiving-mx-hostname": "backup-mx.example.com",
          "receiving-ip": "198.51.100.20",
          "failed-session-count": 3
        }
      ]
    }
  ]
}

The fields worth understanding: date-range gives you the reporting window, usually 24 hours. total-successful-session-count is your baseline — a handful of failures against 10,000 successful sessions is noise; the same handful against 50 successful sessions is not. The actual investigation lives in failure-details: result-type tells you what broke, receiving-mx-hostname and receiving-ip tell you which of your MX hosts had the problem, and failed-session-count tells you how many delivery attempts it affected.

What Failure Events Mean

certificate-expired is the obvious one: your certificate expired. Renew it. If you're using Let's Encrypt or another ACME provider, check whether automation actually ran — a renewal failure that went unnoticed for weeks is one of the most common explanations.

certificate-not-trusted means the chain is broken. Most often a missing intermediate certificate, an untrusted root CA, or a self-signed cert. Verify the chain with openssl s_client -connect mail.example.com:25 -starttls smtp, or use the SSL certificate checker on mrdns.com to inspect the full chain, expiry, SANs, and validation status.

validation-failure covers the broader category: hostname mismatch, revoked certificate, or another X.509 error. Check the additional-information field for specifics.

starttls-not-supported means your MX host didn't advertise STARTTLS. If you're enforcing TLS with MTA-STS, this is a misconfiguration, not a transient event — it needs to be fixed.

tlsa-invalid appears when you're running DANE. Your TLSA record doesn't match the certificate your MX host is presenting. Verify both the record and the fingerprint are current.

Transient timeouts and handshake failures also show up in reports. A few scattered instances are normal. Sustained timeouts against specific MX hosts point to network or server load, not a certificate issue.

Why TLS-RPT Matters

STARTTLS is opportunistic. When negotiation fails, most MTAs silently fall back to plaintext, the message goes through, and you see nothing. TLS-RPT is how you find out — a daily account of every failed negotiation attempt against your MX hosts, what broke, and how many messages were affected.

Combined with MTA-STS, it closes the loop. MTA-STS tells sending servers they must use TLS. TLS-RPT tells you what happened when they tried.

Enable the DNS record, set up a mailbox, parse the JSON, and watch for failures. Most of the time you'll see nothing. When you do see something, it's worth knowing about.

Back to Blog