如何使用Razor引擎进行带有图像src的电子邮件模板化

8
我在这个链接中找到了如何在asp.net中使用Razor Engine来创建电子邮件模板的方法,它非常有效。但我尝试将一个带有图像的标志放入电子邮件模板中,就像这样:

像这样:

EmailTemplate.cshtml(顺便说一下,这是一个强类型视图)

<html>
<body>
  <img src="logo.jpg" />
</body>
</html>

当我试图通过电子邮件提交它时,似乎图片路径没有被读取,只在内容中呈现了一个X。

我在考虑将图片路径作为模型的一部分传递,但这种方法似乎有些奇怪。有没有其他方法可以实现这一点?

非常感谢您的任何帮助。谢谢。


电子邮件是在电子邮件应用程序的上下文中呈现的,而不是在您的网站中。因此,“logo.jpg”的请求没有意义,因为在电子邮件应用程序中没有本地位置可以从中提取该文件。这就是为什么您需要绝对URL,以便它知道从您的域中提取,或者您需要将图像嵌入电子邮件中的原因。 - Chris Pratt
我选择使用绝对路径,因为它更简单。谢谢。 - Boy Pasmo
2个回答

11

要在任何地方查看图片,您可以使用以下选项:

绝对路径

您可以简单地使用图像的完整绝对路径,例如"http://example.com/images/logo.png"

我认为这是最简单的选项,并建议您采用此方法解决问题。

附件

如评论中Mason所提到的,您可以将图像附加到邮件中,然后放置图像标签并使用ContentId附件的内容ID:

//(Thanks to Mason for comment and Thanks to  Bartosz Kosarzyck for sample code)
string subject = "Subject";
string body = @"<img src=""$CONTENTID$""/> <br/> Some Content";

MailMessage mail = new MailMessage();
mail.From = new MailAddress("from@example.com");
mail.To.Add(new MailAddress("to@example.com"));
mail.Subject = subject;
mail.Body = body;
mail.Priority = MailPriority.Normal;

string contentID = Guid.NewGuid().ToString().Replace("-", "");
body = body.Replace("$CONTENTID$", "cid:" + contentID);

AlternateView htmlView = AlternateView.CreateAlternateViewFromString(body, null, "text/html");
//path of image or stream
LinkedResource imagelink = new LinkedResource(@"C:\Users\R.Aghaei\Desktop\outlook.png", "image/png");
imagelink.ContentId = contentID;
imagelink.TransferEncoding = System.Net.Mime.TransferEncoding.Base64;
htmlView.LinkedResources.Add(imagelink);
mail.AlternateViews.Add(htmlView);

SmtpClient client = new SmtpClient();
client.Host = "mail.example.com";
client.Credentials = new NetworkCredential("from@example.com", "password");
client.Send(mail);

数据URI

您可以使用数据URI(data:image/png;base64,....)。

不建议使用,因为大多数邮件客户端都不支持它,在我测试了Outlook.com(web)OutlookWebAccess(web)Office Outlook(Windows)Outlook(windows 8.1)后,不幸的是只有在OutlookWebAccess(web)上能正常工作。


1
假设电子邮件客户端支持数据URI……你有这方面的经验吗?我不会仅仅假设它们支持。 - mason
1
还有一个第三种选项。获取图像,将其附加到电子邮件中,并使用内容 ID 将其放入电子邮件正文中。 - mason
@mason 谢谢您的评论。我已经在outlook.com(网页版)、outlookwebaccess(网页版)、office outlook(Windows)和outlook(Windows 8.1)上进行了测试,但不幸的是,只有在outlookwebaccess上才能正常工作。而且似乎没有很好的支持使用data uri。 - Reza Aghaei
@mason 我编辑了答案,不再推荐使用data url,并添加了使用Attachment.ContentId的示例,并在答案中提到了你的评论。谢谢。希望你会发现这个答案有用 :) - Reza Aghaei

0

自上次回答被接受以来,GraphAPI已经发生了变化。在您阅读此内容时,它可能已经再次更改。祝你好运。

您说您正在使用Razor,并且已接受的解决方案包括一些查找\替换操作,这正是Razor所做的。因此,让我们从那里开始。

在您的EmailTemplate.cshtml中,您可以使用Razor语法调用徽标路径:

<img src="@Model.MainLogo" />

当您构建模板时,该值将在数据模型中设置:

string contentIDlogo = "logo.png";
string templateName = "EmailTemplate.cshtml";

object dataModel = new
{
    MainLogo = $"cid:{contentIDlogo}"
};

// This is where you render the Razor to HTML body string.
string emailTemplate = _razorTemplateCache.RenderBasicTemplate(templateName, dataModel);

// Define a simple e-mail message.
var mailMessage = new Message
{
    Subject = subject,
    Body = new ItemBody
    {
        ContentType = BodyType.Html,
        Content = emailTemplate
    },
    ToRecipients = toRecipients.ToList()
};

// Add the image as an attachment to the email.
mailMessage.HasAttachments = true;
byte[] logoBytes = System.IO.File.ReadAllBytes(contentIDlogo);
mailMessage.Attachments = new List<Attachment>
{
    new FileAttachment
    {
        ContentBytes = logoBytes,
        ContentType = "image/png",
        Name = contentIDlogo,
        IsInline = true,
        ContentId = contentIDlogo,
        Size = logoBytes.Length
    }
};
    

现在您已经有了一条消息,可以使用Graph API发布它。 我的示例正在使用Microsoft.Graph (5.9.0)

// Define our new Microsoft Graph client. 
GraphServiceClient graphServiceClient = new GraphServiceClient(_credentials, _scopes, Endpoint);

var requestBody = new SendMailPostRequestBody
{
    Message = theEmail,
    SaveToSentItems = true
};

// Send mail as the given user. 
var fromUser = graphServiceClient.Users[_sendAsUserObjectId];
await fromUser.SendMail.PostAsync(mailMessage, null, cancelToken).ConfigureAwait(false);

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