使用PHP mail()发送HTML邮件时外部图片无法显示问题
问题原因排查
- HTTP混合内容拦截:你当前图片的
src使用的是http://协议,而Gmail本身是HTTPS站点,主流邮件客户端都会默认拦截HTTPS页面下加载HTTP资源的混合内容请求,哪怕开启了接收所有图片的设置也会阻止这类不安全资源加载。 - 防盗链配置拦截:你的自有服务器大概率配置了图片防盗链规则,会校验请求的Referer字段,邮件客户端加载图片时要么不带Referer,要么Referer字段属于邮件服务域名,不符合你服务器的防盗链校验规则,就会返回403错误导致图片加载失败。
- 邮件内容解析异常:原生
mail()函数在处理多行HTML内容时,若存在换行符格式不规范、特殊字符转义问题,也可能导致img标签被识别错误无法正常加载资源。
解决方法
快速修复方案(外链图片)
- 把图片地址的HTTP协议替换为HTTPS,和你邮件里的跳转链接保持一致:
<img src="https://gestionale.boscarato.eu/Elaborato/images/logo.png" alt="Logo" width="300" height="50">
- 调整你服务器的图片防盗链配置,允许空Referer或者邮件服务相关域名访问该图片资源。
最优稳定方案(内嵌图片)
彻底避免外链图片被拦截的问题,直接把图片转为base64编码内嵌到邮件中,不需要依赖外部资源加载:
// 先读取图片文件转base64 $logo_path = $_SERVER['DOCUMENT_ROOT'].'/Elaborato/images/logo.png'; $logo_type = pathinfo($logo_path, PATHINFO_EXTENSION); $logo_data = file_get_contents($logo_path); $logo_base64 = 'data:image/' . $logo_type . ';base64,' . base64_encode($logo_data); // 然后替换img标签的src $message = ' <html> <head> <title>Password Reset</title> </head> <body> Salve '.$username.', utilizza questo link per resettare la password: <a href="https://gestionale.boscarato.eu/Elaborato/reset/reset_password.php?c='.$operation_code.'">Resetta la tua password </a> <br><br> <img src="'.$logo_base64.'" alt="Logo" width="300" height="50"> <br> Cordiali saluti, <br> <h5>Luca Boscarato [5E] </h5> </body> </html> ';
额外优化建议
- 推荐使用PHPMailer等成熟的邮件发送类库替代原生
mail()函数,对HTML邮件、附件、内嵌资源的兼容性更好,也能减少被判定为垃圾邮件的概率。 - 可以把邮件内容的字符集改为UTF-8,避免多语言内容出现乱码问题,修改headers里的Content-type配置为:
$headers .= 'Content-type: text/html; charset=utf-8' . "\r\n";
内容的提问来源于stack exchange,提问作者Shark44
相关产品推荐
相关产品推荐

