Laravel集成了SwiftMailer库进行邮件发送,邮件配置文件位于config/mail.PHP:
第一步:.env中的MAIL配置
由于阿里云屏蔽了25端口所以改用465端口或者568端口
MAIL_DRIVER=smtpMAIL_HOST=smtp.qq.comMAIL_PORT=465MAIL_USERNAME=xxxxxxxxx@qq.com #你的QQ号或QQ邮箱MAIL_PASSWORD=abcdabcdabcdabcd #授权码MAIL_ENCRYPTION=ssl
16位授权码在QQ邮箱->设置->帐号页面中,开启使用smtp
后可以得到。
encryption
默认是null,需要设置为tls否则会报类似“Must issue a STARTTLS command first.”这种错误。
第二步:config/mail.php中配置from
'from' => [ 'address' => env('MAIL_FROM_ADDRESS', 'xxxxxxxxx@qq.com'), 'name' => env('MAIL_FROM_NAME', 'Example'),],
这样基本邮件配置功能就完成了,运行一下邮件的发送功能报错
aravel5
已经有很好的邮件发送功能,但都是常规 tls
不加密协议,现在有的云服务器已经慢慢禁止使用不加密协议,要求使用ssl加密协议;如阿里云新购买的服务器都开始禁止。
由于laravel5
默认使用的是 swiftmailer
扩展。发送使用的是 stream
其中并未对ssl
提供证书等内容配置,所以当使用ssl时又未指定证书时会错:
Connection could not be established with host *******.com [ #0]
连接失败,造成错误的地方:vendor/swiftmailer/swiftmailer/lib/classes/Swift/Transport/StreamBuffer.php 类
Swift_Transport_StreamBuffer
的 _establishSocketConnection
方法在调用 stream_context_create
时缺少证书相关配置。
看看PHP官方文档:http://php.net/manual/zh/context.ssl.php
其中需要注意的是 verify_peer_name
要求验证证书名默认值为true
,这里是问题所以,当没有指定证书时该值会影响连接验证失败导致整个连接失败。因此需要修改代码并把 verify_peer_name
设置为 false
。
这个问题在 https://github.com/swiftmailer/swiftmailer/issues/544 中已经有说明。
但其增加了两行代码把 verify_peer
和 verify_peer_name
都设置为false
。依文档中看,verify_peer
默认值已经是 false
,所以可以不加。
修改代码如下:
/** * Establishes a connection to a remote server. */ private function establishSocketConnection() { $host = $this->params['host']; if (!empty($this->params['protocol'])) { $host = $this->params['protocol'].'://'.$host; } $timeout = 15; if (!empty($this->params['timeout'])) { $timeout = $this->params['timeout']; } $options = []; if (!empty($this->params['sourceIp'])) { $options['socket']['bindto'] = $this->params['sourceIp'].':0'; } //在这里增加代码,修改默认值$options['ssl']['verify_peer'] = FALSE; $options['ssl']['verify_peer_name'] = FALSE; if (isset($this->params['stream_context_options'])) { $options = array_merge($options, $this->params['stream_context_options']); } $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.']' ); } if (!empty($this->params['blocking'])) { stream_set_blocking($this->stream, 1); } else { stream_set_blocking($this->stream, 0); } stream_set_timeout($this->stream, $timeout); $this->in = &$this->stream; $this->out = &$this->stream; }
这样在运行一边邮件发送功能就OK!