> ## Documentation Index
> Fetch the complete documentation index at: https://docs.orbit.devotel.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Email transport security: MTA-STS and TLS-RPT

> How Orbit helps you protect the SMTP transport for your sender and inbound domains — publishing an MTA-STS policy that forces TLS on connections to your mail hosts, ingesting TLS-RPT aggregate reports that surface downgrade and interception attempts, and the inbound MX/return-path gates that make sure the records you publish actually resolve where they must.

# 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](/concepts/deliverability-lab-pre-send-scoring) 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:

```text theme={null}
version: STSv1
mode: enforce
mx: send.example.com
mx: *.example.com
max_age: 604800
```

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

| Mode | What receivers do | When to use it |
| - | - | - |
| `testing` | Try TLS versus the policy, but **do not fail the delivery** on a mismatch; failures still report via TLS-RPT. | First publish. Mail flows while you collect report data. |
| `enforce` | **Refuse to deliver** unless the connection is authenticated TLS matching the policy. | Steady state. Downgrade attempts now cost the attacker the delivery instead of exposing the message. |
| `none` | Turn the policy off for receivers that cached it. | A deliberate, transitional off-ramp — use it while you decommission, never as a permanent answer. |

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:

```text theme={null}
v=TLSRPTv1; rua=mailto:tlsrpt@example.com
```

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](/concepts/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](/concepts/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.
