Skip to content

STARTTLS (mail, FTP, XMPP, databases, RDP)

Mail servers usually start in plaintext and upgrade with STARTTLS. pqdoctor does that exchange before every probe, then runs the same TLS checks.

Terminal window
pqdoctor smtp.example.com:587 # STARTTLS by port
pqdoctor mail.example.com:143 # IMAP
pqdoctor mail.example.com:2525 --starttls smtp

By port: 25 and 587 are SMTP, 143 is IMAP, and 110 is POP3. --starttls smtp|imap|pop3|none overrides that. The other protocols pqdoctor upgrades are below.

The stack comes from the server’s greeting (the SMTP 220, IMAP * OK or POP3 +OK line), so the fix is written for Postfix, Dovecot, Exim or Exchange. A server that doesn’t offer STARTTLS on the port gets an error, not a diagnosis.

The setting names come from each project’s docs. Check them against your version, and confirm with openssl s_client -starttls ….

Postfix gets PQ from OpenSSL (postconf -a, openssl version). Its group list is tls_eecdh_auto_curves. Check the name and default in your release’s postconf(5).

# main.cf
tls_eecdh_auto_curves = X25519MLKEM768 X25519 prime256v1

Dovecot passes ssl_curve_list to OpenSSL as its group list. It needs OpenSSL 3.5 or newer underneath.

# dovecot.conf (2.3)
ssl_curve_list = X25519MLKEM768:X25519:prime256v1

Exim built against OpenSSL 3.5 or newer can take a group list in tls_eccurve. Check your version’s spec for list support.

tls_eccurve = X25519MLKEM768:X25519:prime256v1

PQ key exchange depends on the Windows Server version’s Schannel. Until it offers ML-KEM, put a PQ-capable mail relay in front, such as Postfix on OpenSSL 3.5.

The lab’s mail servers greet like Postfix and Dovecot, do the SMTP, IMAP or POP3 STARTTLS exchange, then speak TLS on OpenSSL 3.5 with the given groups.

Case pqdoctor said Fix applied After
SMTP STARTTLS, groups X25519:P-256 Not PQ (stack from the greeting: postfix) Postfix list X25519MLKEM768:X25519:prime256v1 PQ
IMAP STARTTLS, groups X25519 Not PQ (dovecot) Dovecot list PQ
POP3 STARTTLS, groups P-256:P-384 Not PQ (dovecot) Dovecot list PQ
SMTP without STARTTLS “the server doesn’t offer STARTTLS on this port” — —

Postfix’s space-separated list was joined with colons, which is how Postfix hands it to OpenSSL. Postfix, Dovecot and Exim themselves weren’t run. Only their group strings went through OpenSSL 3.5.

Protocol Port --starttls The upgrade
FTP 21 ftp AUTH TLS (RFC 4217). The greeting names vsFTPd or ProFTPD
XMPP 5222 xmpp A client stream to the host name, then <starttls/> → <proceed/> (RFC 6120)
LDAP 389 ldap The StartTLS extended operation (RFC 4511 / 4513)
PostgreSQL 5432 postgres SSLRequest → S
MySQL / MariaDB 3306 mysql The server’s handshake must offer CLIENT_SSL; then an SSLRequest. The greeting gives the version
RDP 3389 rdp X.224 Connection Request with RDP_NEG_REQ (TLS or CredSSP); TLS follows. There’s no openssl s_client equivalent, so verify says so
Terminal window
pqdoctor ftp.example.com:21
pqdoctor xmpp.example.org:5222
pqdoctor db.example.com:5432
pqdoctor rdp.example.com:3389
pqdoctor ldap.example.com:10389 --starttls ldap

A server that refuses the upgrade (no AUTH TLS, no xmpp-tls feature, N to SSLRequest, no CLIENT_SSL, RDP security only) gets a clear error, exit status 2.

Checked live on 2026-10-15: smtp.gmail.com:587 (post-quantum), test.rebex.net:21 FTPS (no-mlkem), jabber.org:5222 (no-mlkem), and Ubuntu 24.04’s PostgreSQL 16 in WSL (pinned-nist: its default ssl_ecdh_curve is prime256v1, which openssl s_client -starttls postgres confirmed). LDAP, MySQL and RDP are tested against fake servers only.

PostgreSQL 16 and older set one curve with ssl_ecdh_curve; newer releases take a group list. Check your release’s docs for the name, and that its OpenSSL is 3.5+.