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

# DNS Mail MTA-STS

> Checks the MTA-STS DNS record and policy file that force sending servers to deliver email to the domain only over verified TLS.

<Info>
  **Security Auditor** — checks that the domain of the audited URL advertises SMTP MTA Strict Transport Security (MTA-STS) with a `_mta-sts` TXT record and serves a policy file in `enforce` mode, so email sent to the domain cannot be downgraded to plaintext or delivered to an impostor mail server.
</Info>

<CardGroup cols={2}>
  <Card title="Protection" icon="shield-halved">
    Stops attackers on the network path from stripping TLS or redirecting email sent to your domain.
  </Card>

  <Card title="Standards" icon="book">
    Follows RFC 8461 (SMTP MTA Strict Transport Security), September 2018.
  </Card>
</CardGroup>

SMTP delivers email over TLS only opportunistically: when a sending server is told that TLS is unavailable, or is handed a certificate for the wrong name, it delivers anyway. MTA-STS lets a domain publish a policy saying "my mail servers always support TLS with a valid certificate; refuse to deliver otherwise". The policy is advertised with a TXT record at `_mta-sts.<domain>` and served over HTTPS at `https://mta-sts.<domain>/.well-known/mta-sts.txt`. This auditor checks both, for the domain of the audited URL (one leading `www.` is removed).

## How it works

1. **Domain** — takes the hostname of the audited URL and removes one leading `www.`. A URL with no hostname ends the audit with `501`. The audited page itself is never fetched.
2. **TXT record** — looks up the TXT records at `_mta-sts.<domain>`. A resolver failure (SERVFAIL, timeout) ends the audit with `500`; no record warns (`300`). Only the first record is read: it must start with `v=STSv1` and carry an `id=` tag, otherwise it warns (`301`) and the policy is not fetched.
3. **Policy fetch** — requests `https://mta-sts.<domain>/.well-known/mta-sts.txt` the way a sending server does (RFC 8461 section 3.3): a valid certificate is required, no TLS fallback, and redirects are not followed. A connection, TLS or timeout error warns (`305`); any status other than 2xx, including a redirect, warns (`304`).
4. **Mode** — reads the `mode:` line of the policy. `none` fails (`400`), `testing` warns (`302`), a missing or unrecognised mode warns (`303`), `enforce` passes (`200`).
5. **Aggregate** — FAIL wins over WARNING; the first rule that stops the audit (no record, malformed record, fetch problem) is the one reported.
6. **Specification pin** — every run emits `37A-DnsMailMtaStsAuditor-100` (`INFORMATION`), naming [RFC 8461 SMTP MTA Strict Transport Security](https://www.rfc-editor.org/rfc/rfc8461) (September 2018). It does not change the overall status.

## What it audits

Every row maps to one `checkRule*` method and one `CheckCode`, in the order the auditor runs them. CheckCode suffixes use status ranges: `100` information, `200` success, `300–399` warning, `400–499` fail, `500–599` error.

| CheckCode | Status | When it fires | Recommendation | Why it matters |
| - | - | - | - | - |
| <a id="37A-DnsMailMtaStsAuditor-100" />`37A-DnsMailMtaStsAuditor-100` | `INFORMATION` | Always. Records the specification this auditor implements: RFC 8461 SMTP MTA Strict Transport Security (September 2018). | — (recommendation is `null`; nothing for the site to change) | — |
| <a id="37A-DnsMailMtaStsAuditor-300" />`37A-DnsMailMtaStsAuditor-300` | `WARNING` | No TXT record exists at `_mta-sts.<domain>`, so MTA-STS is not advertised. | Publish a TXT record at `_mta-sts.{domain}` with "v=STSv1; id=\<timestamp>" (for example id=20260101000000Z) and serve the policy at `{policyUrl}`. | Without MTA-STS, a sending server that is downgraded to plaintext or pointed at an impostor mail server still delivers, so email to the domain can be read or altered in transit. |
| <a id="37A-DnsMailMtaStsAuditor-301" />`37A-DnsMailMtaStsAuditor-301` | `WARNING` | The first TXT record does not start with `v=STSv1` (case-insensitive) or has no `id=` tag. | Replace "`{record}`" at `_mta-sts.{domain}` with "v=STSv1; id=\<timestamp>" (for example id=20260101000000Z) and change the id every time the policy changes. | Sending servers ignore an MTA-STS record they cannot parse, so the policy is never fetched and email to the domain gets no transport protection. |
| <a id="37A-DnsMailMtaStsAuditor-305" />`37A-DnsMailMtaStsAuditor-305` | `WARNING` | Fetching the policy URL failed with a connection, TLS or timeout error. | Make `{policyUrl}` reachable over HTTPS with a certificate valid for `mta-sts.{domain}` (sending servers do not fall back, RFC 8461 section 3.3). Last error: `{error}`. | A policy host that cannot be reached over valid HTTPS gives sending servers nothing to enforce, so the advertised MTA-STS protection is not applied to email. |
| <a id="37A-DnsMailMtaStsAuditor-304" />`37A-DnsMailMtaStsAuditor-304` | `WARNING` | The policy URL answered a status other than 2xx (a redirect counts: RFC 8461 section 3.3 forbids following it). | Serve the policy file at `{policyUrl}` with HTTP 200 directly (no redirect, RFC 8461 section 3.3) and a certificate valid for `mta-sts.{domain}`; it currently answers HTTP `{status}`. | When the policy cannot be fetched, sending servers that never cached it deliver without MTA-STS protection and those that cached it stop refreshing it. |
| <a id="37A-DnsMailMtaStsAuditor-400" />`37A-DnsMailMtaStsAuditor-400` | `FAIL` | The policy says `mode: none`. | Change "mode: none" to "mode: enforce" (or "mode: testing" while validating) in `{policyUrl}` and bump the id in the `_mta-sts.{domain}` TXT record. | Mode none tells every sending server to drop the policy, so email to the domain can be downgraded to plaintext or sent to an impostor server without anyone noticing. |
| <a id="37A-DnsMailMtaStsAuditor-302" />`37A-DnsMailMtaStsAuditor-302` | `WARNING` | The policy says `mode: testing`. | Once your TLS-RPT reports show no failures, change "mode: testing" to "mode: enforce" in `{policyUrl}` and bump the id in the `_mta-sts.{domain}` TXT record. | In testing mode a downgrade or certificate problem is only reported, never refused, so email to the domain can still be intercepted while the policy looks deployed. |
| <a id="37A-DnsMailMtaStsAuditor-303" />`37A-DnsMailMtaStsAuditor-303` | `WARNING` | The policy has no `mode` line or a value other than `enforce`, `testing` or `none`. | Set "mode: enforce" in `{policyUrl}` (RFC 8461 allows enforce, testing or none, not "`{mode}`") and bump the id in the `_mta-sts.{domain}` TXT record. | Sending servers discard a policy whose mode they do not recognise, so the domain gets no transport protection despite advertising MTA-STS. |
| <a id="37A-DnsMailMtaStsAuditor-200" />`37A-DnsMailMtaStsAuditor-200` | `SUCCESS` | The TXT record is valid and the policy fetched with HTTP 2xx says `mode: enforce`. Message names the policy URL and the record id. | — | — |
| <a id="37A-DnsMailMtaStsAuditor-500" />`37A-DnsMailMtaStsAuditor-500` | `ERROR` | The resolver failed (SERVFAIL, timeout) on the `_mta-sts.<domain>` TXT lookup, so the record may well exist. | Check that the name servers answering for `_mta-sts.{domain}` respond to TXT queries, then run the audit again. Last error: `{error}`. | — |
| <a id="37A-DnsMailMtaStsAuditor-501" />`37A-DnsMailMtaStsAuditor-501` | `ERROR` | The audited URL is empty, malformed or has no hostname, so no domain can be derived. | Monitor an absolute URL with a hostname (for example [https://example.com/](https://example.com/)) instead of "`{url}`", then run the audit again. | — |

## Output documentation

| Status | Description | Test logic |
| - | - | - |
| **SUCCESS** | MTA-STS is advertised and enforced | Valid `_mta-sts` TXT record and a policy fetched with HTTP 2xx whose mode is `enforce` (`200`). |
| **WARNING** | MTA-STS is missing, unreadable or not enforcing | No TXT record (`300`); malformed record (`301`); policy in `testing` mode (`302`); unknown or missing mode (`303`); policy URL not 2xx (`304`); policy fetch failed (`305`). |
| **FAIL** | MTA-STS is switched off by the policy | Policy mode `none` (`400`). |
| **ERROR** | The auditor could not run the check | DNS lookup failure (`500`); URL without a hostname (`501`). |
| **INFORMATION** | Specification pin | Always emitted (`100`); does not change overall status. |

Every check carries the audited URL as its resource and, in `data`, the fields relevant to that step: `domain`, `mtaStsFqdn`, `txtRecords`, `mtaStsRecord`, `policyId`, `policyUrl`, `policyHttpStatus`, `policyMode`, `policyBody` (capped at 2 KB) and `policyFetchError`.

## Risks and considerations

### Why MTA-STS matters

* Without it, an attacker on the network path can tell a sending server that your mail servers do not support TLS, or present any certificate, and the message is delivered in the clear.
* MTA-STS works with DANE and TLS-RPT: TLS-RPT (`_smtp._tls.<domain>`) is how you learn about delivery failures before switching from `testing` to `enforce`.

### Modes

* `enforce` is the only mode that protects email; `testing` only reports problems, and `none` tells senders to forget the policy (used to retire it).
* Every change to the policy file needs a new `id` in the TXT record, otherwise sending servers keep the cached version until `max_age` expires.

### Policy hosting

* The policy must be served at `https://mta-sts.<domain>/.well-known/mta-sts.txt` with a certificate valid for `mta-sts.<domain>`; RFC 8461 forbids following redirects and falling back to HTTP, and this auditor does neither.
* The auditor reads only the `mode` line. `mx` entries and `max_age` are not validated against the domain's MX records.

### Behavior changes from the previous version

* A URL with no hostname used to `FAIL`; it is now `ERROR` (`501`), because the problem is with the monitored URL, not the domain.
* A DNS resolver failure used to be reported as "MTA-STS not advertised" (`WARNING`); it is now `ERROR` (`500`), because the record may exist.
* A TXT record that starts with `v=STSv1` but has no `id=` tag used to be accepted; it is now malformed (`301`).
* The policy body stored in check data is capped at 2 KB.
* All other verdicts are unchanged: `mode: none` stays `FAIL`; `testing`, an unknown mode, a non-2xx policy answer and a policy fetch error stay `WARNING`.

### What this auditor does not check

* Only the first `_mta-sts` TXT record is read; RFC 8461 says there must be exactly one.
* The policy's `mx` patterns, `max_age` and the actual TLS configuration of the mail servers are out of scope (see the DNS Mail MX and TLS-RPT auditors).


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.