Skip to main content

Email transport security: MTA-STS and TLS-RPT

SPF, DKIM, and DMARC protect the content of a message — they authenticate who sent it and what happens when authentication fails. They say nothing about the connection the message travels over. A sending mail server that reaches your MX host over plain SMTP, or that accepts any certificate presented at STARTTLS time, is exposing your inbound mail to a classic downgrade or interception attack, and none of the content-layer records would show it. MTA-STS (RFC 8461) and TLS-RPT (RFC 8460) close that gap. MTA-STS tells every sending MTA “always negotiate authenticated TLS to my MX hosts” — it removes the silent plaintext fallback that makes SMTP trivially observable on-path. TLS-RPT is the companion feedback loop: receivers of your inbound mail send you a daily JSON aggregate of every TLS negotiation failure they hit, so a downgrade attempt is a report in your inbox instead of invisible mail you never received. This page covers the transport-security layer for email in Orbit: why it matters on a send-as-MTA platform, how the MTA-STS policy helpers and TLS-RPT aggregate ingestion work, and the inbound MX and return-path gates that keep the whole set honest on your sender domain.

Why transport policy matters on a send-as-MTA platform

Orbit is unusual in that you publish records for two directions of email on the same operation:
  • Outbound — the sender domain you use on POST /messages/email. You publish SPF, DKIM, DMARC, the provider-issued return-path MX/SPF pair, and (for inbound mail to that domain — the mailbox your Inbox reads, plus every bounce, complaint, and DMARC report address) you publish MX. MTA-STS/TLS-RPT protect that inbound direction.
  • Inbound — Orbit receives Inbox email at a dedicated inbound funnel subdomain (send.<domain>), not at your apex. The inbound MX gate below grades that record.
Two consequences follow. First, publishing MTA-STS is what makes your inbound funnel and return-path un-downgradable: without it, a carrier or an on-path attacker can strip STARTTLS and your mail arrives plaintext; with mode: enforce it is rejected rather than downgraded. Second, the inbound MX gate only ever grades the funnel your tenant actually provisioned — it never invents an apex requirement — because on a platform where the same domain sends and receives, an apex-only MX check would mis-grade every tenant who receives on the dedicated subdomain and send you chasing a record that was never required.

MTA-STS — policy modes and enforcement tiers

The deliverability wizard’s MTA-STS step (POST /email/deliverability/domains/:domainId/mta-sts) generates the two artifacts an operator publishes:
  1. A TXT record at _mta-sts.<domain> — v=STSv1; id=<policy id>. The id is an opaque string (a timestamp works) you bump on every policy change; receivers use it to detect that the policy changed and re-fetch.
  2. A policy file served over HTTPS at https://mta-sts.<domain>/.well-known/mta-sts.txt with the text/plain body:
The wizard validates what you intend to publish before you publish it — it flags a missing policy id, an empty MX list on enforce/testing, or a max_age outside the RFC’s 60-second to 1-year bound, and reports ready: false on any of them.

The three modes, and what each buys you

Publish in testing, read your TLS-RPT aggregates for a week, then move to enforce. The wizard generates either mode from the same inputs, so the promotion is one republish of the same file with the mode flipped. Orbit never fetches your policy file from the server — the same rule that governs BIMI asset URLs. The policy body is generated for you to copy to your own host, so there is no server-side request surface pointed at a tenant-controlled URL. The DNS record, in contrast, is looked up and graded (valid / warning / invalid / unknown — where a lookup timeout is explicitly unknown, not a verdict), so the deliverability grid reflects what receivers will actually find at _mta-sts.<domain>.

TLS-RPT — aggregate ingestion and failed vs opportunistic TLS

The other half of the pair is the report address. Publish a TXT record at _smtp._tls.<domain> of the form:
The rua= list names one or more destinations — mailto: addresses or an https: endpoint — where mailbox providers send their daily TLS-RPT aggregate reports. The wizard generates this record alongside MTA-STS and validates each destination shape; a record with no rua= destination grades invalid, and a malformed destination grades warning. Each report is a JSON document rolling up, per MX policy, how many SMTP-over-TLS sessions to your domain succeeded versus failed, with an RFC 8460 result-type on every failure. Orbit ingests those aggregates (POST /email/deliverability/tls-rpt/reports/analyze) and folds them into one summary: the overall success rate, and the ranked list of downgrade-indicative failures. The split that matters when you read a report:
  • Opportunistic TLS failures are not necessarily hostile. A sender that simply does not support STARTTLS, or whose certificate chain is misconfigured, shows up as a failure without any attack. Under mode: testing those failures are data; under mode: enforce they are a delivery the sender must fix.
  • Downgrade-indicative failures are the reports that matter. A STARTTLS that silently vanished (starttls-not-supported), a certificate that does not validate for your MX host (certificate-host-mismatch, certificate-not-trusted, certificate-expired), a DANE/TLSA failure (tlsa-invalid, dane-required), or a receiver that can no longer fetch your enforced policy (sts-policy-fetch-error, sts-policy-invalid, sts-webpki-invalid) is exactly what an active on-path attacker — or a broken middlebox — produces. Every one of these result types is surfaced, because a receiver that cannot fetch the enforced policy falls back to unauthenticated opportunistic TLS, the same exposure class as a stripped STARTTLS.
One report in isolation tells you little; the daily aggregates let you see that a specific sending-MTA IP failed against a specific MX hostname with a specific certificate-verdict — enough to distinguish “Google’s STARTTLS implementation hiccuped at 03:14” from “something is actively stripping STARTTLS on this path.”

Inbound MX and return-path gates

Transport-security records are only useful when the underlying mail records resolve where they must, and two gates on the deliverability page check exactly that for a sender domain.

The inbound funnel MX gate

Orbit receives Inbox email — and every bounce, complaint, and DMARC rua report — at a dedicated inbound funnel subdomain, send.<domain>, provisioned per tenant. The gate resolves MX for that one host and grades it against the provider-issued target and priority. When you have provisioned no inbound funnel, the gate falls back to the apex instead, so a sender-only domain is not penalized for a record it never needed. When a funnel is provisioned, the funnel record supersedes the apex row — the deliverability grid carries exactly one MX card, not a duplicated apex+funnel pair. Two failure shapes, and they are different: a funnel that resolves no MX at all grades invalid (Orbit receives nothing there — Inbox mail, bounce reports, and DMARC rua mail are all undeliverable at that host). A funnel whose MX points at a wrong target also grades invalid, with the expected and actual exchanges named in the issue, because “the funnel exists” and “the funnel reaches your receiver” are separate verdicts.

The return-path pair gate

When you register a sending domain with the email provider, the provider issues three records, and Orbit checks all three: the DKIM public key you expect, plus the pair that is easy to miss — an MX and an SPF TXT record at send.<domain> (the provider’s bounce/complaint feedback host, not your inbound funnel — the two share the send. prefix by provider convention). A missing return-path MX or SPF is not advice: it is why the provider’s own verifier refuses to send for the domain, so the gate grades a missing record invalid and that verdict drags the overall deliverability status down alongside it. This gate is provider-agnostic: a domain for which the provider issued no send. records is not checked at all, and its status is unchanged. The gate fires only on domains that actually hold provider-issued return-path rows — it never makes a universal requirement out of one provider’s convention.

How transport security interacts with warming and the delivery lifecycle

The transport layer sits underneath the two concepts you already know:
  • Sender warming and reputation. A warming sender is graded on engagement and complaint rates; a forced-TLS policy is orthogonal to both. But the failure-direction is not: a downgrade or interception attempt against your inbound funnel — the host that receives your bounce and complaint reports — would suppress exactly the signals the warming controller reads. Publishing MTA-STS in enforce and reading TLS-RPT aggregates is how you keep the inbound half of the warming loop as defensible as the outbound half. mode: testing plus TLS-RPT is also the standard first week of a new sender domain: collect aggregate failures before paying the enforce delivery cost of a misconfiguration.
  • Email delivery lifecycle. The lifecycle’s submitted_no_receipt sentinel never fires on inbound MTA-STS rejection — that is a receiver-side refusal, not a missing DLR. Where transport security does touch the lifecycle is the returns path: every bounce and complaint the lifecycle depends on arrives as inbound mail at the funnel, so a mis-graded funnel MX shows up as missing bounce/complaint events, not as a transport verdict. The MX gate exists so that state is surfaced as a DNS problem on the deliverability page before it ever looks like a provider event problem on the message grid.

Worked example: publish MTA-STS and read a TLS-RPT aggregate

1. Generate the records. On the deliverability page for your sender domain, run the MTA-STS/TLS-RPT wizard. It returns the generated TXT record for _mta-sts.<domain>, the policy-file body for https://mta-sts.<domain>/.well-known/mta-sts.txt, and the generated TLS-RPT record for _smtp._tls.<domain>, each with a ready flag and an issues list. Review any flagged problems before you publish. 2. Publish in testing. Copy the policy file to your HTTPS host, publish both TXT records, and set the rua= destination to the mailbox you monitor for infrastructure reports. The wizard’s generated record and policy echo your chosen mode and MX hosts verbatim, so a later re-run with mode: enforce is a one-character mode change in the same artifact. 3. Wait for reports, then ingest. Mailbox providers send a daily aggregate. Submit one or more raw reports to POST /email/deliverability/tls-rpt/reports/analyze — the route accepts the raw JSON, a base64 JSON, or the base64 gzip stream mailbox providers mail as application/tlsrpt+gzip, and tolerates a corrupt per-payload failure (one bad report does not sink the batch). 4. Read the summary. The response gives you an overall success rate and the ranked list of downgrade-indicative failures, each with its result type, the sending MTA IP, and the MX hostname the failure hit. A week of zero downgrade-indicative failures on testing is the signal to republish with mode: enforce. 5. Verify the gates stay green. Re-run the deliverability DNS check for the domain. The inbound funnel row and the return-path pair should each grade valid, and the MTA-STS / TLS-RPT records should grade valid at their respective hosts — all four are the transport-security half of the same grid.