Skip to content

MTA-STS & TLS-RPT Checker

MTA-STS tells sending mail servers that your domain requires TLS and names the MX hosts allowed to receive it. This checker reads the _mta-sts TXT record, fetches the HTTPS policy file, validates mode, mx and max_age against your real MX records, and confirms TLS-RPT reporting is in place.

The problem MTA-STS solves

SMTP between servers is opportunistically encrypted. The sending MTA connects on port 25, the receiver advertises STARTTLS, and the sender upgrades the connection. Nothing in that exchange is authenticated: an attacker positioned between the two hosts can strip the STARTTLS advertisement from the receiver's greeting, and a well-behaved sender will silently fall back to plaintext. Most senders will also accept an expired, self-signed, or wrong-hostname certificate, because refusing would mean bouncing legitimate mail.

MTA-STS (RFC 8461) fixes this by letting a domain publish a policy, out of band over HTTPS, that says: *my MX hosts are these, they support TLS, and their certificates validate — if you cannot get that, do not deliver.* Because the policy is fetched over HTTPS with normal certificate validation and then cached for max_age, an attacker who can tamper with SMTP cannot forge or suppress it.

The two halves that must both exist

MTA-STS is deliberately split across DNS and HTTPS, and a domain with only one half is in a worse position than a domain with neither, because it looks configured while doing nothing.

Read the full explanation of mta-sts & tls-rpt checker results ↓

1. The DNS TXT record

_mta-sts.example.com. 3600 IN TXT "v=STSv1; id=20260901T120000;"

The id is an opaque version string of up to 32 alphanumeric characters. Senders cache your policy and re-fetch it only when the id changes — so you must bump the id every time you edit the policy file, or senders will keep using the cached copy until max_age expires. A date-stamp format like 20260901T120000 is the convention.

2. The HTTPS policy file

Served as text/plain at https://mta-sts.<domain>/.well-known/mta-sts.txt, from a host whose certificate is valid for mta-sts.<domain>:

version: STSv1
mode: enforce
mx: mx1.example.com
mx: mx2.example.com
mx: *.mail.example.com
max_age: 604800
A production policy file
The policy must be served directly, with no redirect. RFC 8461 §3.3 requires senders to fetch it without following redirection, so a host that 301s from mta-sts.example.com to www.example.com silently breaks the whole mechanism. This checker reports a redirect as a failure rather than following it.

Reading each policy field

FieldValuesNotes
versionSTSv1Must be exactly this. Anything else means the whole policy is ignored.
modeenforce, testing, noneOnly enforce actually prevents downgrade. testing reports failures but still delivers. none is how you retire a policy safely.
mxhostname or *.hostnameOne line per pattern. A single leading *. wildcard matches exactly one label — *.example.com matches a.example.com but not a.b.example.com.
max_age1 – 31557600 secondsHow long senders cache the policy. 604800 (one week) is the usual production value.

The mx list must cover every host in your MX record set. This checker resolves your real MX records and reports any that the policy does not match, because that is the failure that takes mail down: in enforce mode, a sender that resolves an uncovered MX host refuses to deliver to it entirely. Cross-check your MX set with the MX lookup tool whenever you change mail providers.

A short max_age weakens the protection: it is the window an attacker gets after a policy is withdrawn, and also the window in which senders re-check. Anything under a day gives an attacker a realistic opportunity. The exception is during rollout, where a short value lets you back out quickly — set 86400 while testing, raise it to 604800 once you are confident.

TLS-RPT: the part people skip

TLS-RPT (RFC 8460) is a separate TXT record that asks senders to send you daily JSON reports about TLS negotiation outcomes:

_smtp._tls.example.com. 3600 IN TXT "v=TLSRPTv1; rua=mailto:[email protected]"

Publish this before you set mode: enforce, not after. It is the only way to discover that some sender cannot validate your certificate, or that one of your MX hosts is missing from the policy, without users reporting bounced mail. The reports name the sending organisation, the policy they applied, and the count of successful and failed sessions. rua accepts mailto: and https: destinations, comma-separated.

TLS-RPT is useful on its own even without MTA-STS. Publishing just the _smtp._tls record tells you how often senders are already failing to negotiate TLS with your MX hosts — often a surprise.

A safe rollout order

  1. Confirm every MX host answers on port 25 with STARTTLS and a certificate valid for its own hostname. Check the certificate with the SSL certificate checker and reachability with the SMTP connection test.
  2. Publish the TLS-RPT record at _smtp._tls.<domain> and wait a week for reports.
  3. Stand up mta-sts.<domain> with a valid certificate, serving the policy file with mode: testing and max_age: 86400.
  4. Publish the _mta-sts.<domain> TXT record with an id.
  5. Watch TLS-RPT reports for a fortnight. Any failures now are exactly the failures that would have bounced mail in enforce mode.
  6. Change the policy file to mode: enforce, raise max_age to 604800, and bump the id in the TXT record. Both edits, every time.

To retire a policy, never simply delete it — senders holding a cached enforce policy will keep enforcing it for up to max_age. Instead set mode: none, bump the id, wait out the old max_age, and only then remove the DNS record and the host.

Checking MTA-STS from the command line

# 1. The DNS half
dig +short _mta-sts.example.com TXT
dig +short _smtp._tls.example.com TXT

# 2. The HTTPS half — note --max-redirs 0, a redirect here is a bug
curl -sS --max-redirs 0 -i https://mta-sts.example.com/.well-known/mta-sts.txt

# 3. Do the MX hosts in the policy match reality?
dig +short example.com MX | sort -n

# 4. Does each MX host actually present a valid certificate on port 25?
openssl s_client -starttls smtp -connect mx1.example.com:25 \
  -servername mx1.example.com -verify_return_error < /dev/null 2>&1 \
  | grep -E 'Verify return code|subject=|DNS:'
Verify both halves and the certificate behind them

Step 4 is the one that catches real outages. -verify_return_error makes openssl fail rather than warn, which is what an MTA-STS-enforcing sender effectively does. If it prints anything other than Verify return code: 0 (ok), that host will refuse mail from enforcing senders once your policy goes live.

MTA-STS and DANE solve the same problem differently: DANE anchors the certificate in DNSSEC-signed TLSA records, MTA-STS anchors it in the web PKI plus HTTPS. They coexist happily, and large receivers support both. If your zone is already DNSSEC-signed — check with the DNSSEC checker — DANE is worth adding alongside.

Frequently asked questions

Do I need a separate web server for mta-sts.example.com?
You need a host that answers HTTPS on that name with a certificate valid for it, but it can be anything — a subdomain on your existing web server, an S3 bucket behind a CDN, a static-site host. It serves exactly one file. What it must not do is redirect, because senders are forbidden from following redirects when fetching the policy.
What happens if I change the policy file but forget to bump the id?
Nothing, for up to max_age. Senders decide whether to re-fetch the policy by comparing the id in the TXT record against the one they cached. An unchanged id means "no change here", so your edit is invisible until the cache expires. If you set max_age to a week, that is a week of the old policy still being enforced.
Will enforce mode bounce mail if one MX host has a bad certificate?
Yes, from senders that honour the policy — that is the entire point. They will defer or reject delivery to that host rather than fall back to an unauthenticated connection. This is why you run mode: testing with TLS-RPT first: the reports show you exactly which hosts would fail before any real mail is affected.
Does MTA-STS encrypt the message itself?
No. It protects the transport hop between mail servers by preventing a downgrade to plaintext and requiring a valid certificate. The message sits unencrypted on every server along the way. For end-to-end confidentiality you need S/MIME or PGP, which are unrelated to MTA-STS.
How do wildcard mx patterns work?
A pattern may start with a single *. which matches exactly one DNS label. *.mail.example.com matches mx1.mail.example.com but not mail.example.com itself and not a.b.mail.example.com. Wildcards anywhere other than the leading label are invalid. When a provider gives you a wildcard pattern, make sure your actual MX hostnames have the right number of labels to match it.
Is MTA-STS worth it if I use Google Workspace or Microsoft 365?
Yes, and it is cheap: both providers' MX hosts already have valid certificates, so the work is publishing the two records and a static file. Google publishes an enforcing policy for gmail.com itself, which is a good template. The protection applies to mail arriving at your domain, so it is your policy to publish even though someone else runs the servers.
Why does my policy fetch fail with a certificate error?
The certificate on mta-sts.<domain> must be valid for that exact name. A common mistake is pointing the subdomain at a host whose certificate only covers the apex and www, or at a CDN distribution where the custom hostname was never added. Check it with openssl s_client -connect mta-sts.example.com:443 -servername mta-sts.example.com.
What is the difference between MTA-STS and DMARC?
They protect different things. DMARC is about who is allowed to use your domain in the From: address of outbound mail, enforced through SPF and DKIM alignment. MTA-STS is about how mail arrives at your servers being encrypted and delivered to the right hosts. You want both; neither substitutes for the other.