You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PHP应用中HTML邮件渲染异常问题求助

PHP HTML邮件渲染异常修复方案

问题核心原因

原代码存在以下关键错误:

  • HTML邮件类型判断逻辑错误
  • 未对base64/quoted-printable编码的邮件内容解码
  • 错误将邮件内容包裹在<style>标签中导致代码暴露
  • 未处理cid:格式的图片资源路径

分步修复方案

1. 修复HTML邮件类型判断

IMAP协议中,type=0表示TEXT类型,HTML属于TEXT的子类型,修正判断逻辑:

$isHTML = false;
if ($structure->type == 0) {
    // 处理多部分邮件
    if (isset($structure->parts)) {
        foreach ($structure->parts as $index => $part) {
            if (strtoupper($part->subtype) == 'HTML') {
                $isHTML = true;
                break;
            }
        }
    }
    // 处理单部分HTML邮件
    if (strtoupper($structure->subtype) == 'HTML') {
        $isHTML = true;
    }
}

2. 添加邮件内容解码函数

处理常见的邮件编码格式:

function decodeEmailContent($content, $encoding) {
    switch(strtoupper($encoding)) {
        case 'BASE64':
            return base64_decode($content);
        case 'QUOTED-PRINTABLE':
            return quoted_printable_decode($content);
        default:
            return $content;
    }
}

3. 正确获取并解码HTML内容

适配单/多部分邮件结构,解码后获取真实内容:

$messageBody = '';
if ($isHTML) {
    if ($structure->type == 0 && isset($structure->parts)) {
        foreach ($structure->parts as $index => $part) {
            if (strtoupper($part->subtype) == 'HTML') {
                $messageBody = imap_fetchbody($mailbox, $i, $index+1); // IMAP部分索引从1开始
                $messageBody = decodeEmailContent($messageBody, $part->encoding);
                break;
            }
        }
    } else {
        $messageBody = imap_fetchbody($mailbox, $i, 1);
        $messageBody = decodeEmailContent($messageBody, $structure->encoding);
    }
} else {
    $messageBody = imap_fetchbody($mailbox, $i, 1);
    $messageBody = decodeEmailContent($messageBody, $structure->encoding);
}

4. 修复HTML渲染与图片路径问题

移除错误的<style>包裹,处理cid:图片(需额外保存附件到服务器生成可访问URL):

if ($isHTML) {
    // 替换cid图片为可访问路径(示例:需实现附件匹配逻辑)
    $messageBody = preg_replace('/cid:([a-zA-Z0-9\-_]+)/', function($matches) use ($mailbox, $i) {
        // 实际项目中需遍历邮件附件,根据cid匹配并生成临时访问URL
        return $matches[0];
    }, $messageBody);

    // 直接渲染HTML内容,若用Mustache需用{{{messageBody}}}(不转义HTML)
    echo $messageBody;
} else {
    echo nl2br(htmlspecialchars($messageBody));
}

完整修正代码

<?php
use Mustache_Engine;
use Mustache_Loader_FilesystemLoader;
require_once '/home/dashboard/vendor/autoload.php';

function decodeEmailContent($content, $encoding) {
    switch(strtoupper($encoding)) {
        case 'BASE64':
            return base64_decode($content);
        case 'QUOTED-PRINTABLE':
            return quoted_printable_decode($content);
        default:
            return $content;
    }
}

$server = '{test severy:993/imap/ssl}INBOX';
$username = 'XXX@gmail';
$password = 'password';

$mailbox = imap_open($server, $username, $password) or die('Cannot connect to the server: ' . imap_last_error());

$totalMessages = imap_num_msg($mailbox);

for ($i = 1; $i <= $totalMessages; $i++) {
    $header = imap_headerinfo($mailbox, $i);
    $structure = imap_fetchstructure($mailbox, $i);
    $isHTML = false;
    $messageBody = '';

    // 判断HTML邮件类型
    if ($structure->type == 0) {
        if (isset($structure->parts)) {
            foreach ($structure->parts as $index => $part) {
                if (strtoupper($part->subtype) == 'HTML') {
                    $isHTML = true;
                    $messageBody = imap_fetchbody($mailbox, $i, $index+1);
                    $messageBody = decodeEmailContent($messageBody, $part->encoding);
                    break;
                }
            }
        }
        if (strtoupper($structure->subtype) == 'HTML' && !$isHTML) {
            $isHTML = true;
            $messageBody = imap_fetchbody($mailbox, $i, 1);
            $messageBody = decodeEmailContent($messageBody, $structure->encoding);
        }
    }

    // 未找到HTML则获取纯文本
    if (!$isHTML) {
        $messageBody = imap_fetchbody($mailbox, $i, 1);
        $messageBody = decodeEmailContent($messageBody, $structure->encoding);
    }

    echo '<strong>From:</strong> ' . $header->fromaddress . '<br>';
    echo '<strong>Subject:</strong> ' . htmlspecialchars($header->subject) . '<br>';
    echo '<strong>Date:</strong> ' . date('Y-m-d H:i:s', strtotime($header->date)) . '<br>';

    echo '<strong>Message:</strong><br>';
    if ($isHTML) {
        // 处理cid图片(需补充附件保存逻辑)
        $messageBody = preg_replace('/cid:([a-zA-Z0-9\-_]+)/', function($matches) use ($mailbox, $i) {
            // 示例占位,实际需匹配附件生成URL
            return $matches[0];
        }, $messageBody);
        echo $messageBody;
    } else {
        echo nl2br(htmlspecialchars($messageBody));
    }

    echo '<hr>';
}

imap_close($mailbox);
?>

额外说明

  • 图片加载:cid:前缀指向邮件附件,需遍历邮件附件匹配cid,将附件保存到服务器后替换为可访问URL才能正常显示。
  • Mustache模板使用:若需用模板渲染,需在模板中使用{{{messageBody}}}(三个大括号表示不转义HTML),而非错误的style标签包裹。

内容的提问来源于stack exchange,提问作者Sargin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 21:47:05