在 MailMessage 中添加附件 base64 图像并在 html 正文中读取

Posted

技术标签:

【中文标题】在 MailMessage 中添加附件 base64 图像并在 html 正文中读取【英文标题】:Add Attachment base64 image in MailMessage and read it in html body 【发布时间】:2017-01-17 08:42:05 【问题描述】:

目前我必须使用MailMessageSmtpClient 发送电子邮件,但我需要发送MailAddress 正文中当前位于base64 string 中的图片。

我知道有必要把它放在Attachment中,但是我不知道如何把base64放在MailMessage类中然后阅读它以便在正文中可视化图像电子邮件。我没有 url 图片路径。

【问题讨论】:

Send inline image in email的可能重复 【参考方案1】:

将正文 html 转换为 AlternateView 的完整方法

bodyHtml 示例(您可以将其传递到下面的 MailMessage 代码块中)

<p>example</p>
<p><img src=\ "data:image/jpeg;base64,---base64string---"></p>
<p>example</p>
<p><img src=\ "data:image/png;base64,---base64string---"></p>
<p>something</p>

使用此方法,您可以通过许多 ESP(gmail、outlook 等)可视化多个图像

private static AlternateView ContentToAlternateView(string content)
    
        var imgCount = 0;
        List<LinkedResource> resourceCollection = new List<LinkedResource>();
        foreach (Match m in Regex.Matches(content, "<img(?<value>.*?)>"))
        
            imgCount++;
            var imgContent = m.Groups["value"].Value;
            string type = Regex.Match(imgContent, ":(?<type>.*?);base64,").Groups["type"].Value;
            string base64 = Regex.Match(imgContent, "base64,(?<base64>.*?)\"").Groups["base64"].Value;
            if (String.IsNullOrEmpty(type) || String.IsNullOrEmpty(base64))
            
                //ignore replacement when match normal <img> tag
                continue;
            
            var replacement = " src=\"cid:" + imgCount + "\"";
            content = content.Replace(imgContent, replacement);
            var tempResource = new LinkedResource(Base64ToImageStream(base64), new ContentType(type))
            
                ContentId = imgCount.ToString()
            ;
            resourceCollection.Add(tempResource);
        

        AlternateView alternateView = AlternateView.CreateAlternateViewFromString(content, null, MediaTypeNames.Text.Html);
        foreach (var item in resourceCollection)
        
            alternateView.LinkedResources.Add(item);
        

        return alternateView;
    

将 Base64 转换为流:

public static Stream Base64ToImageStream(string base64String)
    
        byte[] imageBytes = Convert.FromBase64String(base64String);
        MemoryStream ms = new MemoryStream(imageBytes, 0, imageBytes.Length);
        return ms;
    

设置 MailMessage :

MailMessage mail = new MailMessage();
mail.IsBodyHtml = true;                   
AlternateView alterView = ContentToAlternateView(bodyHtml);
mail.AlternateViews.Add(alterView);
//more settings
//...
//////////////
SmtpClient smtp = new SmtpClient(Host, Port)  EnableSsl = false ;
smtp.Send(mail);

【讨论】:

谢谢!很好的答案。 效果很好。但是应用在 img 标签上的类属性和内联样式将被删除,知道吗?【参考方案2】:

将图片嵌入到您的邮件中:(其与在邮件中添加附件文件相同)

如果您使用 system.net.mail 命名空间发送邮件,则无需将图像转换为 base64。

var mail = new MailMessage();
var imageToInline = new LinkedResource("Your image full path", MediaTypeNames.Image.Jpeg);
            imageToInline.ContentId = "MyImage";
            alternateView.LinkedResources.Add(imageToInline);
mail.AlternateViews.Add(body);

更新:

这是将图像嵌入到您的 mailMessage 的一种有点 hacky 的方式。

Byte[] bitmapData = Convert.FromBase64String(FixBase64ForImage("Your base64 image string"));
System.IO.MemoryStream streamBitmap = new System.IO.MemoryStream(bitmapData);

public static string FixBase64ForImage(string Image)

        System.Text.StringBuilder sbText = new System.Text.StringBuilder(Image, Image.Length);
        sbText.Replace("\r\n", string.Empty); sbText.Replace(" ", string.Empty);
        return sbText.ToString();



var mail = new MailMessage();
var imageToInline = new LinkedResource(streamBitmap , MediaTypeNames.Image.Jpeg);
imageToInline.ContentId = "MyImage";
alternateView.LinkedResources.Add(imageToInline);
mail.AlternateViews.Add(body);

你的 html 邮件正文应该有以下标签:

 <img alt ="" src ="cid:MyImage"/>

【讨论】:

但是我需要将图像与电子邮件一起发送,是吗?我拥有的唯一数据是 base64 图像。 您想在电子邮件中显示图像或将其添加为附件,就像任何其他 zip 文件一样? 我想在电子邮件中显示图像。但我的图像是base64。字符串图像=“数据:图像/png;base64,iVBORw0KGgoAAAANSUh.....”;我怎样才能把它放在电子邮件正文中或转换它? 我更新了我的答案。如果您只想将 base64 图像转换为位图,请参考 this 我正在检查。【参考方案3】:
<body>
     <img src='data:image/jpeg;base64, <!-- base64 data --> />
   </body>

在邮件的 HTML 中使用上面的 img 标签

或者你可以如下附上

Attachment attachment = new Attachment(base64String);
attachment.TransferEncoding = TransferEncoding.Base64;
mailmessage.Attachments.Add(attachment);

【讨论】:

是的,但是如何将 base64 图像附加到 MailMessage 类中? 如果可以使用电子邮件的 HTML 正文可视化图像,为什么还要附加? 我认为许多电子邮件客户端不支持编码的内联图像 我正在使用相同的方法,但它不起作用。我的 base64String 长度为 19000+,因此,它在 Attachment attachment = new Attachment(base64String); 处抛出错误。 这段代码没有意义,附件构造函数没有重载,它接受一个base64字符串,它需要一个路径或一个流。 new Attachment(base64String);

以上是关于在 MailMessage 中添加附件 base64 图像并在 html 正文中读取的主要内容,如果未能解决你的问题,请参考以下文章

MailMessage 带重音符号的附件文件名

.Net 自带System.Net.Mail.MailMessage发送邮件乱码问题

有没有办法序列化 .Net MailMessage 对象

删除附件文件

如何在 MailMessage 中正确添加 CSS

Laravel 5.3 将 html 添加到 MailMessage->line