大概率会,PHP的mail()函数缺乏SMTP认证、加密及域名验证,易被拒收或归入垃圾箱;群发时若循环调用且To头暴露全部收件人,更触发滥发识别。

PHP直接用mail()函数群发会触发垃圾邮件过滤吗
大概率会。默认的mail()函数不支持设置SMTP认证、加密连接和发信域名验证,很多邮箱(如Gmail、QQ邮箱)会直接拒收或打入垃圾箱。更关键的是,它一次只能发一封——所谓“群发”,如果循环调用mail()发100人,每封邮件的To头里还写满所有收件人,极易被识别为滥发。
用PHPMailer发群发邮件必须逐个调用send()吗
不是必须,但推荐。PHPMailer本身不提供原生“批量发送”接口,它的addAddress()支持多次调用,但若把100个邮箱全加进同一个实例再send(),最终发出的邮件仍是“群发可见”(所有收件人能看到彼此邮箱),且一旦其中1个地址无效,整封发送失败。正确做法是:
- 每次循环中新建一个PHPMailer实例(避免状态残留)
- 对每个收件人单独调用
addAddress($email, $name)和send() - 在
send()后检查$mail->isSent(),记录失败地址,不要让一次失败中断整个队列 - 加上
sleep(0.5)或使用队列系统控制并发,防止被SMTP服务器限流(比如腾讯企业邮箱限制100封/小时)
示例关键片段:
$mail = new PHPMailer\PHPMailer\PHPMailer();
$mail->isSMTP();
$mail->Host = 'smtp.exmail.qq.com';
$mail->SMTPAuth = true;
$mail->Username = 'notice@yourdomain.com';
$mail->Password = 'your_app_password'; // 注意:不是邮箱登录密码
$mail->SMTPSecure = 'tls';
$mail->Port = 587;
<p>foreach ($recipients as $r) {
$mail->clearAddresses(); // 必须清空,否则地址会累积
$mail->addAddress($r['email'], $r['name']);
$mail->Subject = '订单通知';
$mail->Body = "Hi {$r['name']},您的订单已发货";</p><pre class="brush:php;toolbar:false;">if (!$mail->send()) {
error_log("发送失败: {$r['email']} - {$mail->ErrorInfo}");
}
sleep(0.3);}
立即学习“PHP免费学习笔记(深入)”;
群发时如何避免被当成垃圾邮件
技术上能控的点比想象中少,但以下几项不做,基本等于主动进垃圾箱:
- 发信域名必须配置SPF、DKIM、DMARC记录(尤其DKIM,PHPMailer可通过
setDKIM()加载私钥签名) - From邮箱必须和SMTP登录账号一致,且域名需与SPF记录匹配(例如SMTP用
notice@abc.com,SPF记录就得包含v=spf1 include:spf.exmail.qq.com ~all) - 邮件正文不能全是图片、无文本、含大量感叹号或“免费”“限时”等敏感词
- 首次群发前,先给几个测试邮箱发几封,用
https://www.mail-tester.com测分(低于9分就别上线)
高并发群发要不要自己搭邮件队列服务
日均发信量超500封,或者需要定时发送、失败重试、发送统计,就别硬扛了。PHP内置的mail()和简单循环都扛不住。这时候该用:
- 基于Redis + Cron的轻量队列:把收件人信息序列化存入List,后台脚本pop+发送,失败push回队列
- 对接SendGrid / Mailgun API:它们天然支持批量发送(Batch API)、打开/点击追踪、退订管理,且IP信誉由服务商维护
- 避免用MySQL做队列表并轮询——锁表、慢查询、连接数爆炸都是现成的坑
如果你只发内部通知且量小,PHPMailer+sleep+日志就够了;但只要涉及用户触达,邮件送达率永远比“代码跑通”重要得多。



















