MTA-STS enforce mode and rollback

Safe deployment strategy for MTA-STS enforce mode. Emergency rollback procedure, the three-point sync rule, max_age cache traps, and Microsoft NDR error codes explained.

The three-point sync rule

What must stay in sync

MTA-STS requires three components to match at all times:

  1. Actual MX DNS records for your domain
  2. mx: entries in your mta-sts.txt policy file
  3. id value in the _mta-sts TXT DNS record

Changing any one of these without updating the others causes delivery failures. A sender fetches the policy, compares the MX hostnames in the policy against the MX records it resolved from DNS, and validates the TLS certificate of each mail server. If the MX hostnames in your policy file do not match the actual MX records, senders in enforce mode reject the connection.

This is the core operational burden of MTA-STS. Every DNS or mail server change requires a coordinated update across all three components.

Example of a correct configuration

DNS MX records:

example.com.  IN MX 10 mail1.example.com.
example.com.  IN MX 20 mail2.example.com.

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

version: STSv1
mode: enforce
mx: mail1.example.com
mx: mail2.example.com
max_age: 86400

DNS TXT record:

_mta-sts.example.com.  IN TXT "v=STSv1; id=20260329T1200"

All three agree on the same MX hostnames. The id value reflects the current version of the policy. This is the state you need to maintain.

Policy ID not updated after change

Symptoms

You update the policy file (for example, switching from mode: testing to mode: enforce) but forget to bump the id in the DNS TXT record. Senders that already cached the old policy do not re-fetch it. They continue using the old policy for up to max_age seconds.

Why this happens

The MTA-STS specification (RFC 8461) uses the id field as a change signal. Senders poll the DNS TXT record periodically and compare the id against the cached value. If the id has not changed, they skip fetching the policy file. The policy file itself is not polled directly.

How to fix it

Every time you modify the policy file, you must also update the id in the DNS TXT record. Use a timestamp or incrementing counter.

Before:

_mta-sts.example.com.  IN TXT "v=STSv1; id=20260101T0001"

After:

_mta-sts.example.com.  IN TXT "v=STSv1; id=20260329T1500"

Until you bump the id, senders will not see your updated policy. This applies to every change: mode switches, MX list updates, and max_age adjustments.

Premature enforce mode

Symptoms

Inbound email bounces immediately after switching from mode: testing to mode: enforce. Senders return non-delivery reports (NDRs) to their users. Your TLS-RPT reports (if configured) show validation failures.

Microsoft Exchange Online NDR codes

Microsoft 365 and Exchange Online are strict MTA-STS enforcers. When they cannot validate your policy, they return specific error codes:

  • 551 5.7.4 STARTTLS is required by recipient domain's MTA-STS policy
  • 551 5.4.8 MX hosts of '<Domain>' failed MTA-STS validation
  • 551 5.7.5 Remote certificate MUST have a subject alternative name matching the hostname
  • 551 5.7.5 Remote certificate failed MTA-STS validation

The first error means your mail server did not offer STARTTLS at all. The second means the MX hostnames in your policy did not match the actual MX records. The third and fourth mean the TLS certificate on your mail server does not cover the MX hostname. All of these pass silently in mode: testing but cause hard bounces in mode: enforce.

How to fix it

Switch back to mode: testing immediately. Bump the id in your DNS TXT record so senders fetch the updated policy. Then investigate each failure:

  1. Verify every MX host supports STARTTLS
  2. Confirm MX hostnames in the policy file match your actual MX DNS records exactly
  3. Check that TLS certificates on every MX host include the MX hostname as a Subject Alternative Name (SAN)
  4. Review TLS-RPT reports for at least 7 days before attempting enforce again

max_age too high on first deployment

Symptoms

You deployed MTA-STS with max_age: 31557600 (1 year) as many guides recommend. Something is wrong with your configuration. You fix the policy file, bump the id, and wait. Some senders recover quickly. Others keep bouncing mail for days or weeks.

Why this happens

Senders cache MTA-STS policies for up to max_age seconds. They only re-check the DNS TXT record periodically, not on every message. If a sender cached your broken policy with a 1-year max_age, it may continue using that cached policy for a long time, even after you fix everything. The sender's refresh interval is implementation-dependent.

How to fix it

You cannot force senders to flush their cache. The only option is to publish the corrected policy, bump the id, and wait for senders to refresh. With a 1-year max_age, this can take a long time depending on the sender's polling frequency.

Prevention

Start with max_age: 86400 (24 hours) during your initial deployment and testing period. This limits the blast radius of any misconfiguration to one day. Only increase max_age to longer values (604800 for 1 week, or 31557600 for 1 year) after you have confirmed everything works correctly in enforce mode for at least 2 weeks.

max_age below 86400

Symptoms

You set max_age: 3600 (1 hour) or another value below 86400 for a short testing cycle. Google does not appear to enforce your policy at all. TLS-RPT reports from Google show no MTA-STS results.

Why this happens

Google silently ignores MTA-STS policies with a max_age below 86400 seconds (1 day). This is not documented in the RFC. It is a Google-specific implementation choice. If you set a value below this threshold, Google treats your domain as having no MTA-STS policy.

How to fix it

Set max_age to at least 86400. Bump the id in your DNS TXT record after making the change. There is no benefit to setting it below 86400, because the largest email provider in the world will ignore it.

Emergency rollback procedure

When to use this

Use this procedure when MTA-STS enforce mode is causing inbound mail delivery failures and you need to stop the damage immediately.

Step-by-step rollback

  1. Change the policy mode to none. Update your mta-sts.txt file:
    version: STSv1
    mode: none
    mx: mail1.example.com
    mx: mail2.example.com
    max_age: 86400
  2. Bump the id in your DNS TXT record. This tells senders to re-fetch the policy:
    _mta-sts.example.com.  IN TXT "v=STSv1; id=20260329-rollback"
  3. Keep the policy file accessible. The policy file must remain served at https://mta-sts.example.com/.well-known/mta-sts.txt for at least as long as the previous max_age value. Senders need to fetch the mode: none policy to flush their cached enforce policy.
  4. Wait. Senders will gradually poll the DNS TXT record, see the new id, fetch the updated policy, and stop enforcing. This takes time depending on each sender's polling interval.
  5. Only then remove DNS records. After the previous max_age has fully elapsed, you can safely remove the _mta-sts TXT record and take down the policy file if you want to disable MTA-STS entirely.

What happens if you skip steps

If you delete the DNS TXT record and policy file immediately, senders with cached enforce policies from days or weeks ago have no way to fetch an updated policy. They continue enforcing the cached policy until it expires. This means mail delivery failures persist for the duration of the old max_age value, which could be up to a year.

Improper MTA-STS removal

Symptoms

You decide to disable MTA-STS entirely. You delete the _mta-sts TXT DNS record and remove the policy file. Some senders continue to bounce mail to your domain days or weeks later.

Why this happens

RFC 8461 section 5.1 specifies that senders must continue enforcing a cached policy until it expires. If a sender cached your enforce policy with a max_age of 31557600 (1 year), that sender will enforce MTA-STS validation for up to a year, even if the DNS record and policy file no longer exist.

When the sender checks DNS and finds no _mta-sts TXT record, it cannot determine whether the record was intentionally removed or is temporarily missing due to a DNS issue. Per the RFC, the safe default is to keep enforcing the cached policy.

How to fix it

Follow the emergency rollback procedure described above. Re-publish the DNS TXT record with a new id and a policy file with mode: none. Keep both accessible until the original max_age expires. Only then remove them.

If you no longer have the infrastructure to serve the policy file, you are stuck waiting for cached policies to expire. There is no other recovery mechanism.

Prevention

Deploy MTA-STS safely

Follow this sequence to avoid the problems described above:

  1. Publish MTA-STS with mode: testing and max_age: 86400
  2. Configure TLS-RPT so you receive failure reports from senders
  3. Monitor TLS-RPT data for at least 7 days, looking for certificate mismatches, missing STARTTLS, and MX validation failures
  4. Fix every reported issue before proceeding
  5. Switch to mode: enforce, bump the id, keep max_age: 86400
  6. Monitor for another 7 days in enforce mode with the short max_age
  7. Gradually increase max_age to your target value (604800 or 31557600), bumping the id each time

DMARCTrust Receiver Shield

DMARCTrust's Receiver Shield removes the manual burden described in this article. It analyzes your TLS-RPT failure data during testing mode and tells you when it is safe to switch to enforce. The hosted MTA-STS feature handles policy ID synchronization automatically, so you never forget to bump the id after a policy change.

For a deeper understanding of how MTA-STS works, see our MTA-STS fundamentals guide.

Was this page helpful? Send us feedback

Last updated: March 2026