# Postfix + SendGrid: TLS Handshake Failure (Port 465 vs 587) ## Symptom Outbound mail silently queues with no delivery. `postqueue -p` shows deferred messages: ``` (Cannot start TLS: handshake failure) ``` `/var/log/maillog` shows: ``` SSL_connect error to smtp.sendgrid.net[...]:465: -1 warning: TLS library problem: error:0A00010B:SSL routines::wrong version number ``` Or on port 587: ``` warning: TLS library problem: error:0A0000C1:SSL routines::no shared cipher ``` ## Root Cause Port **465** (SMTPS) uses **implicit TLS** — the connection starts encrypted immediately. Port **587** (submission) uses **STARTTLS** — the connection starts plaintext, then upgrades. Postfix has two settings that must match the port: | Port | `smtp_tls_wrappermode` | `smtp_tls_security_level` | |------|------------------------|---------------------------| | 465 | `yes` | `encrypt` | | 587 | `no` | `encrypt` (or `may`) | If `smtp_tls_wrappermode=yes` is set with port 587, Postfix sends a TLS ClientHello immediately but the server expects a plaintext SMTP greeting first — `wrong version number`. If `smtp_tls_wrappermode=no` is set with port 465, Postfix sends a plaintext EHLO but the server expects a TLS ClientHello — `no shared cipher` or connection reset. ## Fix Use port 587 + STARTTLS (recommended — more widely supported and debuggable): ```bash postconf -e 'relayhost = [smtp.sendgrid.net]:587' postconf -e 'smtp_tls_wrappermode = no' postconf -e 'smtp_tls_security_level = encrypt' systemctl restart postfix postqueue -f # flush stuck messages ``` ## Verify ```bash # Check config postconf relayhost smtp_tls_wrappermode smtp_tls_security_level # Test TLS connection manually openssl s_client -starttls smtp -connect smtp.sendgrid.net:587 -brief # Watch delivery tail -f /var/log/maillog | grep status= ``` Successful delivery looks like: ``` Untrusted TLS connection established to smtp.sendgrid.net[...]:587: TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 status=sent (250 Ok: queued as ...) ``` ## Why "Untrusted"? If `smtp_tls_CAfile` and `smtp_tls_CApath` are both empty, Postfix can't verify the server certificate and logs "Untrusted TLS connection." The connection is still encrypted — just not authenticated. To fix, point to the system CA bundle: ```bash postconf -e 'smtp_tls_CAfile = /etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem' # Fedora # or postconf -e 'smtp_tls_CAfile = /etc/ssl/certs/ca-certificates.crt' # Ubuntu/Debian ``` ## Notes - OpenSSL 3.x is stricter about protocol mismatches than OpenSSL 1.1 — a config that worked on older distros may break after an OS upgrade. - SendGrid supports both ports, but port 587 + STARTTLS is the documented recommendation. - This applies to any SMTP relay (Mailgun, AWS SES, etc.), not just SendGrid — the port/wrappermode pairing is universal.