thinkphp 6 安全发信需满足七项硬性要求:① env() 必须出现在 config/mail.php 中;② smtp 加密方式与端口严格绑定(ssl+465 或 tls+587);③ php 启用 openssl 且版本不低于 8.0;④ 密码字段填邮箱授权码而非登录密码;⑤ .env 中 mail_* 变量须手动映射到 config/mail.php;⑥ 每次发信必须新建 phpmailer 实例;⑦ 云服务器需放行出站 465/587 端口并注意 dns 解析问题。

env() 必须出现在 config/mail.php 里,否则所有加密配置都不生效 —— 这是 ThinkPHP 6 安全发信的第一道门槛,不是可选项。
SMTP 加密方式必须和端口严格绑定
ssl + 465 和 tls + 587 是唯二被广泛支持的组合,混用会导致连接卡死且无明确报错。QQ 邮箱只认 ssl + 465,163/Gmail 等多数服务要求 tls + 587。填成 ssl + 587 或 tls + 465,symfony/mailer 底层会直接放弃握手,日志里可能只显示 “Connection could not be established”。
- 检查 PHP 是否启用 OpenSSL:运行
php -m | grep openssl,输出为空说明未启用 - 确保
php.ini中extension=openssl未被注释,改完需重启 Web 服务(如sudo systemctl restart php-fpm) - PHP 版本不能低于 8.0,否则
tls协议协商可能失败,报错Unable to connect with TLS
密码字段必须填授权码,不是登录密码
QQ/163 等主流邮箱已全面禁用账户密码直连 SMTP,必须在邮箱设置中开启「POP3/IMAP/SMTP 服务」并生成独立授权码。填错时典型错误是SMTP Error: Could not authenticate,但提示里不会告诉你“该去邮箱后台开授权码”。
- QQ 邮箱授权码在「设置 → 账户 → POP3/IMAP/SMTP 服务」页生成
- 163 邮箱授权码在「设置 → POP3/SMTP/IMAP」中开启并设置
- 授权码要存进
.env的MAIL_PASSWORD,并在config/mail.php中通过env('MAIL_PASSWORD')读取
环境变量不自动加载,必须显式调用
ThinkPHP 6 不会自动把.env 里的 MAIL_* 变量映射到邮件配置,你得手动写进 config/mail.php。只改 .env 而不改这个文件,等于没配。
-
config/mail.php必须返回数组,关键字段全部用env():'host' => env('MAIL_HOST', 'smtp.qq.com'), 'port' => (int)env('MAIL_PORT', 465), 'encryption' => env('MAIL_ENCRYPTION', 'ssl'), 'username' => env('MAIL_USERNAME'), 'password' => env('MAIL_PASSWORD'), 'from' => env('MAIL_FROM_ADDRESS') - 验证是否读取成功:在控制器里执行
var_dump(env('MAIL_ENCRYPTION')),应输出"ssl"或"tls",而不是false或空字符串
别让 PHPMailer 实例复用
PHPMailer 内部维护连接状态、附件列表、收件人队列等可变属性,复用同一个实例发多封邮件,轻则附件叠加、重则 SSL 上下文冲突导致后续发送静默失败。- 每次发信都得新建:
$mail = new \PHPMailer\PHPMailer\PHPMailer(true); - 别在服务类里用
private static $instance缓存它 - 异步任务(如
think-queue)中尤其危险:每个 job 必须独立new,否则上一封的附件可能粘在下一帧里
真正容易被忽略的是:云服务器安全组默认只放行入站端口,出站 465 / 587 往往被拦住,且国内直连 Gmail/Outlook SMTP 容易被限流或 DNS 解析超时 —— 这些问题不会报错,只会让邮件发得慢或根本发不出。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











