When mail to a destination configured for mandatory TLS is delivered in plaintext, that is a security incident, not a delivery problem. Postfix TLS security levels exist to prevent this: at encrypt and above, the message should be deferred if TLS is unavailable, not silently downgraded. If plaintext delivery is happening where policy forbids it, the policy enforcement chain is broken.
The default logging makes this symptom nearly invisible. With smtp_tls_loglevel at its default of 0, no TLS negotiation details are logged for outbound connections. Failed handshakes and silent fallbacks to plaintext produce no log output at all. By the time someone notices, the policy violation may have been ongoing for hours or days.
What this means
Postfix applies TLS policy through a hierarchy of security levels. The distinction that matters for this symptom:
may(opportunistic TLS): Postfix attempts STARTTLS. If the remote server does not offer it, or if the handshake fails, Postfix retries the connection with TLS disabled. This is a silent fallback to plaintext.encrypt(mandatory TLS): Postfix requires a successful TLS handshake. If the remote does not offer STARTTLS, or the handshake fails, the message is deferred. There is no fallback to plaintext. This is enforced viasmtp_tls_security_level = encryptor a per-domainsmtp_tls_policy_mapsentry.verifyandsecure: Mandatory TLS plus hostname or trust chain verification. A peer that fails verification causes a deferral, not a fallback.daneanddane-only: TLS policy derived from DNSSEC-validated TLSA records.danefalls back to opportunistic (may) if no TLSA records exist.dane-onlyis mandatory: no usable TLSA records means deferral.
A Postfix TLS downgrade means one of two things:
A destination with a mandatory TLS policy (
encrypt,verify,secure,dane-only) is receiving mail in plaintext. This should not happen under correct configuration. If it is, the policy is not being applied.A destination where you intended opportunistic TLS to succeed is silently falling back to plaintext. This is expected behavior at the
maylevel, but if TLS was working before and stopped, it signals certificate problems, cipher mismatch, or network interception.
The first case is a page-worthy security incident. The second is a ticket for investigation.
flowchart TD
A[Outbound message to destination] --> B{smtp_tls_policy_maps entry?}
B -->|Yes| C{Policy level in map?}
B -->|No| D{Global smtp_tls_security_level?}
D -->|empty or none| E[Plaintext - no TLS attempted]
D -->|may| F[Attempt STARTTLS]
D -->|encrypt| G[Require STARTTLS]
C -->|encrypt| G
C -->|may| F
C -->|dane-only| H[Require DNSSEC TLSA]
F --> I{Handshake succeeds?}
I -->|Yes| J[Deliver with TLS]
I -->|No| K[Retry without TLS: silent plaintext]
G --> L{Handshake succeeds?}
L -->|Yes| J
L -->|No| M[Defer message]
H --> N{Valid TLSA found?}
N -->|Yes| J
N -->|No| MCommon causes
| Cause | What it looks like | First thing to check |
|---|---|---|
| Policy map not applied | smtp_tls_policy_maps is empty or points to a stale file; mail to the “encrypt” destination goes out plaintext | postconf -h smtp_tls_policy_maps and postmap -q example.com <map> |
| Deprecated parameters conflicting | smtp_use_tls or smtp_enforce_tls set alongside smtp_tls_security_level; behavior does not match expectations | postconf -n | grep -E 'smtp_use_tls|smtp_enforce_tls|smtp_tls_per_site' |
| Broken TLSA or DANE records | dane-only policy defers all mail to the destination; DNSSEC validation failure or stale TLSA record | dig +dnssec TLSA _25._tcp.mx.example.com and mail.log for “TLSA” or “DANE” |
| Active STARTTLS stripping | Opportunistic TLS to a previously TLS-capable destination suddenly falls back to plaintext for all messages | openssl s_client -starttls smtp -connect mx.example.com:25 from the MTA host |
smtp_tls_mandatory_protocols too weak | “encrypt” policy succeeds but negotiates TLSv1.0 instead of TLSv1.2 or higher | Raise smtp_tls_loglevel to 1 and check the protocol version in logs |
Quick checks
# Check current TLS security level for outbound mail
postconf -h smtp_tls_security_level
# Check if a TLS policy map is configured
postconf -h smtp_tls_policy_maps
# Query the policy map for a specific domain (replace map type and path)
postmap -q example.com hash:/etc/postfix/tls_policy
# Check TLS log level (default 0 means no TLS negotiation logging)
postconf -h smtp_tls_loglevel
# Look for deprecated TLS parameters still in active config
postconf -n | grep -E 'smtp_use_tls|smtp_enforce_tls|smtp_tls_per_site|smtp_tls_enforce_peername'
# Check mandatory protocols
postconf -h smtp_tls_mandatory_protocols
# Check mandatory ciphers
postconf -h smtp_tls_mandatory_ciphers
# Scan recent logs for TLS policy violations and verification failures
# Debian/Ubuntu: /var/log/mail.log RHEL/CentOS: /var/log/maillog
grep -E 'TLS policy|SSL_connect error|verification failed|untrusted' /var/log/mail.log | tail -20
# Check for opportunistic TLS connections to unverified peers
grep 'Anonymous TLS connection established' /var/log/mail.log | tail -20
# Test STARTTLS availability to a specific destination from the MTA host
openssl s_client -starttls smtp -connect mx.example.com:25 </dev/null 2>/dev/null | head -20
How to diagnose it
Confirm the outbound TLS policy is active. Run
postconf -h smtp_tls_security_levelandpostconf -h smtp_tls_policy_maps. If the security level is empty ornone, no outbound TLS policy is active at all. If a policy map is configured, verify the source file exists and has a current compiled counterpart (.dbor.lmdb).Query the policy map for the affected domain. Use
postmap -q <domain> <maptype>:<path>. If the query returns nothing, the domain has no entry and inherits the globalsmtp_tls_security_level. If the global level ismayor empty, opportunistic TLS with silent plaintext fallback is the active policy for that destination.Check for deprecated parameters. The old-style TLS parameters (
smtp_use_tls,smtp_enforce_tls,smtp_tls_per_site,smtp_tls_enforce_peername) were replaced bysmtp_tls_security_levelin Postfix 2.3. If these coexist withsmtp_tls_security_level, behavior may not match expectations.smtp_tls_per_siteis ignored whensmtp_tls_policy_mapsis non-empty, but Postfix logs a warning if both are configured.Raise TLS logging temporarily. Set
smtp_tls_loglevel = 1and runpostfix reload. This logs TLS negotiation details for outbound connections without excessive verbosity. Level 2 dumps the full TLS handshake and is useful for cipher debugging but too noisy for sustained production use. Set it back to0after diagnosis, or leave at1permanently for ongoing visibility (recommended in Prevention below).Watch the logs for the affected destination. After raising the log level, send or wait for a test message. Look for these patterns:
Anonymous TLS connection established: opportunistic TLS to an unverified peer. Expected atmay. If you see this for anencryptdestination, the policy is not being enforced.TLS policy: ... digest does not match: DANE or fingerprint verification failure.SSL_connect error: handshake failure. Atencrypt, this should be followed by a deferral, not a plaintext retry.Untrusted TLS connection established: TLS succeeded but the peer certificate was not verified. Expected atencrypt. Wrong atverifyorsecure.
Test STARTTLS from the MTA host. Run
openssl s_client -starttls smtp -connect mx.example.com:25from the Postfix server. If STARTTLS is not offered by the remote, anencryptpolicy should defer. If STARTTLS is offered but the handshake fails, check certificate chain, protocol version, and cipher compatibility.Check DANE or TLSA records if applicable. For
daneordane-onlypolicies, verify TLSA records exist and are DNSSEC-signed:dig +dnssec TLSA _25._tcp.mx.example.com. A stale or malformed TLSA record causesdane-onlyto defer all mail, and causesdaneto fall back to opportunisticmay.
Metrics and signals to monitor
| Signal | Why it matters | Warning sign |
|---|---|---|
| TLS negotiation failure rate | Sustained failures indicate certificate, cipher, or network interception problems | Mandatory TLS: any failure. Opportunistic: above 5% failure rate |
| Deferred queue growth from TLS failures | TLS handshake failures at encrypt cause deferrals, not silent fallback | Deferred messages with “TLS” or “SSL” in the reason string |
Anonymous TLS connection log frequency | Indicates opportunistic TLS to unverified peers; a spike may mean TLS was previously succeeding but stopped | Sudden increase for destinations that previously showed verified TLS |
| Certificate expiration (outbound) | Expired client or server certificates break mandatory TLS | Expiration within 30 days for any certificate in the trust chain |
smtp_tls_mandatory_protocols value | Default may allow TLSv1.0 and TLSv1.1 | Value does not exclude SSLv2, SSLv3, TLSv1, and TLSv1.1 |
| DANE and TLSA record validity | Broken TLSA records cause dane-only deferrals or fallback to may under dane | DNSSEC validation failures or missing TLSA records for DANE-policy destinations |
Fixes
Policy map missing or stale
If smtp_tls_policy_maps is empty or the map file does not contain the affected domain, create or update the entry:
# /etc/postfix/tls_policy
example.com encrypt
Rebuild the map and reload:
# Rebuild the policy map and reload Postfix
postmap /etc/postfix/tls_policy
postfix reload
Verify with postmap -q example.com hash:/etc/postfix/tls_policy.
Deprecated parameters causing confusion
Remove smtp_use_tls, smtp_enforce_tls, smtp_tls_per_site, and smtp_tls_enforce_peername from main.cf. Replace them with smtp_tls_security_level and smtp_tls_policy_maps. After changes, run postfix reload and verify with postconf -n.
Weak mandatory protocols
The upstream default for smtp_tls_mandatory_protocols may allow TLSv1.0 and TLSv1.1. Explicitly restrict mandatory protocols:
# WARNING: these commands modify main.cf directly.
# Back up your configuration first if you are not using version control.
postconf -e 'smtp_tls_mandatory_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1'
postconf -e 'smtp_tls_mandatory_ciphers = high'
postfix reload
Broken TLSA or DANE records
If using dane-only and TLSA records are broken or missing, mail defers until the records are fixed. This is correct behavior. Do not lower the policy to work around it. Coordinate with the destination’s DNS administrator to publish valid, DNSSEC-signed TLSA records.
If using dane (opportunistic DANE), missing TLSA records cause fallback to may, which is expected. But if TLSA records previously existed and disappeared, investigate DNSSEC validation failures or zone misconfiguration on the destination side.
Active STARTTLS stripping
If STARTTLS is stripped for a specific destination but works from other network paths, this may indicate active interception. Verify by testing from multiple vantage points. The protections against STARTTLS stripping are DANE (dane-only with valid TLSA records) or MTA-STS, both of which make the stripping detectable rather than silent.
Postfix has native DANE support since version 2.11. MTA-STS requires an external resolver plugin such as postfix-tlspol or postfix-mta-sts-resolver.
Prevention
Keep
smtp_tls_loglevel = 1permanently. Level 0 hides all TLS negotiation for outbound mail. The extra log volume is minimal, and the visibility is critical for detecting silent fallbacks.Audit
smtp_tls_policy_mapsregularly. Runpostmap -q <domain> <map>for each mandatory-TLS destination to confirm entries resolve correctly. Stale map files after infrastructure changes are a common cause of unintended plaintext delivery.Periodically check for deprecated parameters. Run
postconf -n | grep -E 'smtp_use_tls|smtp_enforce_tls|smtp_tls_per_site|smtp_tls_enforce_peername'after any Postfix upgrade or configuration change.Monitor certificate expiration for outbound TLS. Track the SMTPD server certificate, any client certificates, and the CA chains used for mutual TLS to relay hosts. Certificate expiry is the most common cause of mandatory-TLS breakage.
Prefer DANE (
dane-only) for mandatory enforcement. DNSSEC-anchored TLSA records resist STARTTLS stripping without requiring a separate policy map file that can go stale.
How Netdata helps
Per-second log parsing of Postfix mail logs surfaces TLS negotiation failures,
Anonymous TLS connectionevents, andSSL_connect errorpatterns as they happen, rather than relying on periodic manual log scans.Deferred queue growth rate correlated with TLS failure logs distinguishes a mandatory-TLS deferral storm (policy working correctly, remote is broken) from a silent plaintext fallback (policy not being applied).
Anomaly detection on TLS success and failure ratios flags sudden shifts in TLS posture for specific destinations.
Certificate expiration monitoring for the SMTPD listener and any client certificates provides early warning before mandatory TLS breaks.
Related guides
- Postfix active queue saturation: hitting qmgr_message_active_limit
- Postfix deferred queue growing: why mail piles up and how to drain it
- Postfix connection timed out: delivery deferrals to unreachable destinations
- Postfix bounce rate spike: 5xx failures, bad address lists, and reputation risk
- Postfix check warnings: configuration drift and permission problems
- Postfix connection refused: blocked port 25 and rejected outbound delivery
- Postfix content_filter backpressure: incoming queue growth when Amavis or Rspamd slows
- Postfix daemon memory growth: leaking RSS and OOM risk
- Postfix destination concurrency limit: tuning per-destination delivery
- Postfix queue partition disk full: /var/spool/postfix out of space
- Postfix IP blocklisted: deliverability collapse and sender reputation
- Postfix backscatter storm: bounces to forged senders and blocklisting






