Reputation: 75
Is it possible to specify the encryption protocol version used in PHPMailer?
Trying to build a small web tool for testing SMTP configurations. I used to be able to specify protocol version in .NET, but now that I am using apache, I am trying to do it in a PHP page with phpmailer. So I need to have it try ONLY a single encryption version like TLS 1.3.
I know I can set the smtpautoTLS to FALSE. But Can I specify TLS 1.3 or SSL v3 in something like the SMTPOptions Array? I haven't seemed to be able to find this in documentation/examples/google.
Thanks!
Edit for updated code and confirm this code only works for SMTPS/implicit style, but NOT STARTTLS
<?php
require_once 'PHPMailer/vendor/autoload.php';
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\Exception;
$from = $_POST['from'];
$to = $_POST['to'];
$subj = $_POST['subj'];
$body = $_POST['body'];
$server = $_POST['addr'];
$port = $_POST['port'];
$auth = $_POST['auth'];
$enctype = $_POST['enctype'];
$encver = $_POST['encver'];
$authuser = $_POST['authuser'];
$authpw = $_POST['authpw'];
$mail = new PHPMailer(true);
$mail->IsSMTP();
//$mail->SMTPDebug = 2; //2 for debugging with server responses. 0-4 as choices
$smtpopts = array();
if($encver == "auto")
{
$mail->SMTPAutoTLS = true;
}
else
{
$mail->SMTPAutoTLS = false;
}
if($auth == 1)
{
$mail->SMTPAuth = true;
$mail->Username = $authuser;
$mail->Password = $authpw;
switch($enctype)
{
case "implicit":
$mail->SMTPSecure = PHPMailer::ENCRYPTION_SMTPS;
break;
case "explicit":
$mail->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS;
break;
}
switch($encver)
{
case "ssl3_0":
$smtpopts['ssl'] = array('crypto_method' => STREAM_CRYPTO_METHOD_SSLv3_CLIENT);
break;
case "tls1_0":
$smtpopts['ssl'] = array('crypto_method' => STREAM_CRYPTO_METHOD_TLSv1_0_CLIENT);
break;
case "tls1_1":
$smtpopts['ssl'] = array('crypto_method' => STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT);
break;
case "tls1_2":
$smtpopts['ssl'] = array('crypto_method' => STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT);
break;
case "tls1_3":
$smtpopts['ssl'] = array('crypto_method' => STREAM_CRYPTO_METHOD_TLSv1_3_CLIENT);
break;
}
$mail->SMTPOptions = $smtpopts;
}
else
{
$mail->SMTPAuth = false;
}
$mail->Host = $server;
$mail->Port = $port;
$mail->SetFrom($from);
$mail->AddAddress($to);
$mail->Subject = $subj;
$mail->MsgHTML($body);
$response = array();
try
{
header('Content-Type: application/json');
$mail->Send();
$response['success'] = 1;
$response['msg'] = "Success";
echo json_encode($response);
}
catch (Exception $e)
{
$response['success'] = 0;
$response['msg'] = $e->errorMessage();
error_log($e->errorMessage());
echo json_encode($response);
}
catch (\Exception $e)
{
$response['success'] = -99;
$response['msg'] = $e->getMessage();
error_log($e->getMessage());
echo json_encode($response);
}
?>
Upvotes: 1
Views: 7050
Reputation: 37710
The critical constant for TLSv1.3 support is STREAM_CRYPTO_METHOD_TLSv1_3_CLIENT
, which was introduced in PHP 7.4.0, but appears to be undocumented.
PHPMailer uses the TLS constant STREAM_CRYPTO_METHOD_TLS_CLIENT
in the SMTP class when encryption is initialised via STARTTLS. This constant combines TLS 1.0, 1.1, 1.2, and 1.3, as you can see in the PHP source.
So, for your particular situation, you want to substitute the STREAM_CRYPTO_METHOD_TLS_CLIENT
default for STREAM_CRYPTO_METHOD_TLSv1_3_CLIENT
. You can achieve what you ask (at least for testing purposes) by subclassing the SMTP class and overriding the startTLS
method so that you can control the TLS constant.
However, that approach will only work for SMTP+STARTTLS, not SMTPS. For SMTPS (ssl
mode in PHPMailer) you can use a different approach that may work for both. Looking at this test case shows that you can specify a connection type constant in the options passed to stream_context_create
– and this is the exact same array that PHPMailer gives you access to, so try this:
$mail->SMTPOptions = [
'ssl' => ['crypto_method' => STREAM_CRYPTO_METHOD_TLSv1_3_CLIENT]
];
Upvotes: 2