MTA-STS generator

MTA-STS is how you tell a sender that mail to your domain must arrive over TLS to a receiving MX that matches a list you publish, and that if either condition isn’t met the sender should either report the failure (testing) or refuse to deliver (enforce). It exists because opportunistic STARTTLS is trivially downgraded — a network attacker between two MTAs can strip the STARTTLS capability off the EHLO response and the sender will happily fall back to plaintext. MTA-STS pins the receiver’s TLS requirement out of band so the sender knows the downgrade happened and can refuse.

Three pieces have to line up: a mta-sts.txt policy file served over HTTPS on a mta-sts.<domain> hostname, a _mta-sts.<domain> TXT record that publishes the policy’s version + ID so senders know when to re-fetch, and a _smtp._tls.<domain> TLS-RPT TXT record that tells receivers where to send the aggregate delivery-failure reports. This generator builds all three from one form and shows you where each piece has to live.

Default 2592000 = 30 days. Longer = better cache hits at senders; shorter = faster to roll back a bad policy.

Policy mode

These are the hostnames your inbound MX records resolve to at the receiving side, not the sending relay. Pull them from dig +short MX example.com.

Must change every time you publish a new policy. The suggestion is YYYYMMDDHHMM in UTC; keep it if you have no better scheme.

  • No MX patterns yet — add at least one line matching your inbound MX host (wildcards like *.mx.example.com are allowed).
  • No TLS-RPT reporting address set. Reports go to /dev/null; you'll never see delivery failures.

Policy file: https://mta-sts.example.com/.well-known/mta-sts.txt

Serve this text at that URL over HTTPS, from the mta-sts.<domain> hostname, with a valid TLS certificate for that hostname. Content-Type text/plain.

MTA-STS.TXT
version: STSv1
mode: testing
max_age: 2592000

DNS TXT: _mta-sts.example.com

Publish as a TXT record on that host. Bump id= every time you change the policy file — senders re-fetch when the ID changes.

TXT
v=STSv1; id=202608190757

DNS TXT: _smtp._tls.example.com

TLS-RPT is independent of MTA-STS mode — publishing it alone still gets you aggregate delivery-failure reports from receivers that support it (Google, Microsoft, Yahoo).

TXT
v=TLSRPTv1; rua=

Everything is generated in your browser after the first render. Nothing you type is uploaded — no analytics on the field values, no round-trip to build the record. If you’re wiring this on your DNS + web tier, cross-check the result against a live checker like nanoPost’s DNS auth checker, which flags a missing or mismatched MTA-STS setup end to end.

Testing versus enforce

Testing mode is the shape of a normal MTA-STS rollout. Senders that support the protocol honor the policy file and pin your MX list, but they don’t reject when a message fails — instead the failure lands in the daily TLS-RPT aggregate report you’ll get at the address in your _smtp._tls record. That’s what you use to confirm the policy matches reality: no legitimate mailer is being blocked by an MX pattern you forgot, no fallback path is quietly downgrading to plaintext, no cert on mta-sts.<domain> is expiring under you. Run testing for at least a couple of weeks with reports coming in and no failures before you flip to enforce.

Enforce mode is the same policy file with mode: enforce. Senders now reject any message whose delivery would fail the MTA-STS check, and the receiver never sees it. That’s the value of the protocol, and it’s also the reason the failure modes matter: an expired cert on mta-sts.<domain>, a stale policy ID, or an MX pattern that no longer matches your inbound host, will all cause silent inbound delivery failures. Enforce mode is a live-fire setting; don’t turn it on until testing has been quiet.

none mode is a retraction. Publish it when you’re tearing MTA-STS down so senders’ cached policies expire cleanly instead of hanging around for the length of the previous max_age.

TLS-RPT works on its own

The _smtp._tls record is defined by RFC 8460 and is independent of MTA-STS. Publishing TLS-RPT alone — with no policy file, no _mta-sts record — gets you aggregate reports from receivers that support it (Google, Yahoo, and Microsoft 365 all do) about the TLS handshakes and DANE/MTA-STS checks their outbound side runs against yours. If you’re not ready to publish an MTA-STS policy, publish TLS-RPT anyway. It costs nothing, and the reports are a useful early warning when a cert on your inbound MX starts to fail.

DANE is a different mechanism

DANE (RFC 7671) also pins the receiver’s TLS requirement, but does it in DNS under DNSSEC using a TLSA record on the MX host instead of a policy file on an HTTPS endpoint. Adoption is much narrower than MTA-STS — the whole DNSSEC prerequisite is why — and the two are complementary rather than substitutes; nothing stops you from publishing both. This tool doesn’t emit TLSA records. If DANE is what you want, see your MTA docs (Postfix and Exim both support it) and a DNSSEC-signed zone at your DNS host.

Serving the policy file

The policy file lives at exactly https://mta-sts.<domain>/.well-known/mta-sts.txt, over HTTPS, with a valid TLS certificate for the mta-sts.<domain> hostname. Content-Type is text/plain. HTTP-only won’t work — senders that follow RFC 8461 are required to reject a plaintext fetch. Nor will a self-signed or wrong-hostname cert. On WordPress hosts, the simplest route is a Cloudflare Worker or an Nginx server block that responds to that one hostname with the file body and terminates TLS with a Let’s Encrypt cert issued for it.

Every time you change the policy file, you also have to bump the id= value in the _mta-sts TXT record. Senders cache the policy against that ID; if the ID doesn’t change, senders never re-fetch and your updates never take effect.

When you’re ready to check it worked

Once the policy is live, the DNS auth checker reads your live SPF, DKIM, DMARC, MTA-STS, and TLS-RPT records over DNS-over-HTTPS and scores them against the Gmail, Yahoo, and Microsoft 365 bulk-sender requirements. A missing _mta-sts record, a stale ID that doesn’t match the served policy file, or a _smtp._tls record with no valid rua= all show up on the compliance scorecard there.