MTA-STS policy file is malformed
Updated
What this check looks for
The policy file exists but cannot be understood. Senders discard it and go back to unencrypted delivery.
Why it matters
All of the setup work is done and none of it is having any effect, which is very hard to notice from the outside.
When the check passes, your report says: “The MTA-STS policy file is well formed and readable”.
What it costs your score
When this check fails it removes 12 points from your Email transport score, before the status, confidence and repeat multipliers are applied. Email transport carries a weight of 8 in the overall score.
It shares the email-transport.mta-sts family ceiling of 25 points: however many findings that family produces, together they cannot remove more than that from Email transport. One underlying problem showing up in several places is still one problem.
- Severity
- high
- Default confidence
- confirmed
- Status when triggered
- fail
- Deduction
- 12 points
- Family cap
- email-transport.mta-sts · 25
- Category
- Email transport
- Module
- Email mta sts
- Fix owned by
- user
- In the ruleset since
- 2026.09
How to fix it
Regenerate the policy file and re-upload it.
An unparseable policy is discarded, leaving delivery unprotected.
Fetch the file as a sender would, with
curl -sS -D - https://mta-sts.‹domain›/.well-known/mta-sts.txt, and expect200, no redirect andtext/plain.Fix the line the error names, or regenerate the file with the generator, which writes CRLF line endings.
Re-upload it and confirm the served bytes match. Converting CRLF to LF on the way is harmless; a tool that leaves a carriage return without its LF is not.
Update the
idin the_mta-sts.‹domain›TXT record, so senders that cached the old file fetch the new one.
How to confirm it worked
curl -s https://mta-sts.‹domain›/.well-known/mta-sts.txt | cat -A — expect each line to end in $ (^M$ for CRLF), never ^M alone
Where
cat -Ais not available, as on macOS, pipe the output tood -cinstead and expect\nor\r \nat each line end.
A named slot like ‹domain› — and the braces left in the configuration below — is filled in with your own values when this rule appears on a report.
Technical detail
Parsing https://mta-sts.‹domain›/.well-known/mta-sts.txt failed: ‹parse error›.
RFC 8461 §3.2 defines the file as key: value lines. It needs version: STSv1; a mode of enforce, testing or none; one mx: line per allowed mail host, where *.example.net stands for exactly one label; and a max_age in whole seconds, no more than 31557600. Only mx may repeat. When another key is given twice, RFC 8461 §3.2 says the first entry is the one in force and every later one is ignored; this check does the same and notes the ignored line, so a mode: enforce added below an old mode: testing changes nothing until the old line is removed. Unknown keys are ignored, so a misspelt key is lost rather than rejected: max-age with a hyphen leaves the policy with no lifetime at all.
The standard's text describes CRLF-separated lines, while its formal grammar (sts-policy-term = LF / CRLF) also accepts a bare LF, so this check accepts either, and a mix of the two. CRLF is still the form every reading accepts, which is why our generator writes it. A carriage return on its own, with no LF after it — the old Mac convention — fits neither, and this check reports it.
Senders fetch the file over HTTPS from the mta-sts host and must not follow redirects, so the address above has to answer 200 directly, with a certificate valid for mta-sts.‹domain› and a text/plain content type. A policy that cannot be used is treated like one that could not be fetched: a sender keeps applying a policy it cached earlier, if it has one, and otherwise delivers as though MTA-STS were not deployed.
Standards and references
Test this on your domain
Run the check that produces this finding, on its own, against any domain.