New articles: - Postfix SendGrid TLS handshake failure (port 465 vs 587) - Plex transcoding troubleshooting - Ansible Ubuntu reboot detection kernel mismatch - WSL2 PyTorch checkpoint Windows filesystem deadlock Updated: - AWS S3 cost management (expanded) - Network overview (IP updates) - HEVC VAAPI batch encode (progress + fixes) - SUMMARY.md (new entries)
85 lines
2.8 KiB
Markdown
85 lines
2.8 KiB
Markdown
# 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.
|