个人网站后端语言换成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
//是否启用smtp的debug进行调试 开发环境建议开启 生产环境注释掉即可 默认关闭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;
// 配置邮件内容
//设置smtp的helo消息头 这个可有可无 内容任意
//$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 ='[email protected]';
//smtp登录的密码
$mail->Password = '123456';
//设置发件人邮箱地址 这里填入上述提到的“发件人邮箱”
$mail->From = '[email protected]';
//邮件正文是否为html编码 注意此处是一个方法 不再是属性 true或false
$mail->isHTML(true);
//设置收件人邮箱地址 该方法有两个参数 第一个参数为收件人邮箱地址 第二参数为给该地址设置的昵称
$mail->addAddress('[email protected]',"超管XXX");
//添加多个收件人 则多次调用方法即可
//$mail->addAddress('[email protected]','测试');
//添加该邮件的主题
$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服务器的远程服务器端口号 这一项选择有问题。
刷新