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

PHP带附件邮件仅发附件,表单其他信息未送达问题求助

问题分析与修复方案

我瞅了下你的代码,发现几个关键问题导致姓名、邮箱这些表单信息没跟着邮件发出去,顺便还帮你修正了几个MIME结构和变量使用的小bug,一起来看看:

存在的核心问题

  • 你只处理了附件部分,完全没把姓名、邮箱这些表单数据加入到邮件内容里,multipart/mixed类型的邮件需要包含文本内容块和附件块两部分
  • 变量$nom先通过htmlentities转义,又直接用$_POST['firstname']覆盖,失去了XSS防护的作用
  • 附件读取时错误使用了原文件名$nom_fichier,应该用上传后的临时文件路径$source
  • MIME分隔符的使用不规范,每个内容块必须以--$boundary开头,结尾用--$boundary--
  • 请求头里重复声明了MIME-Version,容易导致解析异常
  • 邮件内容的拼接逻辑混乱,没有按照MIME结构正确组织

修复后的完整代码

<?php
error_reporting(E_ALL);
ini_set("display_errors", 1); // 显示错误

// 处理表单数据并做XSS防护
$nom = htmlentities($_POST['firstname'], ENT_QUOTES, 'UTF-8');
$email = htmlentities($_POST['email'], ENT_QUOTES, 'UTF-8');

// 检查邮件服务商支持的换行符
if(preg_match("#@(hotmail|live|msn)\.[a-z]{2,4}$#i", $email)){
    $passage_ligne = "\n";
}else{
    $passage_ligne = "\r\n";
}

$email_to = "mon adresse email"; // 收件人邮箱
$email_subject = "Recrutement "; // 邮件主题
$boundary = md5(rand()); // 随机分隔符密钥

// 构建邮件头,避免重复声明MIME-Version
$headers = "MIME-Version: 1.0{$passage_ligne}";
$headers .= "From: EA <{$email}>{$passage_ligne}"; // 用用户邮箱作为发件人回复地址更合理
$headers .= "Reply-To: {$nom} <{$email}>{$passage_ligne}";
$headers .= "Content-Type: multipart/mixed; boundary=\"{$boundary}\"{$passage_ligne}{$passage_ligne}";

// 初始化邮件内容,先添加表单信息的文本部分
$email_message = "--{$boundary}{$passage_ligne}";
$email_message .= "Content-Type: text/plain; charset=UTF-8{$passage_ligne}";
$email_message .= "Content-Transfer-Encoding: 8bit{$passage_ligne}{$passage_ligne}";
$email_message .= "新的招聘咨询信息{$passage_ligne}{$passage_ligne}";
$email_message .= "姓名: {$nom}{$passage_ligne}";
$email_message .= "邮箱: {$email}{$passage_ligne}{$passage_ligne}";

// 处理附件
if(isset($_FILES["fichier"]) && $_FILES['fichier']['error'] === UPLOAD_ERR_OK && $_FILES['fichier']['name'] != ""){
    $nom_fichier = $_FILES['fichier']['name'];
    $source = $_FILES['fichier']['tmp_name'];
    $type_fichier = $_FILES['fichier']['type'];
    $taille_fichier = $_FILES['fichier']['size'];

    if($nom_fichier != ".htaccess"){
        if(in_array($type_fichier, ["image/jpeg", "image/pjpeg", "application/pdf"])){
            if ($taille_fichier <= 2097152) { // 2MB限制
                // 替换文件名特殊字符
                $nom_fichier = strtr($nom_fichier, ["é"=>"e", "è"=>"e", "à"=>"a"]);
                // 读取并编码附件内容
                $content = file_get_contents($source);
                $encoded_content = chunk_split(base64_encode($content));

                // 添加附件部分到邮件
                $email_message .= "--{$boundary}{$passage_ligne}";
                $email_message .= "Content-Type: {$type_fichier}; name=\"{$nom_fichier}\"{$passage_ligne}";
                $email_message .= "Content-Transfer-Encoding: BASE64{$passage_ligne}";
                $email_message .= "Content-Disposition: attachment; filename=\"{$nom_fichier}\"{$passage_ligne}{$passage_ligne}";
                $email_message .= $encoded_content . $passage_ligne;
            }else{
                $email_message .= "用户尝试发送附件,但文件大小超过2MB。{$passage_ligne}";
            }
        }else{
            $email_message .= "用户尝试发送附件,但文件格式不正确(仅支持JPEG/PDF)。{$passage_ligne}";
        }
    }else{
        $email_message .= "用户尝试发送.htaccess附件,已拒绝。{$passage_ligne}";
    }
}

// 结束MIME分隔符
$email_message .= "--{$boundary}--{$passage_ligne}";

// 发送邮件
if(mail($email_to, $email_subject, $email_message, $headers)){
    header('Location: index.php');
    exit; // 跳转后终止脚本执行
}else{
    echo "邮件发送失败,请检查服务器邮件配置";
}
?>

关键修改说明

  1. 新增文本内容块:在邮件最开头添加了包含姓名、邮箱的纯文本部分,确保收件人能看到表单提交的基础信息
  2. 规范变量处理:保留htmlentities的转义(并指定编码和引号规则),避免XSS风险
  3. 修复附件读取路径:用上传临时文件路径$source读取内容,而不是原文件名(原文件名在服务器上不存在)
  4. 规范MIME结构:每个内容块都以--$boundary开头,结尾用--$boundary--闭合,确保邮件客户端能正确解析
  5. 优化邮件头:将用户的邮箱和姓名设置为回复地址,更符合实际使用场景,同时去掉重复的MIME-Version声明
  6. 增加错误判断:用UPLOAD_ERR_OK判断文件上传是否成功,避免无效的文件处理
  7. 脚本终止:跳转页面后添加exit,防止后续代码执行

内容的提问来源于stack exchange,提问作者Safa Jwd

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 09:45:25