PHP mail函数无法发送含三个点的Gmail地址邮件问题排查
问题:PHP原生mail函数无法发送邮件到含三个点的Gmail地址
问题场景
使用PHP原生mail()函数发送邮件时,遇到以下异常情况:
- 无法发送到
testing.app.forward.123@gmail.com这类包含三个点的Gmail地址 - 能正常发送到
testing.app.forward@gmail.com(少于三个点)、testingappforward@gmail.com、testingapp.forward@gmail.com这类地址
用户代码如下:
$email_message = "自動通知メールのため、当メールアドレスへの返信はできません。 \n返信をご希望の場合は「info@pwr.co.jp」までご連絡をお願いいたします。" . "\n\n"; $email_message .= "以下の内容でご確認させていただきます。 " . "\n"; $email_message .= "--------------------------------------" . "\n"; $email_message .= "あなたのOTP: " . $otp . "\n"; $email_message .= "--------------------------------------" . "\n\n"; $email_message .= "弊社より一週間以内に返信がなければ、お手数ですが「info@hello.co.jp」までお問い合わせください。" . "\n"; $email_subject = '「Hello」OTPコード'; // create email headers $headers = 'From: ' . "info@hello.fun" . "\r\n" . 'Reply-To: ' . "info@hello.co.jp" . "\r\n" . 'X-Mailer: PHP/' . phpversion(); mail($request->email, $email_subject, $email_message, $headers);
原因分析
- Gmail本身支持带多个点的地址(Gmail会忽略用户名中的点,多地址和无点地址指向同一邮箱),所以问题不在Gmail端。
- 核心问题出在PHP
mail()函数的底层处理或服务器MTA(邮件传输代理,如Sendmail、Postfix)的配置:- 部分MTA默认配置会对邮箱地址的点数量做限制,或因严格格式校验误判多地址为无效。
- 原生
mail()未对收件地址做合规转义,多特殊字符(点)可能导致邮件头格式异常,被MTA拒绝。 - 原代码未指定邮件内容编码,日文内容可能引发解析错误,间接影响发送。
修复方法
1. 验证并转义收件地址
先验证邮箱格式,再用引号包裹地址避免格式问题:
$to = $request->email; // 验证邮箱有效性 if (!filter_var($to, FILTER_VALIDATE_EMAIL)) { // 处理无效地址逻辑 exit('无效邮箱地址'); } // 用引号包裹地址,避免特殊字符干扰 $to = '"' . addslashes($to) . '"'; // 后续mail函数调用改用处理后的$to mail($to, $email_subject, $email_message, $headers);
2. 完善邮件头,添加编码设置
给邮件头加上Content-Type指定编码,适配日文内容:
$headers = 'From: ' . "info@hello.fun" . "\r\n" . 'Reply-To: ' . "info@hello.co.jp" . "\r\n" . 'Content-Type: text/plain; charset=UTF-8' . "\r\n" . 'X-Mailer: PHP/' . phpversion();
3. 改用第三方邮件库(推荐)
原生mail()兼容性差,改用PHPMailer等库可自动处理地址转义、编码等问题:
require 'PHPMailer/PHPMailer.php'; require 'PHPMailer/SMTP.php'; $mail = new PHPMailer\PHPMailer\PHPMailer(); $mail->isSMTP(); $mail->Host = '你的SMTP服务器地址'; // 如smtp.gmail.com或你的服务商SMTP $mail->SMTPAuth = true; $mail->Username = '你的邮箱账号'; $mail->Password = '你的邮箱密码/授权码'; $mail->SMTPSecure = 'tls'; $mail->Port = 587; $mail->setFrom('info@hello.fun', 'Hello'); $mail->addAddress($request->email); $mail->addReplyTo('info@hello.co.jp', 'Info'); $mail->isHTML(false); $mail->Subject = '「Hello」OTPコード'; $mail->Body = $email_message; $mail->CharSet = 'UTF-8'; if (!$mail->send()) { echo '发送失败: ' . $mail->ErrorInfo; } else { echo '发送成功'; }
4. 检查服务器MTA配置
若坚持用原生mail(),需检查服务器MTA(如Postfix)的配置:
- 查看
smtpd_recipient_restrictions是否有过严规则 - 检查
address_verify相关配置是否拦截了多地址
内容的提问来源于stack exchange,提问作者Keinpyi Si
相关产品推荐
相关产品推荐

