Laravel 邮件无法发送原因的查找

上一篇文章 Laravel 邮件配置 已经能够成功发送邮件 奈何部署到服务器后尽然无法发送。https://www.jianshu.com/p/459ab4f30c62

话不多说上图。

image.png

image.png

嗯嗯 看错误 是像端口被禁用了。

Connection could not be established with host smtp.exmail.qq.com

查文档。有一个童鞋一样的问题 链接 https://yq.aliyun.com/ask/65259

嗯禁用了25端口 可是我这个 465端口没有禁用呀。

确认一下


root@www:~# telnet smtp.exmail.qq.com 465
Trying 163.177.72.143...
Connected to smtp.exmail.qq.com.
Escape character is '^]'.

嗯 确实正常

那么就是环境的问题了
换个版本试试。

image.png

换成PHP7.2 正常

问题就出在php7.3上了

我们看看 laravel 报错的位置

$streamContext = stream_context_create($options);
        $this->stream = @stream_socket_client($host.':'.$this->params['port'], $errno, $errstr, $timeout, STREAM_CLIENT_CONNECT, $streamContext);
        if (false === $this->stream) {
            throw new Swift_TransportException(
                'Connection could not be established with host '.$this->params['host'].
                ' ['.$errstr.' #'.$errno.']'
                );
        }

嗯 是 stream_socket_client 这个函数没有正常运行。

查文档 php7.2到php7.3没有对这个函数进行更改。

那么问题出在哪呢。

将这段代码拎出来单独运行。

<?php
$a=stream_socket_client("ssl://smtp.exmail.qq.com:465", $errno, $errstr, 120, STREAM_CLIENT_CONNECT);
?>

错误出来了

Warning: stream_socket_client(): open_basedir restriction in effect. File(/etc/pki/tls/certs/ca-bundle.crt) is not within the allowed path(s): (/www/wwwroot/test.zhusutao.com/:/tmp/:/proc/) in /www/wwwroot/test.zhusutao.com/test.php on line 2

Warning: failed loading cafile stream: `/etc/pki/tls/certs/ca-bundle.crt' in /www/wwwroot/test.zhusutao.com/test.php on line 2

Warning: stream_socket_client(): Failed to enable crypto in /www/wwwroot/test.zhusutao.com/test.php on line 2

Warning: stream_socket_client(): unable to connect to ssl://smtp.exmail.qq.com:465 (Unknown error) in /www/wwwroot/test.zhusutao.com/test.php on line 2

open_basedir 没有包含 /etc/pki/tls/certs/ca-bundle.crt
那么包含进去吧。

image.png

发现还是不行。

看一下这个文件存在不 /etc/pki/tls/certs/ca-bundle.crt

嗯果然不存在。

看文件名像是证书文件。

比对一下php7.2的配置


php7.2 的配置

curl.cainfo = /etc/ca-bundle.crt
openssl.cafile = /etc/ca-bundle.crt

php7.3的配置

curl.cainfo = /etc/pki/tls/certs/ca-bundle.crt
openssl.cafile = /etc/pki/tls/certs/ca-bundle.crt

嗯 文件路径错误无疑了
改过来
php7.3新的的配置

curl.cainfo = /etc/ca-bundle.crt
openssl.cafile = /etc/ca-bundle.crt

在试着发送一下

image.png

完美!

Laravel 技术交流QQ群 852529151

本作品采用《CC 协议》,转载必须注明作者和本文链接
《L05 电商实战》
从零开发一个电商项目,功能包括电商后台、商品 & SKU 管理、购物车、订单管理、支付宝支付、微信支付、订单退款流程、优惠券等
《L03 构架 API 服务器》
你将学到如 RESTFul 设计风格、PostMan 的使用、OAuth 流程,JWT 概念及使用 和 API 开发相关的进阶知识。
讨论数量: 2

其实这是 PHP 版本差异导致的,自 php 5.6 起,当使用 SSL/TLS 的时候,流封装器默认验证端点证书和主机名。也就是 SSL 上下文中的 verify_peer 选项默认值变成 true 了。既然要验证证书,那就提供证书就可以了,所以楼主的解决方法可用,但是对于一些不想用证书的朋友以下可能是你喜欢的解决方案:

在 laravel 项目中的 config/mail 文件夹中写入以下配置:

    'password' => env('MAIL_PASSWORD'), // 这段代码无关,只是作为一个参考

    /*
    |--------------------------------------------------------------------------
    | SMTP Server stream context options
    |--------------------------------------------------------------------------
    |
    | This is an array that determines the stream context options and parameters.
    |
    */
    'stream'    => [
        'ssl' => [
            'verify_peer' => false
        ],
    ],

顺道提醒楼主一句,你的测试案例思路非常不错,但是你忽略了 stream_context_create

4年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!