docker环境下使用phpmailer发送邮件失败问题

最后更新于:2023-09-21 18:43

个人网站后端语言换成php后,在本地环境进行收发邮件测试。使用的是phpmailer,在本地测试win环境是没有任何问题的。

phpmailer使用的是github下载压缩包解压到本地的方式。

接着迁移到了线上服务环境,由于使用了docker部署,坑就出现了:怎么测试都无法发送。

整整看了一天半,测试了Google能查到的大部分方法:

比如用telnet测试SMTP服务器端口是否能通;

比如修改容器内hostname;

以及其他,最终解决办法是使用composer解决:

一.依赖由class解压类文件替换为composer

由于容器已经运行一段时间,不准备在删除重建,于是进入容器进行操作:

1.进入容器内进行操作:

docker exec -it  /bin/bash

2.安装composer:

curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer

3.在项目下创建或编辑composer.json

{
  "require": {
    "phpmailer/phpmailer": "^6.8.0"
  }
}

4.安装依赖项,在composer.json父目录执行:

运行 Composer 来安装新添加的依赖项。在项目目录中运行以下命令:

composer install

Composer 将根据 composer.json 中的配置安装所需的依赖项。

成功的话,会在 composer.json同级目录下,生成composer.lock 文件,同时在项目根目录生成vendor相关依赖文件夹。

也可能报错,报错的原因是因为缺少zip解压扩展:The zip extension and unzip/7z 。下文中有提到,安装即可。

5退出容器,并进行重启:

当您完成以上步骤后,退出容器。在容器内执行以下命令:

exit

重启容器:

最后,重启运行的容器,以便应用新的依赖项配置:

docker restart 

期间在composer install时候可能遇到的报错问题,因为缺少zip相关工具:

Failed to download phpmailer/phpmailer from dist: The zip extension and unzip/7z commands are both missing, skipping.
Your command-line PHP is using multiple ini files. Run `php --ini` to show them.
Now trying to download from source

 Linux centos环境下,执行安装命令:

apt-get update
apt-get install -y zip unzip

然后再次执行install,即可解决。

二.对原有的发送方法改造:

原有的email.php方法:

//引入PHPMailer的核心文件 使用require_once包含避免出现PHPMailer类重复定义的警告

use libs\Log;
use PHPMailer\PHPMailer\PHPMailer;//示例化PHPMailer核心类
use PHPMailer\PHPMailer\SMTP;//示例化PHPMailer核心类

include __DIR__ . '/phpMail/SMTP.php';
include __DIR__ . '/phpMail/PHPMailer.php';
include __DIR__ . '/phpMail/Exception.php';

$mail = new PHPMailer(true);
// 配置SMTP设置
//使用smtp鉴权方式发送邮件,当然你可以选择pop方式 sendmail方式等 本文不做详解
//可以参考http://phpmailer.github.io/PHPMailer/当中的详细介绍
$mail->isSMTP();
//smtp需要鉴权 这个必须是true
//是否启用smtpdebug进行调试 开发环境建议开启 生产环境注释掉即可 默认关闭debug调试模式
//$mail->SMTPDebug = 0;
$mail->SMTPDebug =3; // 设置为2可以输出更详细的调试信息 生产建议为0

$mail->SMTPAuth=true;
//链接qq域名邮箱的服务器地址
$mail->Host = 'smtp.gmail.com';
//设置使用ssl加密方式登录鉴权 因为163默认开启所以不要但是qq要这句
$mail->SMTPSecure = PHPMailer::ENCRYPTION_SMTPS;
//设置ssl连接smtp服务器的远程服务器端口号 可选 465 587 非加密 25
$mail->Port = 465;

// 配置邮件内容
//设置smtphelo消息头 这个可有可无 内容任意
//$mail->Helo = 'Hello smtp.163.com Server';
//设置发件人的主机域 可有可无 默认为localhost 内容任意,建议使用你的域名
//$mail->Hostname = '127.0.0.1';
//设置发送的邮件的编码 可选GB2312 我喜欢utf-8 据说utf8在某些客户端收信下会乱码
$mail->CharSet = 'UTF-8';
//设置发件人姓名(昵称) 任意内容,显示在收件人邮件的发件人邮箱地址前的发件人姓名
$mail->FromName = 'shanNote';
//smtp登录的账号 这里填入163邮箱账号即可
$mail->Username ='hi@shannote.com';
//smtp登录的密码
$mail->Password = '123456';
//设置发件人邮箱地址 这里填入上述提到的发件人邮箱
$mail->From = 'hi@shannote.com';
//邮件正文是否为html编码 注意此处是一个方法 不再是属性 truefalse
$mail->isHTML(true);
//设置收件人邮箱地址 该方法有两个参数 第一个参数为收件人邮箱地址 第二参数为给该地址设置的昵称
$mail->addAddress('receiveUser@qq.com',"超管XXX");
//添加多个收件人 则多次调用方法即可
//$mail->addAddress('xxx@163.com','测试');
//添加该邮件的主题
$mail->Subject = '用户下单通知';
//添加邮件正文 上方将isHTML设置成了true,则可以是完整的html字符串 如:使用file_get_contents函数读取本地的html文件
$mail->Body = $body;
//为该邮件添加附件 该方法也有两个参数 第一个参数为附件存放的目录(相对目录、或绝对目录均可) 第二参数为在邮件附件中该附件的名称
//$mail->addAttachment('./d.jpg','mm.jpg');
//同样该方法可以多次调用 上传多个附件
//$mail->addAttachment('./Jlib-1.1.0.js','Jlib.js');

//发送命令 返回布尔值
//PS:经过测试,要是收件人不存在,若不出现错误依然返回true 也就是说在发送之前 自己需要些方法实现检测该邮箱是否真实有效
Log::out('准备发送邮件'.$mail->Body);
//简单的判断与提示信息
try {
$mail->send();
$str = ''; // 用于存储调试输出的字符串
$mail->Debugoutput = function($output, $level) use (&$str) {
$str .= $output; // 将调试输出附加到 $str 字符串中
};
Log::out('结束调试输出:'.$str);
} catch (Exception $e) {
Log::out('发送结失败:'.$mail->ErrorInfo);
}
只需要将顶部的引入方式修改即可:

//引入PHPMailer的核心文件 使用require_once包含避免出现PHPMailer类重复定义的警告

use libs\Log;
use PHPMailer\PHPMailer\PHPMailer;//示例化PHPMailer核心类
use PHPMailer\PHPMailer\SMTP;//示例化PHPMailer核心类

require 'vendor/autoload.php';

$mail = new PHPMailer(true);
.......

最后顺便提一句,一般上面代码中使用 Password = '123456';即邮箱密码即可,但是对于一些使用授权码的邮件服务,这里的密码应该改为授权码,否则,可能发送邮件时可能出现错误,比如使用163邮箱时,未使用授权码替换密码,会报错:

SMTP Error: Could not authenticate.

此外,如果报错:

SMTP Error: Could not connect to SMTP host. Failed to connect to serverSMTP server error:

很可能是 设置ssl连接smtp服务器的远程服务器端口号 这一项选择有问题。



创建于2023-07-24 22:39 50 阅读