PHP mail()函数发件异常求助:特定环境下邮件显示破损
问题分析与修复方案
核心问题确认
你推测的方向是对的:X-PHP-Originating-Script头部是触发问题的关键因素,但本质是邮件头的结构被破坏了。
ESET插入X-EsetId头部后留下了空行,而PHP原生mail()函数会自动在你自定义的headers之后追加X-PHP-Originating-Script,这就把原本应该连续的MIME核心头(MIME-Version、Content-type)推到了空行之后。根据邮件协议RFC标准,空行是邮件头和正文的分隔符,客户端会把空行后的所有内容当成纯文本正文,所以HTML标签直接暴露出来,邮件显示破损。
Laravel不发送这个头部,所以MIME头始终保持连续,不会被客户端误解析。
修复步骤
1. 禁用PHP自动添加X-PHP-Originating-Script
这是最直接的解决方法,有两种实现方式:
- 全局配置:修改
php.ini文件,设置mail.add_x_header = Off,修改后重启PHP服务生效。 - 脚本临时配置:在调用
mail()函数之前添加一行代码,仅对当前脚本生效:ini_set('mail.add_x_header', 'Off');
2. 修正邮件头的换行格式
邮件协议要求头部换行必须使用\r\n(CRLF),你当前脚本用的是\n(LF),这会增加解析异常的概率,修改headers的换行符:
$headers = "MIME-Version: 1.0" . "\r\n"; $headers .= "Content-type:text/html;charset=UTF-8" . "\r\n"; $headers .= 'From: <email.address@example.com>' . "\r\n";
3. 可选:使用MIME多部分结构(支持纯文本备选)
如果你需要同时发送HTML和纯文本版本(对应你定义的$emailAltBody),手动构造多部分MIME结构可以提升邮件的兼容性,即使头信息出现小问题,客户端也能正确解析:
$subject = mb_encode_mimeheader('Subject text'); $emailAltBody = "..."; // 你的纯文本内容 $boundary = md5(time()); // 生成唯一的MIME边界 // 构造邮件头 $headers = "MIME-Version: 1.0" . "\r\n"; $headers .= "Content-Type: multipart/alternative; boundary=\"$boundary\"" . "\r\n"; $headers .= 'From: <email.address@example.com>' . "\r\n"; // 构造邮件内容 $emailContent = "--$boundary\r\n"; $emailContent .= "Content-Type: text/plain; charset=UTF-8\r\n\r\n"; $emailContent .= $emailAltBody . "\r\n"; $emailContent .= "--$boundary\r\n"; $emailContent .= "Content-Type: text/html; charset=UTF-8\r\n\r\n"; $emailContent .= '<!DOCTYPE html> <html lang="cs"> ... </html>' . "\r\n"; $emailContent .= "--$boundary--"; // 发送邮件 $result = mail("email.address@example.com", $subject, $emailContent, $headers);
内容的提问来源于stack exchange,提问作者Filip
相关产品推荐
相关产品推荐

