附件名称和大小看着正常,下载后PDF阅读器却提示文件损坏。不要先换SMTP服务;先把生成、组装MIME、传输三个环节拆开,找到文件在哪一步改变。
第一步:保存发送前的原始字节
$pdfBytes = $pdf->render(); file_put_contents(BP . '/var/tmp/invoice-test.pdf', $pdfBytes); // 仅在测试环境,完成后删除测试文件
用 file var/tmp/invoice-test.pdf 和 pdfinfo 检查。原始文件打不开,问题在PDF生成或输出缓冲;能打开则继续检查邮件组装。不要把真实客户发票留在可公开访问的pub目录。
最常见的是重复编码
现代Laminas/Mime Part接收原始二进制,并根据encoding生成Base64。如果代码先 base64_encode($pdfBytes),又设置 ENCODING_BASE64,收件人会得到二次编码的文本。确保只编码一次。
$part = new \Laminas\Mime\Part($pdfBytes); $part->type = 'application/pdf'; $part->disposition = \Laminas\Mime\Mime::DISPOSITION_ATTACHMENT; $part->encoding = \Laminas\Mime\Mime::ENCODING_BASE64; $part->filename = 'invoice.pdf';
抓一份.eml对比
测试环境把最终MimeMessage写入var/tmp/test.eml,检查Content-Type、Content-Transfer-Encoding、boundary和文件名。把附件段Base64解码后计算哈希,与原始PDF比较:
sha256sum var/tmp/invoice-test.pdf # 从eml提取附件后 sha256sum var/tmp/invoice-from-eml.pdf
还有两类隐蔽污染
- PHP warning或BOM被写进PDF字节:查看文件头是否以%PDF开头;
- 邮件库升级后仍调用旧的setBodyHtml/setParts组合,导致正文与附件互相覆盖。对照当前Magento版本的TransportBuilder实现,不要照搬旧博客代码。
最后用两个不同邮件服务商和Webmail/客户端各测一次。若.eml中的哈希已正确但只有某一SMTP通道损坏,再检查网关的内容过滤和大小限制。

