dotvitals

Loading the list of pages…

↑↓ to moveEnter to openEsc to close

MTA-STS policy file is malformed

Updated

HighConfirmedQuick winemail.mta-sts.policy-invalid

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 the whole score is calculated

How to fix it

Regenerate the policy file and re-upload it.

An unparseable policy is discarded, leaving delivery unprotected.

  1. Fetch the file as a sender would, with curl -sS -D - https://mta-sts.‹domain›/.well-known/mta-sts.txt, and expect 200, no redirect and text/plain.

  2. Fix the line the error names, or regenerate the file with the generator, which writes CRLF line endings.

  3. 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.

  4. Update the id in 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 -A is not available, as on macOS, pipe the output to od -c instead and expect \n or \r \n at 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.

Open the email mta sts checkerBuild the fix