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

Outlook VSTO Web窗体中CID引用图片(含签名)显示问题排查

解决Outlook VSTO中签名图片CID无法显示的问题

问题根源

签名图片多为隐藏附件,且部分附件类型无法通过常规SaveAsFile方法保存;同时HTML中的CID可能带尖括号,原有匹配逻辑未兼容该格式,导致匹配失败并抛出数据源缺失的异常。

解决方案步骤

  1. 修正CID匹配规则,兼容带尖括号的格式
  2. 遍历所有附件(包括隐藏附件)
  3. 对SaveAsFile失败的附件,通过读取MAPI二进制属性手动保存
  4. 增加本地签名文件夹的兜底查找逻辑

修改后的代码

public string EmailBodyToHtml(MailItem mi)
{
    string htmlBody = mi.HTMLBody;
    var result = htmlBody;
    // 匹配带/不带尖括号的CID格式
    Regex reg = new Regex(@"img[^>]*src=[""']cid:(?<cid>(?:<)?[^""'>]+(?:>)?)[""']", RegexOptions.IgnoreCase);
    var matches = reg.Matches(htmlBody);
    
    foreach (Match match in matches)
    {
        string cid = match.Groups["cid"].Value;
        // 统一格式:去掉尖括号并转小写
        cid = cid.Trim('<', '>').ToLower();
        string tempFile = SaveInlineImageToTempFile(mi, cid);
        
        if (!string.IsNullOrEmpty(tempFile))
        {
            // 替换原HTML中的CID(兼容原始格式)
            result = result.Replace($"cid:{match.Groups["cid"].Value}", tempFile);
        }
    }
    return result;
}

private string SaveInlineImageToTempFile(MailItem mi, string cid)
{
    try
    {
        foreach (Attachment item in mi.Attachments)
        {
            PropertyAccessor pa = item.PropertyAccessor;
            // 获取附件的Content ID属性
            string attCid = pa.GetProperty("http://schemas.microsoft.com/mapi/proptag/0x3712001F") as string;
            if (string.IsNullOrEmpty(attCid))
                continue;
            
            // 统一CID格式后匹配
            attCid = attCid.Trim('<', '>').ToLower();
            if (attCid != cid)
                continue;
            
            // 生成唯一临时文件名,避免重名覆盖
            string tempFile = Path.Combine(Path.GetTempPath(), $"{Guid.NewGuid()}{Path.GetExtension(item.FileName)}");
            try
            {
                // 优先尝试常规保存
                item.SaveAsFile(tempFile);
                return tempFile;
            }
            catch
            {
                // SaveAsFile失败时,读取附件二进制数据手动保存
                byte[] attachmentData = pa.GetProperty("http://schemas.microsoft.com/mapi/proptag/0x37010102") as byte[];
                if (attachmentData != null && attachmentData.Length > 0)
                {
                    File.WriteAllBytes(tempFile, attachmentData);
                    return tempFile;
                }
            }
        }
        
        // 附件中未找到时,尝试从本地签名文件夹查找
        string signatureDir = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), @"Microsoft\Signatures");
        if (Directory.Exists(signatureDir))
        {
            string fileName = cid.Split('@')[0];
            var matchedFiles = Directory.GetFiles(signatureDir, fileName, SearchOption.AllDirectories);
            if (matchedFiles.Length > 0)
                return matchedFiles[0];
        }
    }
    catch (Exception e)
    {
        // 可替换为日志记录逻辑
        Console.WriteLine(e.Message);
    }
    return null;
}

关键修改说明

  • CID格式兼容:处理HTML中带尖括号的CID,统一和附件属性的匹配规则
  • 异常兼容:针对OLE嵌入类附件,通过读取MAPI二进制属性绕过SaveAsFile的限制
  • 兜底查找:部分签名图片未嵌入邮件,直接引用本地签名文件夹,增加该路径的查找逻辑

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 05:42:08