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

如何用PHP原生mail()函数发送带纯文本、HTML及附件的邮件?

原生PHP mail()函数实现纯文本+HTML+附件的邮件发送

问题诊断

你的代码核心问题有两个:

  • 纯文本的Content-Type字符集参数错误:写成了charset="charset=UTF-8",多余的charset=会导致邮件客户端无法正确识别纯文本类型,进而错误显示HTML内容
  • 换行符不统一:MIME协议要求所有头信息和内容分隔使用\r\n,你代码中混用了\n和\r\n,破坏了MIME结构的解析规则

修正后的完整代码

$to = 'xyz@xyz.com';
$subject = 'my test subject';

$htmlMessage = 'this <i>is</i> html';
$plaintextMessage = 'this is plain text';

$attachments = [
    [
        'path' => 'download/',
        'file' => 'test1.pdf'
    ],
    [
        'path' => 'download/',
        'file' => 'test2.pdf'
    ],
];

// 生成唯一的MIME边界符
$mimeBoundary = md5((string) time());
$mimeBoundaryMixed = $mimeBoundary . '_mixed';
$mimeBoundaryAlternative = $mimeBoundary . '_alternative';

// 构建邮件头,统一使用\r\n换行
$headers  = "MIME-Version: 1.0\r\n";
$headers .= "Content-Type: multipart/mixed; boundary=\"$mimeBoundaryMixed\"\r\n";
$headers .= "Content-Transfer-Encoding: 7bit\r\n";

// 构建邮件主体
$body  = "This is a multi-part message in MIME format.\r\n\r\n";

// 第一部分:替代内容(纯文本+HTML)
$body .= "--$mimeBoundaryMixed\r\n";
$body .= "Content-Type: multipart/alternative; boundary=\"$mimeBoundaryAlternative\"\r\n\r\n";

// 纯文本版本
$body .= "--$mimeBoundaryAlternative\r\n";
$body .= "Content-Type: text/plain; charset=\"UTF-8\"\r\n";
$body .= "Content-Transfer-Encoding: 7bit\r\n\r\n";
$body .= $plaintextMessage . "\r\n\r\n";

// HTML版本
if (!empty($htmlMessage)) {
    $body .= "--$mimeBoundaryAlternative\r\n";
    $body .= "Content-Type: text/html; charset=\"UTF-8\"\r\n";
    $body .= "Content-Transfer-Encoding: 7bit\r\n\r\n";
    $body .= $htmlMessage . "\r\n\r\n";
}
// 结束替代内容边界
$body .= "--$mimeBoundaryAlternative--\r\n\r\n";

// 处理附件
if (!empty($attachments)) {
    foreach ($attachments as $attachment) {
        $filePath = $attachment['path'] . $attachment['file'];
        if (file_exists($filePath)) {
            $fileSize = filesize($filePath);
            $fileHandle = fopen($filePath, "rb");
            $fileContent = fread($fileHandle, $fileSize);
            fclose($fileHandle);
            $fileContent = chunk_split(base64_encode($fileContent));

            $body .= "--$mimeBoundaryMixed\r\n";
            $body .= "Content-Type: application/octet-stream; name=\"{$attachment['file']}\"\r\n";
            $body .= "Content-Transfer-Encoding: base64\r\n";
            $body .= "Content-Disposition: attachment; filename=\"{$attachment['file']}\"\r\n\r\n";
            $body .= $fileContent . "\r\n\r\n";
        }
    }
}

// 结束外层MIME边界
$body .= "--$mimeBoundaryMixed--\r\n";

// 发送邮件
mail($to, $subject, $body, $headers);

核心原理说明

  1. MIME层级结构

    • 最外层使用multipart/mixed:用于同时包含"替代内容"和"附件"两种不同用途的内容
    • 内层嵌套multipart/alternative:专门用于存放同一内容的不同格式版本(纯文本和HTML),邮件客户端会根据自身支持能力自动选择显示哪一个(支持HTML的客户端优先显示HTML,纯文本客户端显示纯文本)
  2. 边界符规则

    • 每个MIME部分用唯一的边界符分隔,边界符前必须加--,结束边界符需要在末尾再加--
    • 边界符必须唯一,避免和邮件内容冲突,这里用md5(time())生成唯一值
  3. 编码与格式规范

    • 所有头信息和内容之间必须用\r\n\r\n分隔(空行)
    • 附件使用base64编码,确保二进制文件能被正确传输
    • 字符集统一设置为UTF-8,避免中文等非ASCII字符乱码

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 12:35:26