SSL_accept error in your mail logs means the TLS handshake on an inbound connection failed mid-negotiation. The remote SMTP client connected, STARTTLS was offered, and the OpenSSL handshake aborted before a session was established. Postfix either rejects the message (mandatory TLS) or silently falls back to plaintext (opportunistic TLS).

Default Postfix does not log failed opportunistic TLS handshakes. Both smtpd_tls_loglevel and smtp_tls_loglevel default to 0. You see successful TLS connections but not the ones that failed and fell back to cleartext. You may be delivering mail in plaintext to destinations you believe require encryption, with the only visible symptom being a deferred queue growing with delivery delays.

Inbound failures produce SSL_accept error on your smtpd side. Outbound failures produce SSL_connect error or deferrals with TLS-related reason strings. These present differently and require different diagnostic paths.

What it means

A TLS handshake failure occurs when Postfix and the remote peer cannot agree on a compatible protocol version, cipher suite, or certificate chain. The failure is at the OpenSSL layer. Postfix delegates all TLS negotiation to OpenSSL and reports the outcome.

Three categories dominate production:

  1. Inbound handshake failures (SSL_accept error): A remote client connected to your smtpd, attempted STARTTLS, and the handshake failed. If your policy is may (opportunistic), the client may retry without TLS and deliver in plaintext. If your policy is encrypt or verify, the message is rejected.

  2. Outbound handshake failures (SSL_connect error or silent deferral): Your smtp client attempted STARTTLS to a remote MX, the handshake failed, and Postfix either fell back to plaintext (opportunistic) or deferred the message (mandatory). Deferred failures show up in the deferred queue with TLS-related reason strings, not as explicit TLS errors.

  3. Unexpected Anonymous TLS connection: Postfix logs this when it completes a TLS handshake without verifying the peer certificate. For opportunistic TLS to localhost (e.g., submission relayed to smtpd on 127.0.0.1), this is normal. For outbound delivery to a partner MX where you expected certificate verification, it indicates a policy mismatch or a missing smtp_tls_security_level = verify.

flowchart TD
    A[TLS failure in logs] --> B{Inbound or outbound?}
    B -->|SSL_accept error| C[smtpd: reject or fall back]
    B -->|SSL_connect or deferred| D[smtp client: defer or fall back]
    C --> E{TLS policy?}
    D --> E
    E -->|Mandatory encrypt/verify| F[Rejected or deferred: visible]
    E -->|Opportunistic may| G[Silent plaintext fallback]
    G --> H[Invisible at loglevel 0]

Common causes

CauseWhat it looks likeFirst thing to check
Cipher suite mismatchno shared cipher or SSL_accept error from specific clients onlypostconf smtpd_tls_ciphers smtpd_tls_mandatory_ciphers
Protocol too restrictiveClients fail after you set >=TLSv1.3 on a public MXpostconf smtpd_tls_mandatory_protocols smtpd_tls_protocols
Certificate problemSSL_accept error with certificate verify failed or chain errorsCheck cert expiry, chain completeness, key/cert file paths
ECDSA cert without RSA fallbackno shared cipher from RSA-only clientsCheck if only smtpd_tls_eccert_file is set, no RSA cert
OpenSSL 3.x legacy sigalglegacy sigalg disallowed or unsupported on outbound to TLS 1.0 serversopenssl version and target server TLS version
DPI or TLS interceptionHandshake fails on one network path but succeeds from anotherCompare openssl s_client from MTA vs. different network
Clock skewCertificate validation fails intermittently, resolves on its ownchronyc tracking or ntpstat on the MTA
Deprecated TLS parameterspostconf warns about obsolete parameters after upgradepostconf -n output for smtp_use_tls, smtpd_use_tls, etc.

Quick checks

# Check current TLS log levels (default is 0: failed opportunistic TLS is invisible)
postconf -h smtpd_tls_loglevel smtp_tls_loglevel

# Check inbound TLS protocol and cipher configuration
postconf -h smtpd_tls_protocols smtpd_tls_mandatory_protocols smtpd_tls_ciphers smtpd_tls_mandatory_ciphers

# Check outbound TLS protocol and cipher configuration
postconf -h smtp_tls_protocols smtp_tls_mandatory_protocols smtp_tls_ciphers smtp_tls_mandatory_ciphers

# Check TLS security levels
postconf -h smtpd_tls_security_level smtp_tls_security_level

# Check for deprecated TLS parameters (Postfix 3.9+ warns on these)
postconf -n 2>&1 | grep -E 'smtp_use_tls|smtpd_use_tls|smtp_enforce_tls|smtpd_enforce_tls|smtp_tls_per_site'

# Count recent TLS handshake errors
# Path is /var/log/mail.log on Debian/Ubuntu, /var/log/maillog on RHEL/CentOS
grep -E 'SSL_accept error|SSL_connect error|TLS handshake failed' /var/log/mail.log | tail -20

# On systemd-only hosts without persistent syslog files:
# journalctl -u postfix -S '1 hour ago' | grep -E 'SSL_accept error|SSL_connect error'

# Check specifically for cipher mismatch errors
grep 'no shared cipher' /var/log/mail.log | tail -20

# Check for Anonymous TLS connections (may indicate unexpected opportunistic fallback)
grep 'Anonymous TLS connection' /var/log/mail.log | tail -20

# Test your own server's TLS handshake from localhost
openssl s_client -connect localhost:25 -starttls smtp </dev/null 2>&1 | head -20

# Test outbound TLS to a specific destination MX
openssl s_client -connect mx.example.com:25 -starttls smtp </dev/null 2>&1 | head -20

# Check OpenSSL version (relevant for legacy sigalg compatibility)
openssl version

How to diagnose

  1. Raise TLS logging temporarily. Set smtpd_tls_loglevel = 1 and smtp_tls_loglevel = 1, then reload. This reveals opportunistic TLS fallbacks and negotiation details without dumping hex. Level 2 logs each negotiation phase; level 3 dumps the full handshake. Do not leave level 2 or 3 in production. It is noisy and may expose sensitive negotiation data in logs.

  2. Determine inbound versus outbound. Search for SSL_accept error (inbound, your smtpd) versus SSL_connect error or TLS-related deferral strings (outbound, your smtp client).

  3. For inbound SSL_accept error, identify the failing clients. Extract client IPs and correlate with the error detail string. If failures come from a narrow set of IPs or specific providers (Gmail, Outlook, Earthlink), the problem is likely cipher or protocol compatibility. If failures are widespread, suspect your certificate chain or a globally restrictive policy.

  4. For outbound failures, check deferred queue reason strings. TLS-related outbound failures present as status=deferred with reason text mentioning TLS, SSL, or certificate verification, not as explicit SSL_connect error. Correlate deferred queue growth with TLS log entries.

  5. Reproduce the handshake with openssl s_client. Use -starttls smtp for SMTP. Add -tls1_2 or -tls1_3 to test specific protocol versions. Add -cipher to test TLS 1.2 and earlier cipher constraints, and -ciphersuites for TLS 1.3 suites. The output shows the negotiated protocol, cipher, and certificate chain, which narrows the problem immediately.

  6. Check for deprecated parameters. If the problem appeared after a Postfix upgrade, run postconf -n and look for warnings. Postfix 3.9 made smtp_use_tls, smtpd_use_tls, smtp_enforce_tls, smtpd_enforce_tls, and smtp_tls_per_site officially obsolete. They still function but log warnings and may behave subtly differently. Replace with smtp_tls_security_level and smtpd_tls_security_level.

  7. Check OpenSSL version compatibility. If Postfix is linked against OpenSSL 3.0.x and outbound deliveries to older servers fail with legacy sigalg disallowed or unsupported, the remote server is negotiating TLS 1.0 with a legacy MD5+SHA1 composite signature that OpenSSL 3.x rejects by default.

Metrics and signals to monitor

SignalWhy it mattersWarning sign
TLS handshake error countDirect measure of TLS interoperability failuresAny sustained rate for mandatory TLS; above 2-5% for opportunistic
Opportunistic TLS success ratioTracks silent plaintext fallbacks invisible at loglevel 0Ratio dropping below baseline after config change or upgrade
Deferred entries with TLS reason stringsOutbound TLS failures defer rather than errorSpike in deferrals containing TLS, SSL, or certificate keywords
Certificate expiration dateExpired certs cause immediate handshake failures for verified connectionsWithin 30 days of expiry
Postfix and OpenSSL versionsVersion changes introduce compatibility breaksRecent upgrade followed by new TLS errors
Anonymous TLS connection frequencyMay indicate unexpected opportunistic fallback on outboundSpike to destinations where mandatory TLS was expected
postconf warningsDeprecated parameters may behave differently after upgradeAny warning mentioning obsolete TLS parameters

Fixes

Warning: postconf -e writes directly to main.cf and postfix reload applies changes immediately. Test on a staging server first if possible, and always verify with postconf -n after reloading.

Cipher suite mismatch

The most common inbound failure is a cipher mismatch between your server and connecting clients. Postfix defaults to medium grade ciphers (128-bit or better) for both smtpd_tls_ciphers and smtpd_tls_mandatory_ciphers.

If you tightened cipher policy and old clients now fail:

# Check current cipher policy
postconf -h smtpd_tls_ciphers smtpd_tls_mandatory_ciphers

# If you over-tightened, restore the default medium grade
postconf -e 'smtpd_tls_ciphers = medium'
postfix reload

Do not apply the Mozilla “Modern” TLS profile to a public MX host. Many legitimate mail servers still negotiate TLS 1.2 only. A >=TLSv1.3 mandatory protocol or a cipher list that excludes all TLS 1.2-compatible suites will reject legitimate mail from real providers.

ECDSA certificate without RSA fallback

If your server presents only an ECDSA certificate (smtpd_tls_eccert_file / smtpd_tls_eckey_file) and a connecting client supports only RSA ciphers, the handshake fails with no shared cipher. Postfix supports configuring both RSA and ECDSA certificates simultaneously. The negotiated cipher determines which certificate is presented.

# Check which certificate types are configured
postconf -h smtpd_tls_cert_file smtpd_tls_eccert_file

# If only ECDSA is set, add an RSA certificate as well
postconf -e 'smtpd_tls_cert_file = /etc/letsencrypt/live/example.com/fullchain.pem'
postconf -e 'smtpd_tls_key_file = /etc/letsencrypt/live/example.com/privkey.pem'
postfix reload

Protocol version too restrictive

Postfix 3.6+ uses the >=TLSv1.2 inclusion syntax for smtpd_tls_protocols and smtpd_tls_mandatory_protocols. Before 3.6, only the exclusion syntax (!SSLv2, !SSLv3, !TLSv1, !TLSv1.1) was available. SSLv2 and SSLv3 are disabled by default in all modern Postfix releases.

# Check current protocol policy
postconf -h smtpd_tls_protocols smtpd_tls_mandatory_protocols

# For a public MX, do not raise mandatory protocols above TLS 1.2
# >=TLSv1.3 will reject all TLS 1.2-only clients

TLS 1.3 and certificate-less operation

TLS 1.3 requires server certificates. If you operate a server without certificates, relying on anonymous ciphers (aNULL) only, TLS 1.3 negotiation will fail. To run certificate-less, you must explicitly disable TLS 1.3:

postconf -e 'smtpd_tls_protocols = <=TLSv1.2'
postfix reload

This is an unusual configuration. Most production servers should have certificates configured. Anonymous ciphers (aNULL) are enabled by default for opportunistic TLS on both server and client. They are automatically disabled when client certificates are requested (server side) or when server certificates are verified (client side).

OpenSSL 3.x legacy sigalg failure

When Postfix linked against OpenSSL 3.0.x connects to a server that negotiates TLS 1.0, the ServerKeyExchange may use a legacy MD5+SHA1 composite signature that OpenSSL 3.0 rejects. The resulting error is SSL routines::legacy sigalg disallowed or unsupported.

Options:

  • Upgrade the remote server to TLS 1.2 or higher. Preferred, but you may not control the remote system.
  • Lower the client security level by appending @SECLEVEL=0 to the cipher string. This weakens security for affected connections. Apply it only to specific destinations via smtp_tls_policy_maps, not globally.

Clock skew

Certificate validation depends on correct system time. If the MTA clock is skewed, certificates may appear expired or not-yet-valid, causing handshake failures that resolve when time corrects.

# Check system clock synchronization
chronyc tracking 2>/dev/null || ntpstat 2>/dev/null || timedatectl status

Deprecated TLS parameters

Postfix 3.9 made several TLS parameters obsolete. They still function but log warnings and should be migrated:

Obsolete parameterReplacement
smtp_use_tls = yessmtp_tls_security_level = may
smtpd_use_tls = yessmtpd_tls_security_level = may
smtp_enforce_tls = yessmtp_tls_security_level = encrypt
smtpd_enforce_tls = yessmtpd_tls_security_level = encrypt
smtp_tls_per_sitesmtp_tls_policy_maps

After migrating, run postfix reload and verify with postconf -n that no warnings remain.

TLS 1.3 cipher names have no effect in cipher strings

TLS 1.3 bulk encryption ciphers (such as TLS_AES_128_GCM_SHA256) are not part of the OpenSSL cipherlist mechanism. Listing them in smtp_tls_ciphers or smtpd_tls_ciphers has no effect on TLS 1.3 negotiation. If you believe you are constraining TLS 1.3 ciphers this way, you are not. TLS 1.3 cipher selection is controlled separately.

Prevention

  • Keep TLS log levels at 1 for at least the SMTP client side. Default level 0 hides failed opportunistic TLS entirely. You cannot detect silent plaintext fallbacks without at least level 1 logging. The log volume overhead is minimal.

  • Monitor TLS failure rates alongside deferred queue growth. Outbound TLS failures defer, they do not bounce. A growing deferred queue with TLS-related reason strings is the earliest visible signal of an outbound TLS problem.

  • Test after every Postfix or OpenSSL upgrade. Version changes introduce new protocol defaults, deprecate old parameters, and change cipher behavior. Run openssl s_client -starttls smtp against your own server and against at least two major destination MX hosts after each upgrade.

  • Track certificate expiration for both inbound and outbound TLS. Monitor the smtpd certificate and any client certificates used for mutual TLS to partner destinations. Outbound TLS failures from expired client certificates cause silent deferrals, not obvious errors.

  • Avoid the Mozilla “Modern” profile on public MX hosts. Public mail servers need broad TLS 1.2 compatibility. The Modern profile is designed for HTTPS frontends with controlled client populations, not for SMTP where peer diversity is high and you cannot dictate client capabilities.

  • Run postconf -n after upgrades to catch deprecated parameters. Postfix logs warnings for obsolete parameters but does not remove them. Catch them before they cause subtle behavioral drift.

How Netdata helps

  • Correlate TLS error rates with deferred queue growth. A spike in SSL_accept error or SSL_connect error log entries that coincides with deferred queue expansion confirms a TLS-related delivery problem, distinguishing it from a DNS or network issue. Per-second granularity makes the correlation precise.

  • Detect silent plaintext fallbacks. By tracking the ratio of Anonymous TLS connection log entries to total outbound deliveries over time, a drop in that ratio after a configuration change or upgrade signals that opportunistic TLS is failing and falling back to plaintext rather than producing visible errors.

  • Track certificate expiration proactively. Certificate expiry is a predictable, deterministic failure. Alerting on days-to-expiry for the smtpd certificate and any mutual-TLS client certificates prevents the most common TLS outage.

  • Separate TLS failures from DNS and network failures. All three produce deferred mail and all three look similar in aggregate. Correlating TLS error log patterns with DNS resolver latency and SMTP connection timeout metrics isolates a cipher mismatch from a resolver outage or a network partition.

  • Monitor Postfix process health during TLS incidents. TLS negotiation is CPU-intensive. Elevated CPU on smtpd or smtp processes combined with rising TLS error rates may indicate resource contention or a computational workload spike, not just a cipher incompatibility.