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

使用PHP Mailparse如何区分邮件附件图片与内嵌图片?

解决方案

核心判断依据

邮件协议中两类图片的MIME属性存在明确差异,你可以通过以下三个维度组合判断,准确率可以覆盖绝大多数合规邮件场景:

  • 优先读取每个邮件部分的Content-Disposition头:值为attachment的是用户主动上传的附件,值为inline的大概率是正文内嵌图片
  • 补充校验Content-ID(简称CID)字段:所有被正文HTML引用的内嵌图片都会带有CID,且会在HTML的img标签的src属性中以cid:xxx的形式被引用,你可以把所有正文中出现的CID全部提取出来,只要某张图片的CID在这个列表里,就判定为内嵌图片
  • 兜底校验规则:极少数不规范邮件可能缺失Content-Disposition头,此时如果图片的文件名是类似logo.png、signature.jpg这类通用签名/装饰图命名,且没有符合用户上传附件的常规命名特征,也可以辅助判定为内嵌资源,规则可以根据你的业务场景灵活调整

基于PHP Mailparse的实现步骤

  1. 先用mailparse_msg_parse_file或者mailparse_msg_parse解析原始邮件内容,拿到邮件的MIME结构
  2. 遍历所有邮件部分,先提取所有text/html类型的正文内容,用正则匹配出所有src="cid:xxx"里的CID值,存到$inline_cids数组中
  3. 再次遍历所有图片类型的邮件部分,按规则筛选:
    • 若该部分的Content-Disposition头值为attachment,直接保留为用户上传附件
    • 若Content-Disposition为inline或者没有该头,读取它的Content-ID,去掉头尾的尖括号后判断是否在$inline_cids数组里,是的话判定为内嵌图片直接丢弃,不在的话保留为附件
  4. 注意处理多部分嵌套的情况,比如mixed、alternative、related类型的MIME部分,要递归遍历所有子部分,不要漏掉嵌套的附件

核心代码片段示例

// 初始化解析器,加载原始邮件内容
$mime = mailparse_msg_create();
mailparse_msg_parse($mime, $raw_email_content);
$structure = mailparse_msg_get_structure($mime);

// 第一步:提取正文中所有引用的内嵌图片CID
$inline_cids = [];
foreach ($structure as $part_id) {
    $part = mailparse_msg_get_part($mime, $part_id);
    $part_data = mailparse_msg_get_part_data($part);
    if ($part_data['content-type'] == 'text/html') {
        $body = mailparse_msg_extract_part($mime, $part_id, $raw_email_content);
        // 正则匹配所有cid引用
        preg_match_all('/src=["\']cid:([^"\']+)["\']/i', $body, $matches);
        if (!empty($matches[1])) {
            $inline_cids = array_merge($inline_cids, array_map('trim', $matches[1]));
        }
    }
}

// 第二步:筛选保留用户主动上传的附件图片
$attachments = [];
foreach ($structure as $part_id) {
    $part = mailparse_msg_get_part($mime, $part_id);
    $part_data = mailparse_msg_get_part_data($part);
    // 仅处理图片类型的部分
    if (str_starts_with($part_data['content-type'], 'image/')) {
        $disposition = $part_data['content-disposition'] ?? '';
        $cid = trim($part_data['content-id'] ?? '', '<> ');
        // 满足以下条件判定为用户上传附件,予以保留
        if ($disposition == 'attachment' || !in_array($cid, $inline_cids)) {
            $attachments[] = [
                'name' => $part_data['disposition-filename'] ?? $part_data['content-name'] ?? 'untitled',
                'type' => $part_data['content-type'],
                'content' => mailparse_msg_extract_part($mime, $part_id, $raw_email_content)
            ];
        }
    }
}
// 释放解析资源
mailparse_msg_free($mime);

注:代码中的str_starts_with是PHP8+内置函数,如果使用更低PHP版本,可以替换为substr($part_data['content-type'], 0, 6) === 'image/'实现同等效果

异常场景兼容

  • 纯文本邮件不存在内嵌图片,所有图片附件都可以直接全部保留
  • 少数老旧邮件客户端生成的邮件可能存在头信息填写不规范的情况,建议同时开启Content-Disposition和CID匹配双重校验,误判率可控制在1%以内

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 08:15:04