PHP/Laravel如何读取PDF/DOC/DOCX内容带样式嵌入邮件正文
实现方案
首先明确核心逻辑:邮件客户端原生不支持直接渲染PDF、DOC、DOCX格式的文件内容,你需要先将目标文档转换为带内联样式的HTML格式,再嵌入到邮件的HTML正文块中,就能实现保留原有样式展示的效果。
通用转换方案
推荐使用服务器端安装LibreOffice的方式实现三类文档的统一转换,兼容性最好,格式保留完整:
- 服务器安装LibreOffice后,可直接调用命令行完成任意格式转HTML:
命令示例:libreoffice --headless --convert-to html --outdir 输出目录路径 源文件路径 - 转换完成后读取生成的HTML文件内容,再使用emogrifier类库将HTML中的CSS样式全部转换为元素内联样式,避免邮件客户端屏蔽头部样式导致格式错乱
- 如果文档中包含图片,转换时需要将图片转成base64编码内嵌到HTML中,避免邮件客户端默认不加载外链图片导致丢失内容。
代码修改示例
你原有的邮件发送逻辑基本不用改,只需要在之前新增文档转HTML的逻辑,将转换得到的HTML内容赋值给$message变量即可,参考代码:
// 新增:文档转HTML逻辑 $filePath = 'path/to/my/file.pdf'; // 支持pdf/doc/docx $ext = strtolower(pathinfo($filePath, PATHINFO_EXTENSION)); $outputDir = 'path/to/temp/dir/'; $htmlPath = $outputDir . pathinfo($filePath, PATHINFO_FILENAME) . '.html'; // 调用LibreOffice转换 exec("libreoffice --headless --convert-to html --outdir {$outputDir} {$filePath} 2>&1", $output, $returnVar); if ($returnVar !== 0) { // 转换失败处理逻辑 return false; } // 读取转换后的HTML内容,处理样式内联 $docHtml = file_get_contents($htmlPath); // 这里可以引入emogrifier处理样式内联,示例省略处理逻辑 $message = $docHtml; // 替换原有的邮件正文内容 // 以下是你原有的发送逻辑,基本不用改动 $uid = md5(uniqid(time())); $file_name = basename($filePath); // header $header = "From: Support <info@support.com>\r\n"; $header .= "Reply-To: info@support.com \r\n"; $header .= "MIME-Version: 1.0\r\n"; $header .= "Content-Type: multipart/mixed; boundary=\"".$uid."\"\r\n\r\n"; // message & attachment $nmessage = "--".$uid."\r\n"; $nmessage .= "Content-type:text/html; charset=\"utf-8\"\r\n"; // 建议把编码换成utf-8避免中文乱码 $nmessage .= "Content-Transfer-Encoding: 7bit\r\n\r\n"; $nmessage .= $message."\r\n\r\n"; // 如果不需要保留附件可以删掉下面附件拼接的逻辑 $content = chunk_split(base64_encode(file_get_contents($filePath))); $nmessage .= "--".$uid."\r\n"; $nmessage .= "Content-Type: application/octet-stream; name=\"".$file_name."\"\r\n"; $nmessage .= "Content-Transfer-Encoding: base64\r\n"; $nmessage .= "Content-Disposition: attachment; filename=\"".$file_name."\"\r\n\r\n"; $nmessage .= $content."\r\n\r\n"; $nmessage .= "--".$uid."--"; if (mail($mailto, $subject, $nmessage, $header)) return true; else return false;
可选分格式处理方案
如果不想装LibreOffice,也可以分格式用PHP库处理:
- DOC/DOCX:使用PhpOffice/PHPWord库读取文档内容,直接调用
$writer = \PhpOffice\PhpWord\IOFactory::createWriter($phpWord, 'HTML');方法输出HTML - PDF:使用Poppler工具集的
pdftohtml命令行转换,或者用本地PDF解析库处理
注意事项
- 务必将所有样式转为内联样式,否则Outlook、QQ邮箱等客户端会丢失格式
- 转换后的HTML建议做精简处理,删除冗余标签,避免邮件体积过大被判定为垃圾邮件
- 编码统一用UTF-8,避免多语言内容乱码
内容的提问来源于stack exchange,提问作者ItWorksOnLocal
相关产品推荐
相关产品推荐

