PHP发送邮件附件时生成ATT00001.htm额外文件如何解决?
解决PHP自定义邮件函数生成ATT00001.htm附件的问题
嘿,我之前也踩过这个ATT00001.htm的坑!这个诡异的附件通常是邮件客户端解析MIME多部分内容失败导致的,大概率和你设置的boundary、换行符或者邮件结构有关。结合你给出的代码片段,我给你几个排查和修复的方向:
1. 换掉PHP_EOL,强制用标准MIME换行符\r\n
MIME协议严格要求用CRLF(\r\n)作为换行符,但PHP_EOL会根据服务器系统变化(Linux是\n,Windows是\r\n),如果用了单一的\n,邮件客户端很可能会把未正确分隔的内容当成附件。
把你的代码里的:
$eol = PHP_EOL;
改成:
$eol = "\r\n";
2. 检查MIME多部分结构的完整性
手动拼接MIME邮件最容易出错的就是boundary的使用和部分分隔。你需要确保:
- 邮件头里的
Content-Type正确声明了boundary,格式是multipart/mixed; boundary="你的分隔符" - 每个内容块(正文、附件)都以
--$separator开头,最后以--$separator--结尾(注意结尾的两个短横线) - 每个MIME块的头部(比如Content-Type、Content-Disposition)和内容之间必须有两个换行符(
$eol.$eol)
给你一个正确的结构示例,你可以对照调整你的代码:
// 构建邮件头 $headers = "From: {$from}{$eol}"; $headers .= "MIME-Version: 1.0{$eol}"; $headers .= "Content-Type: multipart/mixed; boundary=\"{$separator}\"{$eol}"; $headers .= "This is a MIME encoded message.{$eol}"; // 正文部分 $body = "--{$separator}{$eol}"; $body .= "Content-Type: text/plain; charset=\"UTF-8\"{$eol}"; $body .= "Content-Transfer-Encoding: 8bit{$eol}{$eol}"; $body .= "这是邮件的正文内容,你可以换成自己的文本{$eol}{$eol}"; // CSV附件部分 $csv_content = file_get_contents($path . $filename); $body .= "--{$separator}{$eol}"; $body .= "Content-Type: text/csv; charset=\"UTF-8\"{$eol}"; $body .= "Content-Disposition: attachment; filename=\"{$filename}\"{$eol}"; $body .= "Content-Transfer-Encoding: base64{$eol}{$eol}"; $body .= chunk_split(base64_encode($csv_content)) . $eol; // 结束边界(必须加两个短横线) $body .= "--{$separator}--{$eol}";
3. 排查多余的空白字符
有时候代码里不经意的空格、换行,甚至是调试用的echo/print输出,都会被混入邮件内容中,导致客户端解析混乱。检查:
- 你的
$path和$filename变量有没有多余的空格 - 代码中有没有在邮件内容拼接之外的输出语句
- 文件开头/结尾有没有多余的空行(比如PHP标签前后的空白)
4. 偷懒但有效的方案:用成熟的邮件库
手动拼接MIME真的很容易踩坑,不如直接用PHPMailer或者SwiftMailer这类库,它们会自动处理boundary、编码、换行符这些细节,省心太多。举个PHPMailer的简单例子:
require 'PHPMailer/PHPMailer.php'; require 'PHPMailer/SMTP.php'; $mail = new PHPMailer\PHPMailer\PHPMailer(); $mail->isSMTP(); $mail->Host = '你的SMTP服务器地址'; // 比如smtp.gmail.com $mail->SMTPAuth = true; $mail->Username = '你的邮箱账号'; $mail->Password = '你的邮箱密码/授权码'; $mail->SMTPSecure = 'tls'; $mail->Port = 587; // 设置收件人、发件人 $mail->setFrom($from); $mail->addAddress($to); $mail->Subject = $subject; // 添加正文和附件 $mail->Body = '这是邮件正文'; $mail->addAttachment($path . $filename, $filename); // 第二个参数是显示的文件名 // 发送邮件 if (!$mail->send()) { error_log('邮件发送失败: ' . $mail->ErrorInfo); } else { echo '邮件发送成功!'; }
先从换行符和MIME结构开始排查,这两个是最常见的原因。如果还是不行,把完整的邮件头和内容打印出来看看,就能很快找到哪里错了。
内容的提问来源于stack exchange,提问作者Eliott Bence
相关产品推荐
相关产品推荐

