使用SMTP PHPMailer给不同邮箱发定制内容仅首用户收到问题求助
问题排查与修复方案
核心错误原因
- 初始化PHPMailer时未开启异常模式,也没有判断
send()方法的返回结果,后续邮件发送失败时感知不到具体报错,无法定位问题 - SQL查询没有加
LIMIT 100限制,若活跃用户数量超过阈值,很容易触发邮件服务的发送频率限制,导致后续邮件直接被拦截 - 全局通用的配置项放在循环内重复执行,部分邮件服务商对重复提交的配置兼容性较差,可能引发未知错误
- 开启
SMTPKeepAlive后没有加异常重连逻辑,一旦单次发送触发SMTP连接报错,后续所有的发送请求都会直接失败
修复后代码
<?php use PHPMailer\PHPMailer\PHPMailer; use PHPMailer\PHPMailer\Exception; require 'class/src/Exception.php'; require 'class/src/PHPMailer.php'; require 'class/src/SMTP.php'; // 初始化时传true开启异常模式,发送出错会抛出异常 $mail = new PHPMailer(true); try { // 全局配置统一放在循环外,只初始化一次 $mail->isSMTP(); $mail->Host = 'mail.company.com'; $mail->SMTPAuth = true; $mail->Username = 'help@company.com'; $mail->Password = '****************'; $mail->SMTPSecure = 'ssl'; $mail->Port = 465; $mail->SMTPKeepAlive = true; $mail->setFrom('help@company.com', 'CompanyName'); $mail->Subject = "所有邮件统一公共标题"; $mail->isHTML(true); $mail->CharSet = 'UTF-8'; // SQL加LIMIT 100限制最多取100条数据 $fetch_data = $conn->query("SELECT name, email FROM db_table WHERE status = 'Active' LIMIT 100"); foreach ($fetch_data as $fetched_data) { $name = $fetched_data['name']; $email = $fetched_data['email']; try { $mail->addAddress($email, $name); $mail->Body = " <h3>Hi $name,</h3><h4>恭喜你!</h4>"; $mail->send(); // 清空收件人,给下一次发送做准备 $mail->ClearAllRecipients(); } catch (Exception $e) { // 这里可以记录单条邮件发送失败的日志,不影响其他用户发送 echo "给 {$email} 发送失败,错误信息:{$mail->ErrorInfo} <br>"; // 如果是SMTP连接报错,重置连接 if (str_contains($mail->ErrorInfo, 'SMTP connect')) { $mail->smtpClose(); $mail->smtpConnect(); } $mail->ClearAllRecipients(); continue; } } $mail->smtpClose(); } catch (Exception $e) { echo "邮件初始化异常:{$mail->ErrorInfo}"; } ?>
额外排查提示
如果修复后仍有发送失败的情况,直接打印$mail->ErrorInfo就能拿到具体失败原因,常见的情况包括:
- 收件人邮箱地址格式无效/不存在
- 邮件服务商触发频率限制,要求降低发送速度,可以在每次发送后加
sleep(1)做延迟 - 邮件内容命中服务商的反垃圾规则,被拦截
内容的提问来源于stack exchange,提问作者Anan
相关产品推荐
相关产品推荐

