Can you specify TLS v1.3 only in phpmailer?

6.5k Views Asked by At

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);
    }
?>
1

There are 1 best solutions below

3
On

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]
];