MTA-STS Checker

Check a domain's MTA-STS record, policy file and every mail server's certificate on port 25, the way a sending server does. Then generate a policy.

RFC 8461 · every MX tested on port 25 from our own server · Gmail and Microsoft 365 rules

We fetch the domain's policy file from our server and dial each mail server on port 25 from our probe server. No mail is sent.

What we contact

The DNS questions go to the domain's own nameservers, Google Public DNS and Cloudflare's 1.1.1.1. The policy file and its certificate are read from our servers. Each mail server, up to 6 a check, is dialled on port 25 from our probe server, probe.dnsrobot.net: it says EHLO, starts TLS, reads the certificate and quits, with no MAIL FROM and no message. Results are kept for up to 10 minutes, so repeat checks don't dial the servers again. The Generate tab runs in your browser.

MTA-STS Checker: gmail.com's policy in enforce mode and each of its mail servers tested on port 25MTA-STS Checker: gmail.com's policy in enforce mode and each of its mail servers tested on port 25Type a domainThe domain after the @ in your addresses. An email address works too: its domain is checked.The verdictOne sentence: protected, at risk, testing, opting out, not working at a named step, or no MTA-STS at all.What a sending server seesThe five checks a sender makes, in order: the record, the policy host's certificate, the file, the MX patterns, each mail server.Every mail serverEach MX dialled on port 25 from our probe server: STARTTLS, the TLS version and the certificate against the MX name.GenerateWrite the record, the policy file and TLS-RPT from your live MX, with hosting steps and each server's last result before you enforce.
A check of gmail.com: the record, the policy file and every mail server, tested the way a sending server tests them.

What is MTA-STS, and what does it protect against?

MTA-STS (RFC 8461) lets a domain tell sending mail servers to deliver to its MX only over TLS, to a server with a valid certificate for its name. Without it, STARTTLS is opportunistic: an attacker in the path can delete the server's STARTTLS offer, and the message travels in plain text although both servers support TLS.

The policy also keeps a sender from handing mail to an impostor. Each MX must match a name in your policy and present a certificate for that name from a public certificate authority, so an attacker who redirects the connection, by spoofing the MX record or rerouting traffic, is refused unless it holds a valid certificate for a name in your policy. In enforce mode the sender doesn't deliver; it treats the failure as temporary and retries later.

The protection starts once a sender has fetched and cached your policy, and it applies only to senders that check MTA-STS. Mail between two domains is held back only when both sides use MTA-STS and a check fails; everyone else's mail flows as before.

Without MTA-STS

  1. Sending server
  2. Attacker in the path
  3. mx1.example.com
  1. EHLO
  2. 250-STARTTLSSTARTTLS offer deleted

Sent in plain text

With MTA-STS (enforce)

Cached policy: TLS and mx1.example.com required

  1. Sending server
  2. Attacker in the path
  3. mx1.example.com

Not delivered: retried later

  1. Sending server
  2. TLS, certificate for mx1.example.com
  3. mx1.example.com

Delivered encrypted

One message to example.com, with and without a cached MTA-STS policy in enforce mode.

G1G2G3G13T30T34T45T85

How does a sending server use an MTA-STS policy?

Before it delivers, a sender looks up _mta-sts.<domain>, fetches the policy file from mta-sts.<domain> over HTTPS and caches it for max_age seconds. Then, for each MX in priority order, it checks the name against the policy's mx lines, insists on STARTTLS and validates the certificate against that MX name.

In enforce mode a server that fails is skipped and the sender tries the next one. When none passes, it must look for a newer policy before failing the message for good, and should retry later. A new id in the TXT record tells senders to fetch the file again; they should refresh about once a day, and keep using the cached policy when a refresh fails.

The first message to a domain may go out before the policy arrives, because a sender may fetch it in the background. And when the file can't be fetched and nothing is cached, the sender carries on as if the domain had no MTA-STS. So a broken policy host costs you protection, not mail, and a sender whose fetch failed should wait five minutes or more before trying the same id again.

  1. 1_mta-sts TXTv=STSv1; id=…
  2. 2Policy hostmta-sts.example.com:443
  3. 3Policy file/.well-known/mta-sts.txt
  4. 4MX matches an mx lineIn MX priority order
  5. 5STARTTLS + certificateport 25, SNI = the MX name
Cached for max_ageRefreshed about once a dayNew id: fetch the file again

Fails: try the next MX

No file, no cache: delivered as if no MTA-STS

The checks a sender makes, in order, and the cache that carries the policy from one message to the next.

T36T35T2T9T14T16T26T27T28T30T34

What goes in the MTA-STS record and the policy file?

The MTA-STS record is a TXT record at _mta-sts.<domain> with two fields: v=STSv1 first, then an id of 1 to 32 letters and digits that changes whenever the policy does. The MTA-STS policy is a text file with four keys: version, mode, max_age and one mx line per allowed mail server.

Both are strict and case-sensitive. Senders discard TXT records that don't begin with v=STSv1;, and when more than one remains they assume there's no policy at all. The record may be split into several strings, which senders join without spaces, or be a CNAME to a provider's record. In the file, a key is followed directly by its colon, lines may end in LF or CRLF, a repeated key counts only the first time, and unknown keys are ignored.

The file must answer 200 at https://mta-sts.<domain>/.well-known/mta-sts.txt, as text/plain, without a redirect and within 64 KB. Google adds two rules for its own console: version on the first line, and a max_age of at least 86400. Microsoft suggests a UTC timestamp as the id, such as 20261101093000Z, and a TTL of 3600 on the record.

The _mta-sts TXT record

Name_mta-sts.example.comTXT

v=STSv1; id=20261101093000Z

  • v=STSv1Must come first, exactly as written
  • id=1 to 32 letters and digits; new with every file

The policy file

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

  1. version: STSv1The only version: STSv1
  2. mode: enforceenforce, testing or none
  3. mx: mx1.example.comOne line per pattern
  4. mx: *.mx.example.netOne line per pattern
  5. max_age: 1209600Seconds senders keep it: up to 31557600

200 · text/plain · no redirect · up to 64 KB

Keys and values are case-sensitive

Google: version on line 1, max_age at least 86400

A made-up example.com record and policy file, taken apart field by field.

T1T2T3T5T6T7T8T10T12T13T15T18T19T20T21T22T23T24T76T77T86

How do MX patterns and wildcards match?

Each MX host must match one mx line: either its exact name, or a pattern that starts with *. where the * stands for exactly one label. So *.example.com matches mail.example.com, but not example.com itself and not a.mail.example.com.

A pattern that matches none of today's MX is allowed: RFC 8461 asks only that every MX match something, and it lets you add a new server's name before you move mail to it. Gmail's own policy lists smtp.google.com, a name none of gmail.com's MX used on 1 November 2026.

Keep wildcards narrow. RFC 8461 warns that *.example.com makes any host under example.com with a CA certificate a valid MX, and Microsoft calls its *.mail.protection.outlook.com an Exchange Online exception: elsewhere, wildcards "must not be used as the MX prefix". Write international names as A-labels (xn--…). An MX that is a CNAME breaks RFC 2181, and Microsoft 365 won't deliver to it under MTA-STS unless the policy also lists the final host.

Pattern · MX hostmx1.example.commail.example.coma.mail.example.comexample.comeu.mx.example.net
mx1.example.comExact nameMatchesNo matchNo matchNo matchNo match
*.example.comMatchesMatchesNo matchTwo labels: too deepNo matchThe name itself: no label for the *No match
*.mx.example.netNo matchNo matchNo matchNo matchMatches
Three patterns against five host names: the * covers one label, no more and no fewer.

T26T23T69T47T87T88T71T92O1

MTA-STS enforce vs testing: when do I switch?

Start in testing and switch to enforce once every mail server passes and your TLS-RPT reports are clean: Google recommends two weeks of testing, Cloudflare a few weeks. In testing, senders deliver even when a check fails and only report it; in enforce, they refuse.

Every change to the file needs a new id in the TXT record, and the order matters: publish the new file first, then the new id. A sender that sees a new id fetches the file again; one that saw the id before the file changed could keep the old policy for max_age. Microsoft's way out of an incident is the same move in reverse: back to testing, then a new id.

To remove MTA-STS, publish mode none with a short max_age, change the id, wait until every earlier max_age has passed, then delete the record and the file. Deleting the record alone doesn't clear a policy senders already cached.

  1. none New id
  2. Old copies expire after max_age
  3. Remove the record and the file
A rollout: two weeks of testing, then enforce, each change of the file followed by a new id.

T32T30T33T74T76T95T80T41T90T43T9

What is TLS-RPT, and what's in a report?

TLS-RPT (RFC 8460) is a TXT record at _smtp._tls.<domain>, such as v=TLSRPTv1; rua=mailto:tls-reports@example.com, that asks senders for a daily report on their TLS sessions with your mail servers. Each report is JSON, usually gzipped, with the successful and failed sessions and a result type for each failure.

The result types name the fault: starttls-not-supported, certificate-host-mismatch, certificate-expired and certificate-not-trusted for a mail server; sts-policy-fetch-error, sts-policy-invalid and sts-webpki-invalid for the policy itself; tlsa-invalid and dnssec-invalid for DANE. Busy networks and timeouts needn't be reported. Reports sent by mail must carry a DKIM signature from the reporting domain. Microsoft 365 sends reports, and Postfix has since version 3.10.

rua can list several mailto: or https: addresses separated by commas, and a reporter may use each or only one; a comma inside an address must be percent-encoded. The address can be at another domain, with no authorization record, unlike DMARC. Google Workspace has no endpoint for https: reports.

ReporterSent as application/tlsrpt+gzip, DKIM-signed

{
  1"organization-name": "Example Mail Inc.",
  2"date-range": {
    "start-datetime": "2026-10-31T00:00:00Z",
    "end-datetime": "2026-10-31T23:59:59Z"
  },
  "contact-info": "tlsrpt@mail.example.org",
  "report-id": "2026-10-31T00:00:00Z_example.com",
  "policies": [
    {
      "policy": {
        3"policy-type": "sts",
        4"policy-string": [
          "version: STSv1",
          "mode: testing",
          "mx: mx1.example.com",
          "max_age: 604800"
        ],
        5"policy-domain": "example.com",
        "mx-host": [
          "mx1.example.com"
        ]
      },
      "summary": {
        6"total-successful-session-count": 5326,
        7"total-failure-session-count": 41
      },
      "failure-details": [
        {
          8"result-type": "certificate-host-mismatch",
          9"sending-mta-ip": "198.51.100.25",
          10"receiving-mx-hostname": "mx2.example.com",
          11"receiving-ip": "192.0.2.40",
          12"failed-session-count": 41
        }
      ]
    }
  ]
}
  1. 1organization-name
  2. 2date-range: one UTC day
  3. 3policy-type: sts
  4. 4policy-string: the policy file's lines
  5. 5policy-domain
  6. 6total-successful-session-count
  7. 7total-failure-session-count
  8. 8result-type
  9. 9sending-mta-ip
  10. 10receiving-mx-hostname
  11. 11receiving-ip
  12. 12failed-session-count

result-type

Mail serverstarttls-not-supportedcertificate-host-mismatchcertificate-expiredcertificate-not-trustedvalidation-failure

MTA-STS policysts-policy-fetch-errorsts-policy-invalidsts-webpki-invalid

DANEtlsa-invaliddnssec-invaliddane-required

A made-up daily report for example.com: one reporter, one policy, one kind of failure.

T53T54T55T57T58T59T60T61T62T79T93T97

Where can I host the MTA-STS policy file?

Anywhere that serves https://mta-sts.<domain>/.well-known/mta-sts.txt with a certificate for that name, a 200 answer, Content-Type text/plain and no redirect. A static host is enough, as long as only you can publish files on it: RFC 8461 warns that a host where others can upload could serve a policy of their own.

Each host has a setting that can break the file. GitHub Pages runs Jekyll, which skips folders that start with a dot, so .well-known needs a .nojekyll file or an include line in _config.yml. Netlify's docs don't say which Content-Type a .txt file gets, so set it in _headers. On nginx and Apache, a site-wide redirect to www or to an app also catches the policy URL; give mta-sts.<domain> its own server block. On Cloudflare, bot protection that covers static resources covers /.well-known/ too.

Exchange Online can't host the file for you: Microsoft recommends Azure Static Web Apps, which issues the certificate itself, over Azure Functions, where you bind your own. Cloudflare Email Routing customers can delegate the whole policy to Cloudflare with a CNAME and a small Worker.

  • Cloudflare Workers

    Certificate
    Issued for you
    Content-Type
    Set it yourself

    Watch: If bot protection covers static resources, it covers /.well-known/ too: a challenge page is not a policy.

    G14T111T110

  • Cloudflare Email Routing

    Certificate
    Issued for you
    Content-Type
    Set it yourself

    Watch: Delegating gives you Cloudflare's policy, which is already in enforce mode with a one-day max_age.

    T95T42G14

  • GitHub Pages

    Certificate
    Issued for you
    Content-Type
    From the .txt extension

    Watch: Jekyll skips folders that start with a dot, so .well-known disappears unless you add .nojekyll or include it in _config.yml.

    T106T107T108

  • Netlify

    Certificate
    Issued for you
    Content-Type
    Not documented: set it

    Watch: Netlify's docs don't say which Content-Type a .txt file gets: set text/plain in _headers. Headers don't apply to proxied or function responses.

    T109

  • nginx

    Certificate
    Bring your own
    Content-Type
    From the .txt extension

    Watch: A catch-all return 301 or a try_files fallback to index.html answers the policy URL with a redirect or HTML.

    G7G8T12T13

  • Apache HTTP Server

    Certificate
    Bring your own
    Content-Type
    From the .txt extension

    Watch: A site-wide Redirect or RewriteRule (to www, to an app's index.php) catches the policy URL too.

    G9G10T13

  • Azure Static Web Apps

    Certificate
    Issued for you
    Content-Type
    From the .txt extension

    Watch: Microsoft's sample mx line, *.mail.protection.outlook.com, is for Exchange Online only: list your other providers' MX by name.

    G11T89T88

  • Azure Functions

    Certificate
    Bring your own
    Content-Type
    Set it yourself

    Watch: Azure issues no certificate here: bind your own for mta-sts.<domain>, and remove the /api route prefix.

    G12T89

Where to host the file, and the setting to watch on each host.

Which mail senders enforce MTA-STS?

Gmail and Microsoft 365 do, by their own documentation: Gmail complies with policies in enforce mode, and Exchange Online has validated MTA-STS on all outgoing mail since February 2022. Postfix does with the postfix-mta-sts-resolver add-on, which by default skips policies in testing.

When Microsoft 365 won't deliver, the sender may get a bounce: 5.4.8 when the MX isn't in your policy, 5.7.5 when the mail server's certificate fails. Exchange Online checks a smart host's domain rather than the recipient's, and won't deliver to a domain whose MX is a CNAME unless the policy also lists the final host. postfix-mta-sts-resolver lets an MTA-STS policy override DANE, against RFC 8461, and gives up on a policy host after 4 seconds.

Yahoo, Proton and Fastmail publish policies for their own domains, but we found no page from them, or from Zoho, saying whether they check other domains' policies when sending. Exim has no built-in support. Where your MX also has DANE records, a sender that supports DANE checks those first. And a message with the header TLS-Required: No asks senders to skip MTA-STS and DANE for it.

SenderEnforce modeTesting modeSource
Gmail and Google WorkspaceChecks itComplies with policies in enforce mode when sending to external servers.Not documented: Google's page covers enforce mode only.

T72T73T75

Microsoft 365 (Exchange Online)Checks itValidates MTA-STS on all outgoing mail, always on; nothing for admins to switch on.When it won't deliver:5.4.8 The MX isn't matched by any mx line in the policy.5.7.5 The mail server's certificate doesn't chain to a trusted root or doesn't name the MX host.Fetches the policy but doesn't enforce it.

T83T84T85T90T92T94T93

Postfix with postfix-mta-sts-resolverWith an add-onEnforces enforce-mode policies through Postfix's smtp_tls_policy_maps.Skipped by default; enforced only with strict_testing: true.

T97T98T99T101T102

Postfix on its ownNot built inNo built-in MTA-STS: it needs a policy plugin.—

T97

EximNot built inNo built-in MTA-STS or TLS-RPT in Exim's own change log.—

T104

Yahoo MailNot documentedPublishes its own policy (testing on 2026-11-01).—

T105O3

Proton MailNot documentedPublishes its own policy (enforce on 2026-11-01).—

T105O5

FastmailNot documentedPublishes its own policy (testing on 2026-11-01).—

T105O5

Zoho MailNot documentedPublishes TLS-RPT but no MTA-STS policy for zoho.com (2026-11-01).—

T105O5

Where an MX also has DANE records, a sender that supports DANE checks them first, and MTA-STS may not override a DANE failure.

A message carrying TLS-Required: No asks senders to ignore MTA-STS and DANE for it.

Who checks your policy when sending, from each sender's own documentation or code.

T31T96T70

MTA-STS FAQ

How do I check MTA-STS?

Type the domain above and press Check. The checker reads the _mta-sts TXT record, fetches https://mta-sts.<domain>/.well-known/mta-sts.txt with a sender's rules (no redirects, a 200 answer, text/plain), checks the certificate on that host, matches every MX against the policy's mx lines, and dials each mail server on port 25 for STARTTLS and its certificate. By hand, dig TXT _mta-sts.example.com and curl on the policy URL cover the first steps.

Is MTA-STS worth it?

Yes, if your mail servers already have valid certificates. Without it, an attacker in the network path can delete the STARTTLS offer, and mail travels in plain text. With an enforce policy, Gmail and Microsoft 365 refuse that connection, and any impostor server. The cost is a small text file and two TXT records, kept in step with your MX. It protects mail only from senders that check it, once they've fetched your policy.

How do I enable MTA-STS?

Serve a policy file at https://mta-sts.<domain>/.well-known/mta-sts.txt with version, mode, max_age and one mx line per mail server. Then publish a TXT record at _mta-sts.<domain>: v=STSv1; id= and a UTC timestamp. Add a TLS-RPT record at _smtp._tls.<domain> for reports. Start in testing mode, read the reports for about two weeks, then switch the file to enforce and publish a new id. The Generate tab above writes all three.

Testing or enforce: when do I switch?

Switch when every MX matches an mx line, every mail server offers STARTTLS with TLS 1.2 or later and a valid certificate for its own name, and your TLS-RPT reports show no failures. Google recommends about two weeks of testing; Cloudflare says a few weeks. Testing blocks nothing: Gmail and Microsoft 365 act only on enforce. To switch, change the mode in the file first, then publish a new id in the record.

What max_age should I use?

One to two weeks (604800 to 1209600 seconds) while testing, as Google recommends, and weeks or more once you enforce, as RFC 8461 expects. A longer max_age keeps your policy in senders' caches through a refresh an attacker blocks. The maximum is 31557600, about a year, and Google's console refuses anything under 86400. Shorten it before you remove MTA-STS, so old copies expire sooner.

My MX isn't in the policy: what happens?

In enforce mode, senders that check MTA-STS won't deliver to that server. They try your other MX in priority order; if none passes, they should keep the message queued and retry rather than bounce at once, and a bounce from Microsoft 365 carries code 5.4.8. In testing mode they deliver anyway and report it. Add the host as an mx line, publish the file, then publish a new id.

Do I need TLS-RPT too?

It isn't required, but without it you won't know when a sender's checks fail. TLS-RPT is a TXT record at _smtp._tls.<domain> naming a mailto: or https: address. Senders that support it send a daily JSON report of successful and failed sessions, with the reason for each failure. It's what makes testing mode useful: the reports show what enforce would block before it blocks anything.

MTA-STS or DANE?

Both, if you can. DANE pins your servers' certificates in DNS and needs DNSSEC, which also resists an attacker who blocks the policy lookup. MTA-STS needs only a public certificate and an HTTPS file, but it trusts the first fetch and the certificate authorities. When both are present, a sender that supports DANE checks it first, and MTA-STS can't override a DANE failure. Microsoft 365 supports both on the same domain.

Missing something?Suggest a feature or a new tool