C# 用C语言生成HTML邮件正文

C# 用C语言生成HTML邮件正文,c#,html,email,C#,Html,Email,与使用Stringbuilder执行以下操作相比,是否有更好的方法在C中生成HTML电子邮件以通过System.Net.Mail发送: string userName = "John Doe"; StringBuilder mailBody = new StringBuilder(); mailBody.AppendFormat("<h1>Heading Here</h1>"); mailBody.AppendFormat("Dear {0}," userName); m

与使用Stringbuilder执行以下操作相比,是否有更好的方法在C中生成HTML电子邮件以通过System.Net.Mail发送:

string userName = "John Doe";
StringBuilder mailBody = new StringBuilder();
mailBody.AppendFormat("<h1>Heading Here</h1>");
mailBody.AppendFormat("Dear {0}," userName);
mailBody.AppendFormat("<br />");
mailBody.AppendFormat("<p>First part of the email body goes here</p>");

等等,等等?

像这样发出手工构建的html可能是最好的方法,只要标记不太复杂。stringbuilder在经过大约三次串联后才开始在效率方面回报您,所以对于真正简单的东西,string+string就可以了


除此之外,您可以开始使用html控件System.Web.UI.HtmlControl并呈现它们,这样您有时可以继承它们并为复杂的条件布局创建自己的类别。

使用System.Web.UI.HtmlTextWriter类

StringWriter writer = new StringWriter();
HtmlTextWriter html = new HtmlTextWriter(writer);

html.RenderBeginTag(HtmlTextWriterTag.H1);
html.WriteEncodedText("Heading Here");
html.RenderEndTag();
html.WriteEncodedText(String.Format("Dear {0}", userName));
html.WriteBreak();
html.RenderBeginTag(HtmlTextWriterTag.P);
html.WriteEncodedText("First part of the email body goes here");
html.RenderEndTag();
html.Flush();

string htmlString = writer.ToString();
对于包含样式属性创建的广泛HTML,HtmlTextWriter可能是最好的方法。然而,它的使用可能有点笨拙,一些开发人员喜欢标记本身易于阅读,但HtmlTextWriter在缩进方面的选择有点古怪

在本例中,您还可以非常有效地使用XmlTextWriter:-

writer = new StringWriter();
XmlTextWriter xml = new XmlTextWriter(writer);
xml.Formatting = Formatting.Indented;
xml.WriteElementString("h1", "Heading Here");
xml.WriteString(String.Format("Dear {0}", userName));
xml.WriteStartElement("br");
xml.WriteEndElement();
xml.WriteElementString("p", "First part of the email body goes here");
xml.Flush();
您可以使用

这是您使用它的方式:

MailDefinition md = new MailDefinition();
md.From = "test@domain.com";
md.IsBodyHtml = true;
md.Subject = "Test of MailDefinition";

ListDictionary replacements = new ListDictionary();
replacements.Add("{name}", "Martin");
replacements.Add("{country}", "Denmark");

string body = "<div>Hello {name} You're from {country}.</div>";

MailMessage msg = md.CreateMailMessage("you@anywhere.com", replacements, body, new System.Web.UI.Control());

此外,我还写了一篇关于如何使用的博文。

我建议使用某种模板。有各种不同的方法来实现这一点,但本质上是将电子邮件模板保存在磁盘、数据库等的某个位置,然后简单地将关键数据(例如:收件人姓名等)插入模板中


这要灵活得多,因为这意味着您可以根据需要修改模板,而无需修改代码。根据我的经验,您可能会收到最终用户对模板的更改请求。如果你想一劳永逸,你可以包括一个模板编辑器。

你可能想看看目前可用的一些模板框架。其中一些是MVC的衍生产品,但这不是必需的。是个不错的选择。

如果您不想依赖完整的.NET Framework,还有一个库可以让您的代码看起来像:

string userName = "John Doe";

var mailBody = new HTML {
    new H(1) {
        "Heading Here"
    },
    new P {
        string.Format("Dear {0},", userName),
        new Br()
    },
    new P {
        "First part of the email body goes here"
    }
};

string htmlString = mailBody.Render();
它是开源的,你可以从

免责声明:我是此库的作者,编写此库完全是为了解决同一问题-从应用程序发送HTML电子邮件。

更新答案:

这个答案中使用的类SmtpClient的文档现在是这样写的:“ObsoleteSmtpClient及其类型网络的设计很差,我们强烈建议您使用和”

资料来源:

原始答复:

使用MailDefinition类是错误的方法。是的,它很方便,但它也很原始,并且依赖于web UI控件,而这些控件对于通常是服务器端任务的东西来说毫无意义

下面介绍的方法基于MSDN文档和

注意:本例从嵌入式资源中提取HTML文件、图像和附件,但使用其他替代方法获取这些元素的流是可以的,例如硬编码字符串、本地文件等

Stream htmlStream = null;
Stream imageStream = null;
Stream fileStream = null;
try
{
    // Create the message.
    var from = new MailAddress(FROM_EMAIL, FROM_NAME);
    var to = new MailAddress(TO_EMAIL, TO_NAME);
    var msg = new MailMessage(from, to);
    msg.Subject = SUBJECT;
    msg.SubjectEncoding = Encoding.UTF8;
 
    // Get the HTML from an embedded resource.
    var assembly = Assembly.GetExecutingAssembly();
    htmlStream = assembly.GetManifestResourceStream(HTML_RESOURCE_PATH);
 
    // Perform replacements on the HTML file (if you're using it as a template).
    var reader = new StreamReader(htmlStream);
    var body = reader
        .ReadToEnd()
        .Replace("%TEMPLATE_TOKEN1%", TOKEN1_VALUE)
        .Replace("%TEMPLATE_TOKEN2%", TOKEN2_VALUE); // and so on...
 
    // Create an alternate view and add it to the email.
    var altView = AlternateView.CreateAlternateViewFromString(body, null, MediaTypeNames.Text.Html);
    msg.AlternateViews.Add(altView);
 
    // Get the image from an embedded resource. The <img> tag in the HTML is:
    //     <img src="pid:IMAGE.PNG">
    imageStream = assembly.GetManifestResourceStream(IMAGE_RESOURCE_PATH);
    var linkedImage = new LinkedResource(imageStream, "image/png");
    linkedImage.ContentId = "IMAGE.PNG";
    altView.LinkedResources.Add(linkedImage);
 
    // Get the attachment from an embedded resource.
    fileStream = assembly.GetManifestResourceStream(FILE_RESOURCE_PATH);
    var file = new Attachment(fileStream, MediaTypeNames.Application.Pdf);
    file.Name = "FILE.PDF";
    msg.Attachments.Add(file);
 
    // Send the email
    var client = new SmtpClient(...);
    client.Credentials = new NetworkCredential(...);
    client.Send(msg);
}
finally
{
    if (fileStream != null) fileStream.Dispose();
    if (imageStream != null) imageStream.Dispose();
    if (htmlStream != null) htmlStream.Dispose();
}

作为MailDefinition的替代方案,请看一下RazorEngine

这看起来是一个更好的解决方案

归因于

例如

哪个输出

<h1>Heading Here</h1>
Dear Fred,
<br />
<p>First part of the email body goes here</p>
亲爱的弗雷德,邮件的第一部分 尸体在这里

我用它来完成这个任务

它接受一个模板,并用匿名对象的内容填充特殊标识符

//define template
String templateSource = "<h1>{{Heading}}</h1>Dear {{UserName}},<br/><p>First part of the email body goes here");
Template bodyTemplate = Template.Parse(templateSource); // Parses and compiles the template source

//Create DTO for the renderer
var bodyDto = new {
    Heading = "Heading Here",
    UserName = userName
};
String bodyText = bodyTemplate.Render(Hash.FromAnonymousObject(bodyDto));

它也适用于集合,请参见。

我在生产中使用的一个商业版本,允许轻松维护,已经使用了3年多,允许我在不更新代码免责声明、链接等的情况下更改文本模板它可以简单到

Contact templateData = ...; 
string html = Template
     .FromFile("template.txt")
     .DataFrom(templateData )
     .Render();

值得一看,就像我一样;尝试了这里提到的各种答案后。

+1。Nice虽然有限,但可能有很多用途。如果您想以编程方式包含HTML的部分和/或循环一组需要呈现的项,那么这就没什么用处了。我最近才意识到这一点。很酷。我想它告诉你,在自己为任何问题编写类之前,查看MSDN文档是多么重要。我写了我自己的类,这几乎和MailDefinition一样。对我来说太糟糕了。浪费时间。我不喜欢使用MailDefinition类,因为指定from、to、cc和bcc字段的选项有限。它还依赖于Web UI控件的命名空间,这对我来说毫无意义。请参阅下面的答案…+1,因为我不知道这个类的存在,尽管底层实现只是在replacements列表上迭代并运行Regex.Replacebody、pattern、replacement、RegexOptions.IgnoreCase;对于每个键/值对。。。根据这些细节,除非使用对System.Web.UI.Controls的现有引用,否则该类不会提供上面使用的太多值。这比使用@${someValue}有什么好处?事实上,我认为您的代码不如直接处理Strings那么可读,因为这段代码
它已经过测试,正在生产应用程序中使用。这看起来不正确,是否将HTML附加到mediatype PDF?var file=new AttachmentfileStream,MediaTypeNames.Application.Pdf;您提到的示例部分演示了如何将PDF附加到电子邮件中。这有点令人困惑,因为在其他一些库中,HTML是作为附件发送的。我建议从这个示例中删除PDF附件部分以使其更清晰。此外,在这个示例代码中从未设置过msg.Body,我假设应该为它分配Body变量?缺少一个关键步骤,设置msg.IsBodyHtml=true。在这里看到这个答案:templateSource可以是一个.html文件吗?或者最好是一个.cshtml razor文件?@ozy它实际上可以是任何文本文件。DotLiquid甚至允许更改模板语法,以防它干扰您的模板文件。您好,如何将内联样式添加到例如h1标记?当打开电子邮件弹出窗口时,正文,iam在我的上下文中使用div标记,它被渲染为。您能帮我完成最后一步如何正确渲染吗,在我看来,这真的取决于解决方案。我已经做了所有的事情,从抓取用户输入到从不同的模式自动格式化。我对html邮件的最佳解决方案实际上是xml+xslt格式,因为我们预先知道邮件的输入。这取决于您的需求有多复杂。我曾经有一个应用程序在一封HTML电子邮件中呈现一个表,我使用ASP.NET Gridview来呈现HTML-连接字符串来生成一个表会很混乱。大家都同意,所有的答案几乎都是使用不同的方法来做相同的事情。格式是您所需要的,您可以使用其中任何一种创建您自己的模板;引导到新闻网站。这将在需要循环和ifs时提供最多选项
Contact templateData = ...; 
string html = Template
     .FromFile("template.txt")
     .DataFrom(templateData )
     .Render();