如何使用SendGrid发送带有嵌入式图片的电子邮件?

12

我开始使用SendGrid来发送电子邮件,但是我找不到如何嵌入图片的方法。在不使用SendGrid的情况下,我使用以下代码发送带有嵌入图像的电子邮件:

var mail = new System.Net.Mail.MailMessage();
mail.Subject = "Warning";
mail.From = "from_user@test.com";
mail.To.Add("to_user@test.com");
mail.IsBodyHtml = true;
mail.Body = "<html><body><a href='http://www.mywebsite.com' title='My Website'><img src='cid:my_image' alt='My Image' border='0' /></a><br /><h1>My E-mail Title</h1>E-mail content.</body></html>";
var av = AlternateView.CreateAlternateViewFromString(mail.Body, null, "text/html");
av.LinkedResources.Add(new LinkedResource(@"C:\my_image.png", "image/png"){ContentId="my_image"});
mail.AlternateViews.Add(av);
var smtp = new SmtpClient("smtp.test.com");
smtp.Credentials = new NetworkCredential("user", "pass");
smtp.Send(mail);

现在我正在使用以下代码发送我的电子邮件(使用SendGrid类)。

var message = SendGrid.GetInstance();
message.Subject = "Warning";
message.From = new MailAddress("from_user@test.com");
message.To = new MailAddress[] { new MailAddress("to_user@test.com") };
message.Html = "<html><body><a href='http://www.mywebsite.com' title='My Website'><img src='cid:my_image' alt='My Image' border='0' /></a><br /><h1>My E-mail Title</h1>E-mail content.</body></html>";
var transportSMTP = SMTP.GetInstance(new NetworkCredential("user", "pass"));
transportSMTP.Deliver(message);

我需要了解如何使用内容ID(CID)在电子邮件中嵌入和链接我的图像。


你能展示一下你现在正在使用的代码吗? - Swift
为什么你不能使用相同的代码? - Swift
我已经添加了我现在正在使用的代码。为了使用sendgrid发送电子邮件,我正在使用他们自己的类。这里是下载链接:https://github.com/sendgrid/sendgrid-csharp。我可以使用默认的.net类来发送带有sendgrid的邮件吗? - Diogo Arenhart
1
是的,您可以使用默认的 .net 类来发送电子邮件。只需将其配置为指向 smtp.sendgrid.net 即可。您真正想使用 SendGrid 库的唯一时间是如果您正在广泛使用 X-SMTPAPI 标头,该库使其更加容易。 - Swift
我遇到了同样的问题。我正在使用SendGrid API发送电子邮件,以便可以嵌入唯一的参数,但无法弄清楚如何嵌入图像。是否有人使用C#包装器成功实现了这个功能:github.com/sendgrid/sendgrid-csharp? - user327999
这在c#库中不可能吗? - TWilly
4个回答

7

我也曾经对此纠结过一段时间。解决方法是先添加图片,然后在邮件中使用文件的直接名称进行嵌入。

var myMessage = new SendGridMessage();
myMessage.AddTo("to@email.com");
myMessage.From = "from@email.com";
myMessage.Subject ="Forgotten Password";
string body = @"<div><img src='cid:email_reset' alt='Email Reset Header' border='0' /></div>" +
              @"<p>Content...</p>";

string att = Request.PhysicalApplicationPath + @"Content\files\images\email_reset.jpg";
var attachment = new Attachment(att, new ContentType("image/jpeg"));
var linkedResource = new LinkedResource(att, new ContentType("image/jpeg"));
myMessage.AddAttachment(attachment.ContentStream, attachment.Name);
myMessage.EmbedImage(attachment.Name, "email_reset");

myMessage.Text = WebUtility.HtmlDecode(Regex.Replace(body, "<[^>]*(>|$)", string.Empty));
myMessage.Html = body;

// Authenticate and Send the email

5
linkedResource 有被使用吗?它看起来是多余的代码? - Sam

3

对于那些在通过SendGrid发送电子邮件时使用存储的模板遇到嵌入式图片发送问题的人,这里是解决方法:

/* In my case the images reside in the SQL DB as BLOBs but for this example it does not matter.
All you need is an array of bytes with your image.
*/
var imageContent = File.ReadAllBytes("Images\\logo_eml.jpg");
using (MemoryStream s = new MemoryStream(imageContent))
{
    ContentType ctype = new ContentType("image/jpg");
    var attachment = new System.Net.Mail.Attachment(s, ctype);
    var linkedResource = new LinkedResource(s, ctype);
    attachment.Name = "cibc_ins_logo_eml.jpg";
    emailMsg.AddAttachment(attachment.ContentStream, attachment.Name);
    emailMsg.EmbedImage(attachment.Name, linkedResource.ContentId + ".jpg");

    values.Add("%embedLogo%", linkedResource.ContentId + ".jpg");
}

string templateJSON = "{\"to\": [\"%to%\"],\r \"sub\": {\":name\": [\"%name%\"],\":embedLogo\": [\"%embedLogo%\"]},\r \"category\": [\"Quotes\"],\r \"filters\": {\"templates\": {\"settings\": {\"enable\": 1,\"template_id\": \"%templateid%\"}}}}"
emailMsg.Headers.Add("x-smtpapi", SubstituteTemplate(templateJSON, values));

最后一行将替换值。在我的情况下,它只是进行了正则表达式替换。此代码将负责使用先前存储在values中的Dictionary<string,string>的值,用你特定JSON中的%embedLogo%的值linkedResource.ContentId+".jpg"进行替换。
以下是您在存储的HTML模板中所需的内容:
<img width="227" height="86" src="cid::embedLogo">

CID和两个冒号非常关键。
然后Gmail将显示嵌入的图像而不仅仅是附件!

2
我和 SendGrid 的客户支持工程师交流过,他把我引荐到了这里。
所以你的代码应该是... https://github.com/sendgrid/sendgrid-csharp/blob/ca91fad22dfec2cd1219267fe979c1d9a33a522e/SendGrid/SendGridMail/SendGrid.cs#L211
var message = SendGrid.GetInstance();
message.Subject = "Warning";
message.From = new MailAddress("from_user@test.com");
message.To = new MailAddress[] { new MailAddress("to_user@test.com") };
message.Html = "<html><body><a href='http://www.mywebsite.com' title='My Website'><img src='cid:my_image' alt='My Image' border='0' /></a><br /><h1>My E-mail Title</h1>E-mail content.</body></html>";

// added    
message.EmbedImage(@"C:\my_image.png","my_image");
// added

var transportSMTP = SMTP.GetInstance(new NetworkCredential("user", "pass"));
transportSMTP.Deliver(message);

我正在寻找一种方法来添加一个MemoryStream对象,而不是文件名。目前看起来似乎还没有这个选项。

实际上是可以的。看一下类似问题的答案:https://dev59.com/oIXca4cB1Zd3GeqPN9EO#27362265 。您可以使用MemoryStream而不是文件名来实例化LinkedResource。 - Prutswonder
我正在使用MemoryStream从数据库加载图片,但没有使用EmbedImage,附加的图片在Outlook中可以正常工作但在Gmail中无法正常显示。我尝试了各种EmbedImage()方法,但都没有用——Outlook总是能够正常工作,而Gmail从来没有成功过。我已经准备跳楼了。 - ajeh

1

如果您想要更简单的方法,可以将图像文件编码为Base64格式,然后将其作为字符串直接嵌入电子邮件正文的html中。对我来说这个方法很有效,因为我只是想在电子邮件签名中包含一个小标志:

<img alt="My Image" src="data:image/jpeg;base64,/9j/4S/+RXhpZgAATU0AKgAAAAgACAESAAMAENkDZ5u8/61a+X...more encoding" />

7
请注意,这在(基于网络的)邮件客户端中得到的支持并不太好! - 321X

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接