C#发送HTML邮件时内嵌base64图片不显示的原因及解决方法
问题原因
该问题确实是主流邮箱服务商的通用安全限制导致:包括Gmail在内的几乎所有商用邮箱,都会默认拦截HTML正文中通过data:image/xxx;base64,格式直接内嵌的图片资源。这类限制主要用于防范超长base64字符串注入恶意代码、隐藏跟踪像素非法收集收件人信息等安全风险,因此哪怕同一段HTML在本地浏览器打开可以正常加载图片,邮件客户端、网页端邮箱都会主动过滤这类内嵌资源,不会自动渲染。
另外你贴的原始代码还有一个配置错误:发件人地址被错误设置成了收件人地址,正常应该填写你用来发信的Gmail账号地址,否则也可能触发邮件服务商的拦截规则。
解决方案
不要直接把base64字符串拼接到img标签的src属性中,使用.NET类库自带的LinkedResource实现标准的邮件内嵌图片方案,这种方式符合邮件MIME规范,所有主流邮箱都能正常识别,不会触发安全拦截。
具体实现逻辑:
- 将HTML中img标签的src属性替换为
cid:自定义内容ID格式的占位符,其中内容ID可以自行定义,保证唯一即可 - 创建
AlternateView对象承载HTML格式的邮件正文 - 将base64字符串转换为内存流,通过
LinkedResource加载图片流,设置和HTML占位符一致的ContentID - 将图片资源绑定到HTML视图,再把视图添加到邮件对象的
AlternateViews集合中
修正后的可运行代码示例:
using System.Net.Mail; using System.Net.Mime; using System.IO; using System.Text; public static void SendMail(string sendTo, string base64PngContent, Encoding enCode) { string senderEmail = "mail@gmail.com"; // 注意:Gmail需开启两步验证后生成应用专用密码,不能直接使用账号登录密码 string senderPassword = "your_gmail_app_password"; using MailMessage mail = new MailMessage(); SmtpClient smtpServer = new SmtpClient(); // 修正原代码发件人配置错误 mail.From = new MailAddress(senderEmail); mail.To.Add(sendTo); mail.Subject = "邮件主题"; mail.BodyEncoding = enCode; mail.IsBodyHtml = true; // HTML正文,img标签通过cid引用内嵌资源 string htmlBody = "<img src='cid:embedded_png_001' />"; // 创建HTML格式的邮件替代视图 AlternateView htmlView = AlternateView.CreateAlternateViewFromString(htmlBody, enCode, MediaTypeNames.Text.Html); // 加载base64图片为内嵌资源 byte[] imgBytes = Convert.FromBase64String(base64PngContent); using MemoryStream imgStream = new MemoryStream(imgBytes); LinkedResource embeddedImg = new LinkedResource(imgStream, "image/png") { ContentId = "embedded_png_001", // 和HTML中cid后的内容保持一致 TransferEncoding = TransferEncoding.Base64 }; htmlView.LinkedResources.Add(embeddedImg); mail.AlternateViews.Add(htmlView); // SMTP服务配置 smtpServer.UseDefaultCredentials = false; smtpServer.Credentials = new NetworkCredential(senderEmail, senderPassword); smtpServer.EnableSsl = true; smtpServer.Port = 587; smtpServer.Host = "smtp.gmail.com"; smtpServer.Send(mail); }
补充注意事项
- Gmail从2022年起就已经关闭了“低安全性应用访问”入口,直接使用账号密码登录SMTP会报错,必须先给账号开启两步验证,再生成16位的应用专用密码填入代码的密码字段
- 如果需要内嵌多张图片,为每个图片资源分配唯一的ContentID,和HTML里的cid一一对应即可
- 不要将图片作为普通附件添加后尝试引用,这种方式大部分邮箱会直接把图片显示在附件栏,不会内嵌到正文对应位置
内容的提问来源于stack exchange,提问作者Amen
相关产品推荐
相关产品推荐

