What a TLSA record pins, and why a new key breaks it
mail.example.com, the record is at _25._tcp.mail.example.com. Every MX host needs its own record.
A TLSA record has three numbers followed by a hash. The most common combination for mail is 3 1 1:
3(DANE-EE) means "match the server's own certificate," with no CA chain check.1(selector) means "look at the public key (SubjectPublicKeyInfo), not the whole certificate."1(matching type) means "the data is a SHA-256 hash."
3 1 1 record pins the public key, not the certificate. You can renew a certificate as many times as you like and the record keeps matching, as long as the key pair stays the same. The moment the renewal tool creates a fresh key, the hash changes and the record is wrong.
Senders that validate DANE, such as Postfix configured with smtp_tls_security_level = dane, treat a mismatch as a failed secure connection. They do not fall back to plaintext, because that would defeat the point of DANE. The mail is deferred and retried, and if the mismatch lasts long enough it eventually bounces, depending on the sender's queue settings. Senders that do not validate DANE never look at the record and deliver normally. That split is why this problem often reaches support as "some people can email us, some can't," which looks like a reputation or blocklist issue at first glance.
TLSA records are only used when the zone is DNSSEC-signed and validates. If DNSSEC itself is broken, you have a different problem. For that side of it, see Thinking DNSSEC Re-Signs Itself After Moving DNS to BIND, Until RRSIGs Expire.
The timing matters more now than it used to. According to CA/Browser Forum rules, the maximum certificate lifetime is 200 days from March 15, 2026, dropping to 100 days from March 15, 2027, and to 47 days by 2029. If each renewal rotates the key, every renewal is a chance to break DANE. Doing renewals by hand at that pace is not realistic either, which is covered in Why Manual SSL Renewal Tracking Fails as Certificate Lifetimes Shrink to 47 Days.
Step 1: Read the published TLSA record and confirm it validates
ad (authenticated data) flag in the response header. Without it, DANE-aware senders will ignore the record anyway.
BASH
# Find the MX hosts for the domain
dig +short MX example.com
# Read the TLSA record for one MX host (repeat for each MX)
dig +short TLSA _25._tcp.mail.example.com
# Check that the answer is DNSSEC-validated: look for 'ad' in the flags line
dig +dnssec TLSA _25._tcp.mail.example.com | grep -E 'flags:|TLSA'+short answer gives you the usage, selector, matching type, and the hash. Some dig versions split long hex data with spaces, so remove spaces before comparing, and compare case-insensitively since dig typically prints uppercase hex and openssl prints lowercase.
If the ad flag is missing, check whether the resolver you queried actually validates DNSSEC before concluding the zone is broken. Querying a known validating resolver directly with dig @resolver-ip helps separate the two.
Step 2: Hash the key the server presents over STARTTLS
3 1 1 record.
Run this from a host that can reach port 25 outbound. Many residential networks and some cloud providers block outbound port 25, which makes the connection hang rather than fail cleanly.
BASH
# Hash the live public key (SPKI, SHA-256) as a 3 1 1 record would
openssl s_client -connect mail.example.com:25 -starttls smtp \
-servername mail.example.com </dev/null 2>/dev/null \
| openssl x509 -noout -pubkey \
| openssl pkey -pubin -outform DER \
| openssl dgst -sha256
# Sample output format (label text varies by OpenSSL version):
# SHA2-256(stdin)= 3f9a...e1c4= is what should appear in your TLSA record. If it matches, DANE senders are happy with the current key. If it doesn't match any published 3 1 1 record, they are deferring right now.
OpenSSL 1.1.0 and later can also do the comparison for you. Adding -dane_tlsa_domain mail.example.com and -dane_tlsa_rrdata '3 1 1 <hash>' to the s_client command makes it report whether the TLSA data matched the presented certificate in its verification output. Check openssl s_client -help on your build to confirm the options are available. If you run Postfix, its posttls-finger tool can test a destination with DANE as well, which is closer to how a real sender behaves.
One more thing worth checking when there are several MX hosts: they do not always share the same certificate or key. A backup MX that was renewed separately can quietly drift out of sync with its own TLSA record.
Step 3: Check the next key before it goes live
reuse_key = True. Certbot's long-standing default has been to generate a new key on renewal unless told otherwise, so confirm the behavior for your installed version. acme.sh has its own key handling and options, so check its documentation for the version you run.
BASH
# Is key reuse enabled for this certificate? (Certbot)
grep -i 'reuse_key' /etc/letsencrypt/renewal/mail.example.com.conf
# Hash the private key on disk the same way as the live check
sudo openssl pkey -in /etc/letsencrypt/live/mail.example.com/privkey.pem \
-pubout -outform DER | openssl dgst -sha256Keeping the key stable or rolling TLSA safely
3 1 1 record stays valid across renewals. The trade-off is that you are no longer rotating the key automatically, so you need to plan a deliberate rotation from time to time, especially if the key could have been exposed.
The other way is to roll the key with a two-record overlap. DANE allows more than one TLSA record at the same name, and a sender accepts the connection if any one of them matches. The sequence looks like this:
- Generate the next key in advance, without deploying it.
- Publish a second
3 1 1record with the next key's hash, alongside the current one. - Wait at least the TLSA record's TTL, plus some margin, so resolvers that cached the old answer have picked up both records.
- Deploy the certificate that uses the new key and reload the mail server. Rerun the Step 2 check to confirm the live hash matches the new record.
- After another TTL has passed, remove the old record.
2 1 1 record instead, which pins the issuing CA's key rather than their own. That avoids rolling TLSA on every key change, but it ties you to that CA's intermediate key. If the CA changes intermediates, the record breaks for a reason outside your control. It is a reasonable option only if you track the CA's intermediate changes closely.
Whichever approach you choose, treat the Step 2 hash check as part of every renewal, not something you run after senders start complaining. Put it in the renewal hook or in monitoring, compare it against every TLSA record for every MX host, and alert on a mismatch. With certificate lifetimes getting shorter, the renewal itself is routine. What keeps mail flowing is making sure the key DNS promises and the key the server presents are still the same one.