You need to enable JavaScript to run this app. PHP Mail如何同时发送Base64格式邮件与附件?
优惠活动
大模型
产品
解决方案
定价
更多

PHP Mail如何同时发送Base64格式邮件与附件?

问题根因

你之前的发送逻辑是把整封邮件全部做单段Base64编码后投递,没有遵循标准邮件的MIME格式规则。*当邮件需要同时装下HTML表单内容、独立附件两类不同的内容块时,单段编码会抹掉MIME结构的识别标记,导致邮件服务器根本分不清哪部分是正文、哪部分是附件,自然没法正常投递。

标准Multipart实现步骤
  • 第一步:生成独立的块边界标识
    边界是用来隔开邮件不同内容块的唯一随机字符串,长度建议16位以上无规律字符,绝对不能在HTML内容、附件的实际字节内容里出现,否则会提前触发块分隔,导致内容错位。
  • 第二步:搭建分层MIME结构
    整封邮件最外层统一声明为multipart/mixed类型,用来容纳两个大类的内容:
    • 第一类是正文区域:如果要兼容不支持HTML的老旧邮箱,正文区内部再嵌套一层multipart/alternative,分别存放纯文本兜底内容、经Base64编码的大体积HTML表单内容
    • 后续每一块对应一份独立附件,每个块都要单独标注自己的MIME类型、编码方式、附件文件名
  • 第三步:按规范拼内容块
    所有块的分隔必须严格按邮件协议要求来:
    • 块之间用--边界字符串作为分隔标记,块内先写对应内容的头部声明(类型、编码方式、文件名等),空一行之后再放实际内容
    • 整封邮件的最后,必须用--边界字符串--作为结束标记,不能漏写
  • 第四步:对接PHP mail()函数
    所有MIME版本声明、外层Content-Type声明、发件人信息这类内容,统一作为第四个参数(额外头部)传给mail()函数;所有用边界拆分的正文、附件内容,统一作为第三个参数(邮件正文)传入,绝对不能和头部声明混在同一段。
最小可运行代码示例
// 生成两个不重复的随机边界
$mixed_boundary = "-----=Mail_Mixed_" . bin2hex(random_bytes(8));
$alt_boundary = "-----=Mail_Alt_" . bin2hex(random_bytes(8));

// 组装邮件头部
$headers = "From: 发件人 <noreply@yourdomain.com>\r\n";
$headers .= "MIME-Version: 1.0\r\n";
$headers .= "Content-Type: multipart/mixed; boundary=\"{$mixed_boundary}\"\r\n";

// 组装正文部分
$body = "--{$mixed_boundary}\r\n";
$body .= "Content-Type: multipart/alternative; boundary=\"{$alt_boundary}\"\r\n\r\n";
// 纯文本兜底内容
$body .= "--{$alt_boundary}\r\n";
$body .= "Content-Type: text/plain; charset=utf-8\r\n";
$body .= "Content-Transfer-Encoding: 7bit\r\n\r\n";
$body .= "这是纯文本兜底内容,不支持HTML的邮箱会展示这段\r\n\r\n";
// Base64编码的大体积HTML表单内容
$encoded_html = base64_encode($你的大体积HTML表单原始内容);
$body .= "--{$alt_boundary}\r\n";
$body .= "Content-Type: text/html; charset=utf-8\r\n";
$body .= "Content-Transfer-Encoding: base64\r\n\r\n";
$body .= chunk_split($encoded_html) . "\r\n\r\n";
// 正文区结束
$body .= "--{$alt_boundary}--\r\n";

// 组装附件块
$encoded_attachment = base64_encode(file_get_contents($附件本地路径));
$body .= "--{$mixed_boundary}\r\n";
$body .= "Content-Type: 附件对应MIME类型\r\n";
$body .= "Content-Transfer-Encoding: base64\r\n";
$body .= "Content-Disposition: attachment; filename=\"附件文件名.ext\"\r\n\r\n";
$body .= chunk_split($encoded_attachment) . "\r\n";
// 整封邮件结束
$body .= "--{$mixed_boundary}--\r\n";

// 执行发送
mail("收件人邮箱地址", "邮件主题", $body, $headers);
高频踩坑提醒
  • Base64编码的内容必须用chunk_split()按76字符拆分换行,这是RFC2045协议的强制要求,否则过长的编码行会被邮件服务器截断,导致内容损坏
  • 所有头部声明、块之间的换行必须用\r\n,不能单独用\n,否则会被服务器判定为格式非法的垃圾邮件
  • 边界字符串在Content-Type声明里必须用双引号包裹,部分严格的邮箱服务会因为没加引号直接拒绝接收
  • 之前遇到的发送故障本质就是把整封邮件都做了Base64编码,导致MIME声明被编码成了普通内容,服务器识别不到结构——实现时只需要把对应的HTML块单独做Base64编码,保留头部、边界的明文结构即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.11.08 19:45:01