PHPMailer 5.2.28 kann über SMTP keine Mails versenden: „key too small“

Für ein Projekt möchte ich ein Web-Formular als E-Mail versenden. Um die sensitiven Daten besonders gut zu schützen, möchte ich das E-Mail direkt vom Hosting Web-Server auf den Ziel-Mailserver senden und den lokalen SMTP des Hostinganbieters nicht mit den Daten in Berührung kommen lassen. Und die Übermittlung des E-Mails an den SMTP-Server müsste auch noch verschlüsselt erfolgen.

Leider verfügt der Ziel-SMTP-Server über ein (mittlerweile) schwaches Zertifikat, denn PHPMailer respektive OpenSSL weigert sich, verschlüsselt mit dem SMTP-Server zu kommunizieren:

...
2020-09-30 19:48:46 Connection failed. Error #2: stream_socket_enable_crypto(): SSL operation failed with code 1. OpenSSL Error messages:error:141A318A:SSL routines:tls_process_ske_dhe:dh key too small [../PHPMailer-5.2.28/class.smtp.php line 374]
...

PHPMailer gibt diese Debug-Meldungen direkt an den Browser aus, wenn man bei der Initialisierung der Klasse folgende Option aktiviert:

...
$mail = new PHPMailer();
...
$mail->SMTPDebug = SMTP::DEBUG_LOWLEVEL;
...

Andere, weniger geschwätzige Optionen sind: SMTP::DEBUG_CLIENT, SMTP::DEBUG_SERVER, SMTP::DEBUG_CONNECTION. SMTP::DEBUG_OFF unterdrückt jegliche Debug-Meldungen.

Das Problem ist, dass der vom Server verwendete Diffie Hellman-Key zu kurz ist; im vorliegenden Fall ist er nur 1024 bit lang. Dies erlaubt Logjam-Attacken.

Überprüfen kann man die Key-Länge mit folgendem Befehl:

$ openssl s_client -connect mailserver.tld:25 -starttls smtp
...
Server Temp Key: DH, 1024 bits
...

Beim Debugging habe ich auch noch den Web-Service www.checktls.com entdeckt, der mir bestätigt hat, dass der Server grundsätzlich verschlüsselt spricht.

Nun, entweder überzeugt man den Betreiber des SMTP-Servers, die Verschlüsselungskonfiguration anzupassen respektive einen neuen Schlüssel zu generieren.

Falls dies keine Option ist, und man das Risiko in Kauf nehmen möchte, gibt es aber noch folgende Möglichkeit:

...
$mail = new PHPMailer();
...
$mail->SMTPSecure = 'tls';
$mail->SMTPOptions = array(
'ssl' => array(
'security_level' => 0
)
);
...

Die Option security_level gibt es seit PHP 7.2 und OpenSSL 1.1.0. Mögliche Werte sind in der offiziellen Dokumentation nachzuschlagen. 0 bedeutet sinnbildlich NULL Sicherheit.

DIESER WORKAROUND ERFOLGT AUF EIGENE GEFAHR! Ich würde das nur machen, wenn man sich wirklich bewusst ist, was man tut.