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

PHP发送带附件邮件异常:附件显示为Base64格式的解决方法

问题原因分析

你遇到的问题核心是邮件的MIME结构没有正确配置——你的代码只对附件做了Base64编码,但没有告诉邮件客户端这是一个独立的附件,也没有将邮件声明为「多部分混合内容」(multipart/mixed),导致客户端把Base64编码后的内容当成了邮件文本的一部分直接显示。

修正方案

要解决这个问题,你需要完善邮件的MIME头结构,明确区分邮件正文和附件部分,具体步骤如下:

  1. 生成随机边界字符串:用来分隔邮件中的不同内容块(正文、附件),避免内容冲突。
  2. 更新邮件头:添加Content-Type: multipart/mixed声明,并指定边界字符串。
  3. 构建完整的邮件内容:包含邮件正文(如果需要)和附件部分,每个部分都要用边界包裹,同时为附件设置正确的MIME属性。

修正后的完整代码

<?php
$from = 'sender@example.com'; // 替换为你的发件人邮箱
$to = 'recipient@example.com'; // 替换为收件人邮箱
$subject = '带附件的测试邮件';

// 1. 生成随机边界字符串(用于分隔邮件内容块)
$boundary = md5(uniqid(time()));

// 2. 构建完整的邮件头
$headers = "From: $from\r\n";
$headers .= "Reply-To: $from\r\n";
$headers .= "MIME-Version: 1.0\r\n";
$headers .= "Content-Type: multipart/mixed; boundary=\"$boundary\"\r\n";
$headers .= "X-Mailer: PHP/" . phpversion() . "\r\n";

// 3. 读取附件内容(保留你原有的文件读取逻辑)
$arquivo = $_FILES['your_file_input']; // 替换为你的文件上传字段名
$file = $arquivo['tmp_name'];
$originalFile = $arquivo['name'];
$file_size = filesize($file);
$handle = fopen($file, "rb");
$anexo = fread($handle, $file_size);
fclose($handle);
$anexo = chunk_split(base64_encode($anexo));

// 4. 构建邮件内容主体
$message = "--$boundary\r\n";
// 邮件正文部分(不需要的话可以直接删除这段)
$message .= "Content-Type: text/plain; charset=UTF-8\r\n";
$message .= "Content-Transfer-Encoding: 7bit\r\n\r\n";
$message .= "这是邮件的正文内容,请查收附件。\r\n\r\n";

// 附件核心部分(关键配置)
$message .= "--$boundary\r\n";
$message .= "Content-Type: application/octet-stream; name=\"$originalFile\"\r\n";
$message .= "Content-Transfer-Encoding: base64\r\n";
$message .= "Content-Disposition: attachment; filename=\"$originalFile\"\r\n\r\n";
$message .= $anexo . "\r\n";

// 结束边界(注意末尾的两个连字符)
$message .= "--$boundary--\r\n";

// 发送邮件
if (mail($to, $subject, $message, $headers)) {
    echo "邮件发送成功!";
} else {
    echo "邮件发送失败!";
}
?>

关键修改点说明

  • MIME结构声明:新增的MIME-Version: 1.0和Content-Type: multipart/mixed; boundary="...",是告诉邮件客户端「这是一个包含多种内容的邮件,用指定边界区分不同部分」。
  • 附件的MIME属性:
    • Content-Type: application/octet-stream:表示这是二进制文件(如果知道具体文件类型,比如图片用image/jpeg、PDF用application/pdf,通用场景用octet-stream即可)。
    • Content-Disposition: attachment; filename="...":明确告诉客户端这是一个附件,并指定显示的文件名。
    • Content-Transfer-Encoding: base64:说明附件内容是Base64编码的,客户端会自动解码还原成正常文件。
  • 边界字符串的正确使用:每个内容块前后都要用--$boundary包裹,最后用--$boundary--结束整个邮件内容,这是MIME多部分邮件的规范要求。

额外注意事项

  • 如果邮件主题包含中文,建议用mb_encode_mimeheader()处理避免乱码:$subject = mb_encode_mimeheader('带附件的测试邮件', 'UTF-8', 'B');
  • 部分服务器的mail()函数可能依赖本地MTA配置,如果发送不稳定,推荐使用PHPMailer等第三方邮件库,配置更灵活且兼容性更好。

内容的提问来源于stack exchange,提问作者Débora Gonçalves

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 10:10:29