【问题标题】:Can you specify TLS v1.3 only in phpmailer?您可以仅在 phpmailer 中指定 TLS v1.3 吗?
【发布时间】:2020-08-03 16:22:19
【问题描述】:

是否可以指定PHPMailer中使用的加密协议版本?

尝试构建一个用于测试 SMTP 配置的小型 Web 工具。我曾经能够在 .NET 中指定协议版本,但现在我使用的是 apache,我正在尝试使用 phpmailer 在 PHP 页面中执行此操作。所以我需要让它只尝试一个单一的加密版本,比如 TLS 1.3。

我知道我可以将 smtpautoTLS 设置为 FALSE。但是我可以在 SMTPOptions 数组之类的东西中指定 TLS 1.3 或 SSL v3 吗?我似乎无法在文档/示例/谷歌中找到它。

谢谢!

编辑更新代码并确认此代码仅适用于 SMTPS/隐式样式,但不适用于 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);
    }
?>

【问题讨论】:

    标签: phpmailer starttls sslv3 tls1.3


    【解决方案1】:

    TLSv1.3 支持的关键常量是 STREAM_CRYPTO_METHOD_TLSv1_3_CLIENT,它是 introduced in PHP 7.4.0,但似乎没有记录。

    PHPMailer 使用 TLS 常量 STREAM_CRYPTO_METHOD_TLS_CLIENT in the SMTP class when encryption is initialised via STARTTLS。此常量结合了 TLS 1.0、1.1、1.2 和 1.3,如您所见 in the PHP source

    因此,对于您的特定情况,您希望将STREAM_CRYPTO_METHOD_TLS_CLIENT 默认替换为STREAM_CRYPTO_METHOD_TLSv1_3_CLIENT。您可以通过子类化 SMTP 类并覆盖 startTLS 方法来实现您的要求(至少出于测试目的),以便您可以控制 TLS 常量。

    但是,该方法仅适用于 SMTP+STARTTLS,不适用于 SMTPS。对于 SMTPS(PHPMailer 中的ssl 模式),您可以使用对两者都适用的不同方法。查看this test case 表明您可以在传递给stream_context_create 的选项中指定连接类型常量——这与PHPMailer 允许您访问的数组完全相同,所以试试这个:

    $mail->SMTPOptions = [
        'ssl' => ['crypto_method' => STREAM_CRYPTO_METHOD_TLSv1_3_CLIENT]
    ];
    

    【讨论】:

    • 我不确定调整 crypto_method 是否有效。我使用 AWS SES 对其进行了测试,我认为它不应该支持 SSL 3.0,但它似乎通过了。我将看看是否可以使用 office 365 SMTP 进行测试。我添加了我的代码,以防错误很容易被发现。
    • 要记住的一点是,在邮件服务器上使用相对较低的安全设置是非常普遍的,因为未能协商安全连接可能会以明文传输结束,这比没有加密,不管它有多糟糕。不过,这更适用于入站而不是出站。
    • 我可以用我的 .NET 代码确认,在使用 SSL v3 时,通过使 AWS SES 电子邮件失败,控制加密协议按预期工作,但允许支持的协议。我还测试了您在选项中使用 SSL 模式的解决方案似乎仅适用于 SMTPS。我将不得不看看您的解决方案的第一部分是否允许我操纵 STARTTLS,因为这是症结所在,也是最常用的
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-04-03
    • 2014-05-27
    • 2015-03-26
    • 1970-01-01
    相关资源
    最近更新 更多