PHP sendmail脚本突发故障求助:运行三年的网站表单失效
排查与解决PHP Sendmail表单失效问题
第一步:移除错误抑制,获取具体错误信息
原脚本中@mail()的错误抑制符会掩盖真实错误,先去掉它并开启PHP错误报告,直接定位问题根源:
error_reporting(E_ALL); ini_set('display_errors', 1); // ... 保留原脚本其他代码 ... if(mail($sendto, $subject, $msg, $headers)) { echo "Thank You!"; } else { echo "邮件发送失败,错误信息:" . error_get_last()['message']; }
提交表单后查看页面返回的具体错误,这是最快定位问题的方式。
第二步:检查服务器Sendmail服务状态
- 登录服务器,执行命令检查Sendmail是否正常运行:
若服务未运行,启动服务:# systemd系统(如Ubuntu 16.04+、CentOS 7+) systemctl status sendmail # SysVinit系统 service sendmail statussystemctl start sendmail # 或 service sendmail start - 查看邮件日志获取发送失败的详细记录:
日志中通常会包含邮件被拒绝、队列阻塞或配置错误的具体信息。# Debian/Ubuntu系统 tail -f /var/log/mail.log # CentOS/RHEL系统 tail -f /var/log/maillog
第三步:验证PHP邮件配置
检查PHP的sendmail_path配置是否正确:
- 在脚本中添加代码查看当前配置:
echo "Sendmail路径:" . ini_get('sendmail_path'); - 或创建
phpinfo.php文件,访问后查找sendmail_path项,确保路径指向正确的Sendmail可执行文件(通常为/usr/sbin/sendmail -t -i)。
第四步:排查邮件投递与信誉问题
- 检查收件箱垃圾邮件文件夹:邮件可能被当作垃圾邮件拦截,而非发送失败。
- 验证SPF/DKIM配置:若近期域名DNS记录有变更,可能导致SPF/DKIM验证失败,邮件被拒收。
- 检查服务器IP信誉:服务器IP可能被列入邮件黑名单(如Spamhaus),导致邮件无法投递,需确认IP状态。
第五步:优化脚本的安全性与兼容性
原脚本存在直接使用用户输入的风险,且邮件头格式可能存在问题,建议修改如下:
<?php error_reporting(E_ALL); ini_set('display_errors', 0); // 生产环境关闭错误显示,改为记录日志 $sendto = "milestone.kamal@gmail.com"; // 验证并过滤POST数据 $name = filter_input(INPUT_POST, 'name', FILTER_SANITIZE_STRING); $email = filter_input(INPUT_POST, 'email', FILTER_VALIDATE_EMAIL); $mobile = filter_input(INPUT_POST, 'mobile', FILTER_SANITIZE_STRING); $project = filter_input(INPUT_POST, 'project', FILTER_SANITIZE_STRING); $city = filter_input(INPUT_POST, 'city', FILTER_SANITIZE_STRING); // 验证必填字段 if (!$name || !$email || !$mobile || !$project) { echo "请填写所有必填字段"; exit; } $subject = $project . " Enquiry"; // 使用服务器域名邮箱作为From地址,提升投递成功率 $headers = "From: Website Enquiry <noreply@dlfhomes.co.in>\r\n"; $headers .= "Reply-To: " . $email . "\r\n"; $headers .= "MIME-Version: 1.0\r\n"; $headers .= "Content-Type: text/html;charset=utf-8\r\n"; $msg = "<html><body style='font-family:Arial,sans-serif;'>"; $msg .= "<h2 style='font-weight:bold;border-bottom:1px dotted #ccc;'>" . htmlspecialchars($project) . " Enquiry</h2>"; $msg .= "<p><strong>Full Name:</strong> " . htmlspecialchars($name) . "</p>"; $msg .= "<p><strong>Mobile No:</strong> " . htmlspecialchars($mobile) . "</p>"; $msg .= "<p><strong>Email:</strong> " . htmlspecialchars($email) . "</p>"; $msg .= "<p><strong>Project:</strong> " . htmlspecialchars($project) . "</p>"; $msg .= "<p><strong>City:</strong> " . htmlspecialchars($city) . "</p>"; $msg .= "</body></html>"; // 记录发送日志(可选) file_put_contents('mail_log.txt', date('Y-m-d H:i:s') . " - 尝试发送邮件至:$sendto,主题:$subject\n", FILE_APPEND); if(mail($sendto, $subject, $msg, $headers)) { echo "Thank You!"; file_put_contents('mail_log.txt', date('Y-m-d H:i:s') . " - 邮件发送成功\n", FILE_APPEND); } else { $error = error_get_last()['message'] ?? "未知错误"; echo "发送失败,请稍后重试"; file_put_contents('mail_log.txt', date('Y-m-d H:i:s') . " - 邮件发送失败:$error\n", FILE_APPEND); } ?>
修改点说明:
- 增加输入验证与过滤,避免XSS攻击和非法数据导致的错误
- 改用服务器域名邮箱作为
From地址,避免被收件服务器拒收 - 统一使用
\r\n作为邮件头换行符,符合RFC标准 - 添加日志记录,方便后续排查
内容的提问来源于stack exchange,提问作者Kamal K
相关产品推荐
相关产品推荐

