You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PHP联系表单仅支持部分邮箱提交,请求故障排查

联系表单邮件仅部分送达的问题排查与修复

由于我的标准表单无法在客户网站运行,因此改用了客户的联系表单邮箱。目前客户仅能收到部分提交(比如我的测试提交和一条随机提交),但使用个人邮箱或客户自身邮箱提交时,完全收不到表单邮件。我曾尝试修改From头信息,但直接导致所有提交失败。请问这段代码存在什么问题?

PHP脚本(mail.php)

function stripFormSlashes($arr)
{
    if(!is_array($arr))
    {
        return stripslashes($arr);
    }
    else
    {
        return array_map('stripFormSlashes', $arr);
    }
}

if(get_magic_quotes_gpc())
{
   $_POST = stripFormSlashes($_POST);
}
$message = "";
$message .= "First Name: " . htmlspecialchars($_POST['first_name'], ENT_QUOTES) . "<br />\n";
$message .= "Last Name: " . htmlspecialchars($_POST['last_name'], ENT_QUOTES) . "<br />\n";
$message .= "Email: " . htmlspecialchars($_POST['email'], ENT_QUOTES) . "<br />\n";
$message .= "Phone: " . htmlspecialchars($_POST['telephone'], ENT_QUOTES) . "<br />\n";
$message .= "Company: " . htmlspecialchars($_POST['company'], ENT_QUOTES) . "<br />\n";
$message .= "Comments: " . htmlspecialchars($_POST['message'], ENT_QUOTES) . "<br />\n";
$lowmsg = strtolower($message);
$injection_strings = array ("content-type:","charset=","mime-version:","multipart/mixed","bcc:","cc:");
foreach($injection_strings as $suspect)
{
    if((stristr($lowmsg, $suspect)) || (stristr(strtolower($_POST['first_name']), $suspect)) || (stristr(strtolower($_POST['email']), $suspect)))
    {
        die ( 'Illegal Input.  Go back and try again.  Your message has not been sent.' );
    }
}
$headers = "MIME-Version: 1.0\r\nContent-type: text/html; charset=utf-8\r\n";
$headers .= "Content-Transfer-Encoding: 8bit\r\n";
$headers .= "From: \"" . $_POST['first_name'] . " " . $_POST['last_name'] . "\" <" . $_POST['email'] . ">\r\n";
$headers .= "Reply-To: " . $_POST['email'] . "\r\n";
mail("emailtosendto@customdomain.com", "Contact Form Submission", $message, $headers);
header("Location: ../thank_you.html");
?>

表单模态框代码

<div
            class="modal fade"
            id="contactForm"
            data-bs-backdrop="static"
            data-bs-keyboard="false"
            tabindex="-1"
            aria-labelledby="contactFormLabel"
            aria-hidden="true"
        >
            <div class="modal-dialog modal-lg">
                <div class="modal-content">
                    <div
                        class="modal-header border-0"
                        style="background-color: var(--tp-theme-main-bg)"
                    >
                        <h2
                            class="modal-title fs-5"
                            id="ContactFormLabel"
                            style="font-size: 36px !important"
                        >
                            Contact Me!
                        </h2>
                        <button
                            type="button"
                            class="btn-close"
                            data-bs-dismiss="modal"
                            aria-label="Close"
                        ></button>
                    </div>
                    <div class="modal-body form-group col-12 px-5">
                        <p>
                            contact text
                        </p>
                        <form
                            action="./assets/mail.php"
                            method="POST"
                            id="contactForm"
                        >
                            <div class="row g-3">
                                <div class="col-md-6">
                                    <div class="input-item">
                                        <input
                                            type="text"
                                            name="first_name"
                                            placeholder="First Name"
                                            required
                                        />
                                    </div>
                                </div>
                                <div class="col-md-6">
                                    <div class="input-item">
                                        <input
                                            type="text"
                                            name="last_name"
                                            placeholder="Last Name"
                                            required
                                        />
                                    </div>
                                </div>
                                <div class="col-lg-12">
                                    <div class="input-item">
                                        <input
                                            type="text"
                                            name="company"
                                            placeholder="Company Name"
                                        />
                                    </div>
                                </div>
                                <div class="col-md-6">
                                    <div class="input-item">
                                        <input
                                            type="text"
                                            name="email"
                                            placeholder="Email Address"
                                            required
                                        />
                                    </div>
                                </div>
                                <div class="col-md-6">
                                    <div class="input-item">
                                        <input
                                            type="tel"
                                            name="telephone"
                                            placeholder="(555) 123-4567"
                                        />
                                    </div>
                                </div>
                                <div class="col-12">
                                    <div class="input-item-textarea">
                                        <textarea
                                            name="message"
                                            placeholder="Let us know what you're looking for"
                                            required
                                        ></textarea>
                                    </div>
                                </div>
                            </div>
                            <div class="modal-footer border-0 me-auto flex-row-reverse flex-md-row">
                                <button
                                    type="button"
                                    class="btn btn-secondary"
                                    data-bs-dismiss="modal"
                                >
                                    Close
                                </button>
                                <button
                                    type="submit"
                                    name="submit"
                                    class="btn btn-primary"
                                    style="position: relative"
                                >
                                    Submit
                                </button>
                            </div>
                        </form>
                    </div>
                </div>
            </div>
        </div>

核心问题分析

  1. 发件人身份验证失败(SPF/DKIM拦截)
    当前代码直接将用户提交的邮箱作为From头发件人地址:

    $headers .= "From: \"" . $_POST['first_name'] . " " . $_POST['last_name'] . "\" <" . $_POST['email'] . ">\r\n";
    

    主流邮件服务商都会通过SPF/DKIM验证发件人身份,如果服务器未被授权发送用户提交域名的邮件,邮件会被判定为伪造,直接被拦截或扔进垃圾箱。测试提交可能用了服务器允许的域名(比如客户自身域名),所以能正常送达,外部邮箱则会被拦截。

  2. 头信息拼接存在安全风险与格式错误
    直接拼接用户输入的姓名、邮箱到邮件头,未过滤换行符、引号等特殊字符,可能导致邮件头格式混乱,甚至触发邮件注入攻击。当前的注入检测仅覆盖特定字符串,防护不全面。

  3. 无错误处理与日志记录
    调用mail()后未检查返回值,也没有错误日志,无法定位发送失败的具体原因(比如服务器配置问题、DNS解析失败等)。

  4. 原生mail()函数局限性
    PHP原生mail()依赖服务器sendmail/SMTP配置,配置不当易被垃圾邮件系统标记,且对现代邮件验证机制支持不足。

修复方案

1. 修正发件人头信息

用服务器授权的邮箱(比如客户域名下的noreply邮箱)作为From头,保留Reply-To为用户邮箱,既符合验证规则,又不影响回复:

// 过滤姓名中的特殊字符,防止头注入
$safe_first_name = preg_replace('/[\r\n\t"]/', '', $_POST['first_name']);
$safe_last_name = preg_replace('/[\r\n\t"]/', '', $_POST['last_name']);
$safe_name = $safe_first_name . " " . $safe_last_name;
// 验证邮箱格式
$safe_email = filter_var($_POST['email'], FILTER_VALIDATE_EMAIL);
if (!$safe_email) {
    die('请输入有效的邮箱地址。');
}

$headers .= "From: \"Contact Form\" <noreply@customdomain.com>\r\n";
$headers .= "Reply-To: \"" . $safe_name . "\" <" . $safe_email . ">\r\n";

2. 加强输入验证

替换现有注入检测,全面过滤换行符,同时验证邮箱格式:

// 检查所有输入是否包含换行符,防止头注入
foreach ($_POST as $value) {
    if (preg_match('/[\r\n]/', $value)) {
        die('非法输入,请返回重试。');
    }
}
// 验证邮箱格式
if (!filter_var($_POST['email'], FILTER_VALIDATE_EMAIL)) {
    die('请输入有效的邮箱地址。');
}

3. 添加错误处理与日志

检查mail()返回值,记录错误日志:

$mail_sent = mail("emailtosendto@customdomain.com", "Contact Form Submission", $message, $headers);
if (!$mail_sent) {
    error_log("表单邮件发送失败: " . date('Y-m-d H:i:s') . " | 提交邮箱: " . $_POST['email']);
    die('邮件发送失败,请稍后重试或联系管理员。');
}
header("Location: ../thank_you.html");
exit;

4. 改用专业邮件库(推荐)

放弃原生mail(),使用PHPMailer/SwiftMailer支持SMTP协议,提升送达率:

require 'PHPMailer/PHPMailer.php';
require 'PHPMailer/SMTP.php';

$mail = new PHPMailer\PHPMailer\PHPMailer();
$mail->isSMTP();
$mail->Host = 'smtp.customdomain.com';
$mail->SMTPAuth = true;
$mail->Username = 'noreply@customdomain.com';
$mail->Password = 'your_auth_password';
$mail->SMTPSecure = 'tls';
$mail->Port = 587;

$mail->setFrom('noreply@customdomain.com', 'Contact Form');
$mail->addAddress('emailtosendto@customdomain.com');
$mail->addReplyTo($_POST['email'], $_POST['first_name'] . " " . $_POST['last_name']);

$mail->isHTML(true);
$mail->Subject = 'Contact Form Submission';
$mail->Body = $message;

if (!$mail->send()) {
    error_log("PHPMailer发送失败: " . $mail->ErrorInfo);
    die('邮件发送失败,请稍后重试。');
} else {
    header("Location: ../thank_you.html");
    exit;
}

内容的提问来源于stack exchange,提问作者Randy Christenhusz

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 13:44:49