PHP同函数发两封邮件时Gmail商家邮箱收不到问题排查
问题核心原因
你的代码存在业务逻辑错误+邮件配置不规范两类问题,和Gmail的接收限制没有直接关系,核心错误如下:
代码逻辑硬错误(这是商家收不到邮件的首要原因)
- 循环提前终止:你在遍历全量商家的
while循环内部直接写了return判断,只要遍历完第一个(最新注册、ID最大的)商家,就会直接退出整个函数,除了第一个商家之外,其他所有商家根本不会被遍历到,自然收不到邮件。同时你在内层查询平台订单商品的循环中,复用了外层商家循环的$row变量,会直接覆盖外层结果集的游标,进一步导致外层循环无法遍历后续商家。 - 发信判断缺失:你没有校验当前遍历到的商家是否真的有对应
$cart_code的订单,哪怕商家和当前订单完全无关,也会给他发送一封只有标题、没有商品内容的空订单通知。 - 结果判断失效:PHP原生
mail()函数返回true仅代表邮件成功提交到你服务器本地的发信代理,完全不代表对方邮箱服务器成功收到邮件,更不代表邮件进入了收件箱,你现有的判断逻辑无法确认商家侧的实际送达状态。 - 安全隐患:查询商品信息时直接拼接未转义的
$p_id参数到SQL语句,存在SQL注入风险。
邮件配置不规范(就算逻辑修对,Gmail也大概率收不到)
- 邮件头不符合RFC标准:你拼接邮件头使用
\n作为换行符,国际邮件标准要求使用\r\n作为头信息换行符,同时缺少Date、Message-ID、Reply-To这类必要头字段,很容易被Gmail等服务商判定为垃圾邮件直接拦截。 - 发信来源可信度不足:使用原生
mail()函数发信时,如果你的发件域名shoply.ng没有配置正确的SPF、DKIM、DMARC解析记录,发件服务器IP也没有做反向PTR解析,Gmail会直接拒收这类来源无法验证的邮件,多数情况下连垃圾箱都不会投递,也不会返回退信提示。 - 邮件内容不规范:你发送的邮件只有HTML格式内容,没有配套的纯文本备选内容,会进一步提高垃圾邮件判定评分。
修复方案
- 重构查询逻辑:不要全表遍历所有商家,直接通过
cart_db关联business_account表,查询出当前订单号对应的所有所属商家,针对性发信,避免无效遍历和空邮件发送。 - 修正循环逻辑:内层循环单独命名变量,不要和外层循环的
$row重名;把return逻辑移到所有循环执行完成之后,等所有对应商家都处理完再返回最终结果。 - 规范邮件配置:补全符合标准的邮件头,统一用
\r\n作为换行符;放弃原生mail()函数,改用成熟的邮件类库通过SMTP方式发信;给发件域名配置SPF、DKIM、DMARC解析,给发件服务器IP做反向PTR解析,大幅提升Gmail送达率。 - 增加前置判断:给商家发信前先校验对应订单的商品结果集是否为空,只有当前商家确实有对应订单商品时,才组装邮件内容触发发信。
- 所有SQL入参都做转义处理,包括数字类型的产品ID,避免SQL注入。
内容的提问来源于stack exchange,提问作者Eluan David Harold
相关产品推荐
相关产品推荐

