使用 SmtpClient 发送邮件时图像中断
Posted
技术标签:
【中文标题】使用 SmtpClient 发送邮件时图像中断【英文标题】:Images breaking when sending mail using SmtpClient 【发布时间】:2013-05-20 04:48:21 【问题描述】:我正在使用 C# 使用 SmtpClient
类发送邮件。在发送邮件之前,我正在做以下事情。
var mailMessage = new MailMessage();
model.ToAddresses.ForEach(to => mailMessage.To.Add(to));
mailMessage.Subject = "Test Email - By Yasser";
mailMessage.Body = String.Format("012",
"<html><body>",
GetEmailContent(model),
"</body></html>");
mailMessage.IsBodyHtml = true;
return MailService.SendEmail(mailMessage);
下面是我的 MailService 类:
public class MailService
public static bool SendEmail(MailMessage mailMessage)
var smtpClient = new SmtpClient();
try
smtpClient.Send(mailMessage);
return true;
catch(Exception exp)
return false;
现在当我发送邮件时,邮件被发送,这是我在按查看源时在 Outlook 中得到的邮件内容。下面是邮件的内容,有图源(显然我只保留了部分图片数据)
<html>
<body>
<h1>Test</h1>
<h2>Hello World</h2>
<h3>Missing close h3 tag</h3>
<p>
<a href="www.google.com">
<img src="data:image/gif;base64,/9j/4AAQSkZJRgABAgEAYABgAAD/4Q8HRXhpZgAAT" />
</a>
</p>
</body>
</html>
所以这在邮件中显示为损坏(图像),但是当我复制此源并将其粘贴到编辑器并使用浏览器打开文件时,一切似乎都很好(甚至图像)。
更新:添加了来自 Outlook 的邮件图片
有什么想法吗????
【问题讨论】:
澄清一下:您的问题是,图像没有在电子邮件中加载(显示)?是否显示无法加载图像的图标? 您可能想试试邮件在 gmail 或其他网络邮件程序中的外观。验证问题是否存在于所有邮件客户端,而不仅仅是 Outlook。 如何将图像添加到电子邮件中?您是否正在使用自己的方法来获取嵌入图像所需的字符串或诸如AlternateView
之类的内置内容?
你可能想看看这个问题的答案:***.com/questions/9110091/…
@Anubis1233 在 Thunderbird 和 gmail 中试过,看起来一样...
【参考方案1】:
这是我尝试并为我工作的方法,在 Outlook、Thunderbird 和 gmail 中进行了测试。工作正常!
您可能想查看我提到的以下资源:
Using LinkedResource Class for Sending HTML E-mail in .NET 2.0 Sending emails with embedded images in html view using linked resources class How do I embed an image in a .NET HTML Mail Message? System.Net.Mail FAQ示例代码:
// we need to use the prefix 'cid' in the img src value
string emailReadyHtml = string.empty;
emailReadyHtml += "<p>Hello World, below are two embedded images : </p>";
emailReadyHtml += "<img src=\"cid:yasser\" >";
emailReadyHtml += "<img src=\"cid:smile\" >";
MailMessage mailMessage = new MailMessage();
mailMessage.To.Add("yasser@mail.yy");
mailMessage.From = new MailAddress("info@mail.yy", "Info");
mailMessage.Subject = "Test Mail";
mailMessage.IsBodyHtml = true;
string image1Path = HttpContext.Current.Server.MapPath("~/Content/images/yasser.jpg");
byte[] image2Bytes = someArrayOfByte;
ContentType c = new ContentType("image/jpeg");
// create image resource from image path using LinkedResource class.
LinkedResource linkedResource1 = new LinkedResource(imagePath);
linkedResource1.ContentType = c ;
linkedResource1.ContentId = "yasser";
linkedResource1.TransferEncoding = TransferEncoding.Base64;
// the linked resource can be created from bytes also, which may be stored in database (which was my case)
LinkedResource linkedResource2 = new LinkedResource(new MemoryStream(image2Bytes));
linkedResource2.ContentType = c;
linkedResource2.ContentId = "smile";
linkedResource2.TransferEncoding = TransferEncoding.Base64;
AlternateView alternativeView = AlternateView.CreateAlternateViewFromString(emailReadyHtml, null, MediaTypeNames.Text.Html);
alternativeView.ContentId = "htmlView";
alternativeView.TransferEncoding = TransferEncoding.SevenBit;
alternativeView.LinkedResources.Add(linkedResource1) ;
alternativeView.LinkedResources.Add(linkedResource2);
mailMessage.AlternateViews.Add(alternativeView);
SmtpClient smtpClient = new SmtpClient();
smtpClient.Send(mailMessage);
【讨论】:
您永远不会将正文分配给 mailMessage。此代码不起作用。 您是否尝试过代码@AAlferez?最好分配一个主体,但这不是必需的。【参考方案2】:这是一个可以解决问题的函数。在发送电子邮件之前调用它,例如:
ProcessEmbeddingImages(mailMessage);
return MailService.SendEmail(mailMessage);
ProcessEmbeddingImages 函数是用 VB.Net 编写的,因此您可能希望使用其中一种在线翻译器将其翻译成 c#。
Private Sub ProcessEmbeddingImages(ByRef oMail As System.Net.Mail.MailMessage)
Dim oLinkedResources As New Hashtable()
oMail.Body = PadSrcDataImage(oMail.Body, oLinkedResources)
If oLinkedResources.Count > 0 Then
Dim oAlternateView As System.Net.Mail.AlternateView = System.Net.Mail.AlternateView.CreateAlternateViewFromString(oMail.Body, Nothing, "text/html")
oAlternateView.ContentId = "htmlView"
oAlternateView.TransferEncoding = Net.Mime.TransferEncoding.SevenBit
For Each oItem As DictionaryEntry In oLinkedResources
Dim oKey As String() = Split(oItem.Key, "-")
Dim i As Integer = oKey(0)
Dim sExt As String = oKey(1)
Dim sData As String = oItem.Value
Dim oLinkedResource As New System.Net.Mail.LinkedResource(New IO.MemoryStream(System.Convert.FromBase64String(sData)))
oLinkedResource.ContentId = "MyImg" & i
oLinkedResource.TransferEncoding = Net.Mime.TransferEncoding.Base64
oLinkedResource.ContentType = New System.Net.Mime.ContentType("image/" & sExt)
oAlternateView.LinkedResources.Add(oLinkedResource)
Next
oMail.AlternateViews.Add(oAlternateView)
End If
End Sub
Private Function PadSrcDataImage(ByVal sHtml As String, ByRef oLinkedResources As Hashtable) As String
Dim oList As New ArrayList
Dim sSearch As String = "\s-s-rc=['""]data:image/(.*?);base64,(.*?)['""]"
Dim oMatches As System.Text.RegularExpressions.MatchCollection = System.Text.RegularExpressions.Regex.Matches(sHtml, sSearch, System.Text.RegularExpressions.RegexOptions.IgnoreCase)
For Each m As System.Text.RegularExpressions.Match In oMatches
If m.Groups.Count >= 2 Then
Dim sExt As String = m.Groups(1).Value
Dim sData As String = m.Groups(2).Value
If sData.Length > 7 AndAlso Right(sData, 6) = "%3D%3D" Then
'Replace trailing %3D%3D with ==
sData = Left(sData, sData.Length - 6) & "=="
End If
oLinkedResources.Add(oLinkedResources.Count & "-" & sExt, sData)
Dim iPos1 As Integer = m.Groups(1).Index - "data:image/".Length
Dim iPos2 As Integer = m.Groups(2).Index + m.Groups(2).Length
Dim iPoints As Integer() = iPos1, iPos2
oList.Add(iPoints)
End If
Next
Dim sRet As String = ""
If oList.Count = 1 Then 'One img
Dim iPoints As Integer() = oList(0)
Dim sStr1 As String = sHtml.Substring(0, iPoints(0))
Dim sStr2 As String = sHtml.Substring(iPoints(1))
sRet = sStr1 & "cid:MyImg0" & sStr2
ElseIf oList.Count > 1 Then
For i As Integer = 0 To oList.Count - 1
Dim iPoints As Integer() = oList(i)
Dim iPos1 As Integer = iPoints(0)
If i = 0 Then
'First img
Dim sStr1 As String = sHtml.Substring(0, iPos1)
sRet += sStr1 & "cid:MyImg" & i
Else 'Rest imgs
Dim iPrevPos2 As Integer = oList(i - 1)(1)
Dim sStr1 As String = sHtml.Substring(iPrevPos2, iPos1 - iPrevPos2)
sRet += sStr1 & "cid:MyImg" & i
If i = oList.Count - 1 Then 'Last
sRet += sHtml.Substring(iPoints(1))
End If
End If
Next
End If
If sRet <> "" Then
Return sRet
Else
Return sHtml
End If
End Function
【讨论】:
它读取 data:image 数据并将这些图像添加为链接资源。以上是关于使用 SmtpClient 发送邮件时图像中断的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 SmtpClient.SendAsync 发送带有附件的电子邮件?
使用第三方与投递文件夹时 SMTPClient 发送限制为 50 封电子邮件