security

How to Set Up MTA-STS: Step-by-Step Guide with Policy File and DNS Records

A copy-paste walkthrough of all three MTA-STS parts: the _mta-sts TXT record, the mta-sts.txt policy file served over HTTPS at the well-known path, and the mx, mode, and max_age directives. Includes dig and curl validation steps to confirm each piece resolves before you switch from testing to enforce mode, plus how MTA-STS relates to TLS-RPT, DANE, and DMARC.

Jul 3, 20268 min read

MTA-STS (SMTP MTA Strict Transport Security, RFC 8461) forces the servers that send you mail to use TLS and to verify your MX certificate before delivery. Without it, an active attacker can strip encryption during the SMTP handshake and read or redirect your inbound mail. Setting it up means publishing three things that must agree: a _mta-sts TXT record, a policy file served over HTTPS at a fixed path, and the mx, mode, and max_age directives inside that file. This guide walks through all three, then shows how to validate each piece before you switch from testing to enforce mode.

Reads public DNS only. Nothing is stored unless you save the domain to an account.

What MTA-STS actually does

SMTP was designed without mandatory encryption. When a sending server connects to your MX, it issues STARTTLS to upgrade the plaintext session to TLS. The problem is that STARTTLS is opportunistic: if the command is stripped from the connection or the certificate is invalid, most senders quietly fall back to plaintext and deliver anyway. That fallback is the exact gap a man-in-the-middle exploits.

MTA-STS closes it by letting you publish a policy that says "for my domain, TLS is required, and here are the MX hostnames whose certificates you should trust." A sending server that supports MTA-STS fetches your policy, caches it, and refuses to deliver over an unencrypted or unauthenticated connection. Google, Microsoft, and Yahoo all honor these policies on outbound mail, so the coverage is real even though not every sender participates yet.

It is worth being clear about scope. MTA-STS protects inbound mail to your domain (mail other people send to you). It does nothing for the messages you send out, and it is not an authentication control like SPF or DKIM. It sits alongside SPF, DKIM, and DMARC, not in place of them.

The three moving parts

A complete deployment has exactly three components, and all three must be consistent:

  1. A DNS TXT record at _mta-sts.<yourdomain> that advertises the policy and a version ID.
  2. An HTTPS endpoint at https://mta-sts.<yourdomain>/.well-known/mta-sts.txt that serves the policy file.
  3. The policy file contents themselves: the version, mode, mx, and max_age directives.

The TXT record tells senders a policy exists and when it last changed. The file tells them what the policy says. If the record points at a policy the HTTPS host cannot serve, senders treat it as if there is no policy at all, so getting both live matters.

Step 1: Publish the _mta-sts TXT record

Create a TXT record at the subdomain _mta-sts under your domain:

_mta-sts.example.com. IN TXT "v=STSv1; id=20260703000000Z"

The v=STSv1 tag is fixed. The id is an opaque string you control, and its only job is to signal change. Whenever you edit the policy file, bump the id to a new unique value (a timestamp like 20260703000000Z is a common convention). Senders compare the cached id to the current one to decide whether to refetch the file. If you never change the id, caching senders will keep using the old policy until their cache expires.

Step 2: Serve the policy file over HTTPS

The policy lives at one exact URL, on a subdomain named mta-sts:

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

Three requirements are non-negotiable here. The host must answer over HTTPS on port 443, the certificate must be valid and match mta-sts.example.com, and the file must be served as text/plain. A plain HTTP redirect is not enough, and a self-signed or expired certificate voids the whole policy. You can host this on a small static site, a CDN, an object store with a custom domain, or a dedicated MTA-STS provider. What matters is a trusted certificate and a stable path.

You will need a DNS record for the mta-sts host too (an A/AAAA or CNAME to wherever you serve the file). That is separate from the _mta-sts TXT record and is easy to forget.

Step 3: Write the policy file directives

The file is a short list of key-value lines with LF or CRLF endings:

version: STSv1
mode: testing
mx: mail.example.com
mx: *.mail.example.com
max_age: 604800

Here is what each directive controls:

  • version is always STSv1.
  • mode is testing, enforce, or none. In testing, senders honor the policy for reporting but still deliver if TLS fails, which is how you validate safely. In enforce, senders refuse delivery when the policy is not met. none withdraws the policy.
  • mx lists every MX hostname allowed to receive your mail. List one per line. Wildcards like *.mail.example.com match a single label, so use them when your provider uses per-region MX names. Every hostname in your actual MX records must be covered here or enforce mode will bounce legitimate mail.
  • max_age is how long, in seconds, senders may cache the policy. Common values run from 86400 (one day) up to 604800 (one week). Start low while testing so mistakes clear quickly, then raise it once you are in enforce.

Confirm your mx list against your live MX records. If your mail is on Google Workspace, Microsoft 365, or another provider, copy the exact MX hostnames from your zone rather than guessing, because a missing entry becomes a delivery failure the moment you enforce.

Validate every piece before you enforce

Do not jump straight to mode: enforce. Run the deployment in testing first and confirm all three parts resolve.

Check the TXT record

Query the record directly and confirm the id matches what you intend:

dig +short TXT _mta-sts.example.com

You should see your v=STSv1; id=... string and nothing malformed.

Check the HTTPS policy file

Fetch the file and inspect both the certificate and the body:

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

Verify that the TLS handshake succeeds with a valid certificate for mta-sts.example.com, that the response is 200 OK with Content-Type: text/plain, and that the body matches your intended mode, mx, and max_age. A certificate warning here is the single most common reason a policy silently fails.

Confirm mx coverage

Cross-check the mx lines against your real MX:

dig +short MX example.com

Every hostname returned must be listed in the policy file, either explicitly or via a matching wildcard. Run a full check with SPFWise's scanner or any MTA-STS validator to catch mismatches you might miss by eye. Only after all three checks pass, and after a few days in testing with no surprises, change mode: testing to mode: enforce and bump the id in your TXT record so senders pick up the change.

MTA-STS, TLS-RPT, and DANE

Two related records are worth knowing about. TLS-RPT (RFC 8460) is a companion TXT record that asks reporting senders to send you daily summaries of TLS delivery successes and failures, which is how you learn that a policy is working before you enforce it. A minimal record looks like _smtp._tls.example.com. IN TXT "v=TLSRPTv1; rua=mailto:tls-reports@example.com".

DANE is the other approach to enforcing SMTP TLS, using DNSSEC-signed TLSA records instead of a hosted HTTPS policy. The two solve the same problem with different trust anchors, and many domains run both. For a direct comparison of when to choose each, see MTA-STS vs DANE. If your goal is broader inbox placement, pair this work with a solid DMARC policy and the Google and Yahoo sender requirements, since transport security and authentication together are what modern mailbox providers expect.

Frequently asked questions

Do I need MTA-STS if I already have SPF, DKIM, and DMARC?

Yes, they solve different problems. SPF, DKIM, and DMARC authenticate who sent a message and stop spoofing. MTA-STS protects the transport layer so inbound mail cannot be downgraded to plaintext or redirected during delivery. Run both.

What is the difference between testing and enforce mode?

In testing mode, senders evaluate your policy and report failures but still deliver mail even when TLS cannot be established, so a misconfiguration cannot cause an outage. In enforce mode, senders refuse delivery when the connection does not meet the policy. Always start in testing, validate, then move to enforce.

Why does my policy file need its own subdomain and certificate?

The specification fixes the location at https://mta-sts.<domain>/.well-known/mta-sts.txt precisely so senders can find it without guessing, and it requires a valid certificate for that mta-sts host so an attacker cannot forge the policy. A missing DNS record for the subdomain or an invalid certificate makes senders ignore the policy entirely.

How do I update or remove an MTA-STS policy safely?

To change the policy, edit the file and then set a new id in the _mta-sts TXT record so caching senders refetch it. To retire MTA-STS, set mode: none in the file and bump the id, then leave both records in place until every sender's cache (governed by your max_age) has expired before removing anything.

Check your own domain

Run a free scan and get your grade with the exact records to fix.

Scan a domain

Related guides

How to Set Up MTA-STS: Step-by-Step Guide