Outlook VSTO Web窗体中CID引用图片(含签名)显示问题排查
解决Outlook VSTO中签名图片CID无法显示的问题
问题根源
签名图片多为隐藏附件,且部分附件类型无法通过常规SaveAsFile方法保存;同时HTML中的CID可能带尖括号,原有匹配逻辑未兼容该格式,导致匹配失败并抛出数据源缺失的异常。
解决方案步骤
- 修正CID匹配规则,兼容带尖括号的格式
- 遍历所有附件(包括隐藏附件)
- 对
SaveAsFile失败的附件,通过读取MAPI二进制属性手动保存 - 增加本地签名文件夹的兜底查找逻辑
修改后的代码
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
相关产品推荐
相关产品推荐

