
邮件客户端(如Gmail)会自动折行过长的HTML行,导致URL在空格处被截断并编码为 %20;根本解决方法是控制HTML行长度或启用Base64编码传输。
邮件客户端(如gmail)会自动折行过长的html行,导致url在空格处被截断并编码为 `%20`;根本解决方法是控制html行长度或启用base64编码传输。
在PHP中通过 mail() 函数发送HTML邮件时,看似无误的URL(如 'http://rfp.wabtec.com/production/apps/documentControl')点击后却变成 http://rfp.wabtec.com/production/apps/documen%20tControl,其根本原因并非代码中存在空格,而是邮件传输过程中的自动行折叠(line folding)机制触发了URL损坏。
? 问题根源:MIME行长度限制与自动折行
根据RFC 2822规范,纯文本邮件头和正文的每行不应超过998字符(通常实践中以76–1024字符为安全阈值)。当HTML字符串过长(尤其是单行拼接的
例如,原始URL:
http://rfp.wabtec.com/production/apps/documentControl
若被截断为:
http://rfp.wabtec.com/production/apps/documen tControl
则客户端可能将其解析为 documen
✅ 推荐解决方案(二选一)
✅ 方案一:显式换行 + 短行HTML(推荐,简单有效)
将 $email_body 字符串改写为多行字面量(使用定界符或自然换行),确保每行HTML不超过900字符,并避免长URL跨行:
$email_body =
BODY {font-family: Arial, Helvetica, sans-serif, Verdana; font-size: 14px;}
.heading {font-family: Arial, Helvetica, sans-serif, Verdana; font-size: 16px; font-weight: bold;}
th {text-align: left; padding-right: 10px; padding-bottom: 5px;}
td {padding-bottom: 5px;}
<div>Hello</div><br><div>$body_one</div><br>
| File: | $name |
|---|---|
| Type: | $type |
| Description: | $description |
HTML;
✅ 优势:无需修改邮件头,兼容所有PHP环境;✅ 关键点:URL必须完整位于单行内(如上例中 行未被折断)。
✅ 方案二:启用 Base64 编码(更健壮,适合复杂HTML)
在 $email_headers 中添加 Content-Transfer-Encoding: base64,并对 $email_body 进行Base64编码:
// 修改 headers
$email_headers = "MIME-Version: 1.0\r\n" .
"Content-Type: text/html; charset=utf-8\r\n" .
"Content-Transfer-Encoding: base64\r\n" .
"From: RFPC Document System \r\n" .
"Reply-To: RFPC Document System \r\n";
// 编码 body(注意:需用 chunk_split 保证每行 ≤76 字符)
$email_body_encoded = chunk_split(base64_encode($email_body), 76, "\r\n");
$email_send = @mail($email_to, $email_subject, $email_body_encoded, $email_headers);
⚠️ 注意:charset 应统一为 utf-8(而非 iso-8859-1),避免中文乱码;chunk_split() 是必需步骤,否则Base64块超长仍会触发折行。
? 验证与调试建议
- 在发送前 echo htmlspecialchars($email_body) 查看实际HTML结构,确认URL是否跨行;
- 使用 Mail-Tester.com 检查邮件原始源码,定位被折行的具体位置;
- 测试时优先用Gmail账户接收,因其折行策略最严格,可暴露潜在问题。
✅ 总结
%20 出现在URL中不是PHP拼接错误,而是邮件协议层的自动折行副作用。最直接有效的修复方式是重构HTML字符串为短行格式,确保所有URL独占一行;若邮件内容复杂、含大量样式或脚本,建议升级至 Content-Transfer-Encoding: base64 并配合 chunk_split(),从协议层面杜绝折行风险。











