C#中RDOMessage内嵌图片无法正常显示的问题排查
问题:RDOMessage内嵌图片无法正常显示(Outlook)
我用以下C#代码给RDOMessage添加内嵌图片,尝试在HTMLBody中显示:
_message.BodyFormat = 2; _message.HTMLBody = MailHelper.GetHtmlMessage(MailBody, "utf-8"); if (ImageSource != null && !string.IsNullOrWhiteSpace(ImageName)) { PngBitmapEncoder encoder = new PngBitmapEncoder(); encoder.Frames.Add(BitmapFrame.Create(ImageSource)); string id = "qr-code.png"; int index = _message.HTMLBody.IndexOf("%imageQr%"); if (index >= 0) { string tempDir = TempDirectory.Create(); string tmpFile = Path.Combine(tempDir, id); using (FileStream fileStream = new FileStream(tmpFile, FileMode.Create)) { encoder.Save(fileStream); } RDOAttachment attachment = _message.Attachments.Add(tmpFile, 1, null, ImageName); attachment.ContentID = id; _message.HTMLBody = _message.HTMLBody.Insert(index, $"<img src=\"cid:{id}\">"); _message.HTMLBody = _message.HTMLBody.Replace("%imageQr%", string.Empty); } }
但实际显示只有破损图片占位符(图片前后的内容显示正常)。之前用OOM的类似代码能正常工作,而且OOM里可以把id设为不带后缀的Guid,但RDOMessage这么设置会导致附件无法打开。
补充:发送后的邮件HTMLBody里图片被自动设为32×32px尺寸和额外样式,和原图100×100px不符;未发送时邮件显示图片破损,保存后重新打开也是这样,而发送前HTMLBody格式正确且BodyFormat设为2(HTML格式),为什么没法在Outlook里正常显示?
解决方案
- 修正ContentID格式:RDOMessage对ContentID的要求更严格,必须用
<>包裹,比如<qr-code.png>,同时img标签里的cid也要对应写成cid:<qr-code.png>。OOM会自动处理包裹逻辑,但RDOMessage需要手动添加。 - 替换临时文件为内存流:直接通过内存流添加附件,避免文件IO和路径相关的潜在问题,减少出错概率。
- 显式指定图片尺寸:在img标签里明确设置
width和height属性,比如<img src="cid:<qr-code.png>" width="100" height="100">,防止Outlook自动强制修改图片尺寸。 - 强制设置MAPI属性:仅设置
ContentID属性可能不生效,需直接写入MAPI属性PR_ATTACH_CONTENT_ID(标签值0x3712001F),确保ContentID被正确识别。
修改后的核心代码示例:
if (ImageSource != null && !string.IsNullOrWhiteSpace(ImageName)) { PngBitmapEncoder encoder = new PngBitmapEncoder(); encoder.Frames.Add(BitmapFrame.Create(ImageSource)); string contentId = "<qr-code.png>"; // 带<>包裹的ContentID int index = _message.HTMLBody.IndexOf("%imageQr%"); if (index >= 0) { // 使用内存流直接添加附件,无需临时文件 using (MemoryStream ms = new MemoryStream()) { encoder.Save(ms); ms.Position = 0; RDOAttachment attachment = _message.Attachments.Add(ms, 1, null, ImageName); attachment.ContentID = contentId; // 显式设置MAPI属性,确保ContentID生效 attachment.Fields[0x3712001F] = contentId; } // 替换占位符,同时指定图片原始尺寸 _message.HTMLBody = _message.HTMLBody.Replace("%imageQr%", $"<img src=\"cid:{contentId}\" width=\"100\" height=\"100\">"); } }
内容的提问来源于stack exchange,提问作者Marcel Grüger
相关产品推荐
相关产品推荐

