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

使用PHP mail()发送带.docx附件失败,请求代码排查及修改建议

解决PHP mail()发送docx附件失败的问题

从你的代码来看,主要问题出在文件上传验证缺失和MIME邮件结构错误上,以下是具体的修正方案:

第一步:修正mail.php的核心问题

修正后的完整mail.php代码

<?php
if (isset($_POST['submit'])) {
    $mailto = "to@gmail.com";
    $from_mail = $_POST["fromEmail"];
    $replyto = $_POST["fromEmail"];
    $from_name = $_POST["fromName"];
    $message = "This is message part";
    $subject = "this is subject part";

    // 1. 首先处理文件上传验证
    $fileError = $_FILES["fileAttach"]["error"];
    if ($fileError !== UPLOAD_ERR_OK) {
        $errorMsg = match($fileError) {
            UPLOAD_ERR_INI_SIZE => "上传文件超过php.ini限制",
            UPLOAD_ERR_FORM_SIZE => "上传文件超过表单限制",
            UPLOAD_ERR_PARTIAL => "文件仅部分上传",
            UPLOAD_ERR_NO_FILE => "未选择上传文件",
            UPLOAD_ERR_NO_TMP_DIR => "服务器缺少临时目录",
            UPLOAD_ERR_CANT_WRITE => "文件写入失败",
            UPLOAD_ERR_EXTENSION => "PHP扩展阻止了文件上传",
            default => "未知上传错误"
        };
        echo "<script>alert('上传失败:{$errorMsg}');</script>";
        exit;
    }

    // 2. 验证文件类型为docx
    $allowedMime = ["application/vnd.openxmlformats-officedocument.wordprocessingml.document"];
    $fileMime = mime_content_type($_FILES["fileAttach"]["tmp_name"]);
    if (!in_array($fileMime, $allowedMime)) {
        echo "<script>alert('仅允许上传docx格式文件');</script>";
        exit;
    }

    // 3. 处理文件信息
    $filename = basename($_FILES["fileAttach"]["name"]);
    $content = chunk_split(base64_encode(file_get_contents($_FILES["fileAttach"]["tmp_name"])));
    $uid = md5(uniqid(time()));

    // 4. 构建邮件头(仅包含基础头信息)
    $header = "From: " . $from_name . " <" . $from_mail . ">\r\n";
    $header .= "Reply-To: " . $replyto . "\r\n";
    $header .= "MIME-Version: 1.0\r\n";
    $header .= "Content-Type: multipart/mixed; boundary=\"" . $uid . "\"\r\n";

    // 5. 构建邮件主体内容(包含正文和附件)
    $body = "This is a multi-part message in MIME format.\r\n";
    $body .= "--" . $uid . "\r\n";
    $body .= "Content-type:text/html; charset=utf-8\r\n";
    $body .= "Content-Transfer-Encoding: 7bit\r\n\r\n";
    $body .= "<div style='color: red'>" . $message . "</div>\r\n\r\n";
    
    $body .= "--" . $uid . "\r\n";
    $body .= "Content-Type: {$fileMime}; name=\"" . $filename . "\"\r\n";
    $body .= "Content-Transfer-Encoding: base64\r\n";
    $body .= "Content-Disposition: attachment; filename=\"" . $filename . "\"\r\n\r\n";
    $body .= $content . "\r\n\r\n";
    $body .= "--" . $uid . "--";

    // 6. 发送邮件:第三个参数是完整的邮件主体,第四个是头信息
    if (mail($mailto, $subject, $body, $header)) {
        echo "<script>alert('Success');</script>";
    } else {
        echo "<script>alert('Failed');</script>";
        // 调试时可以开启错误提示:error_reporting(E_ALL); ini_set('display_errors', 1);
    }
}
?>

关键修改点说明

  1. 增加文件上传完整验证

    • 检查$_FILES["fileAttach"]["error"],确保文件成功上传,避免因上传失败导致后续代码报错
    • 验证文件MIME类型为docx的标准类型,防止非目标文件引发问题
  2. 修复MIME邮件结构

    • 原来的代码错误地将所有MIME内容放到了邮件头($header)中,现在将正文和附件内容移到邮件主体($body)里,mail()函数的第三个参数传递完整的MIME主体,第四个参数传递基础头信息,这是符合邮件协议的正确写法
  3. 移除无效代码

    • 删除了未定义变量$name = basename($file);,避免PHP警告干扰邮件发送
  4. 规范附件MIME类型

    • 使用docx的官方MIME类型application/vnd.openxmlformats-officedocument.wordprocessingml.document,替代通用的application/octet-stream,提升邮件客户端的兼容性

额外建议

  • 在index.html中给表单字段增加required属性,确保用户填写必要信息:
    <input type="text" name="fromName" required>
    <input type="email" name="fromEmail" required>
    <input type="file" name="fileAttach" required accept=".docx">
    
  • 调试时可以开启PHP错误提示,更容易排查问题:在mail.php开头添加error_reporting(E_ALL); ini_set('display_errors', 1);

内容的提问来源于stack exchange,提问作者Ramlal S

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 08:58:07