代码之家  ›  专栏  ›  技术社区  ›  Rob

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

  •  103
  • Rob  · 技术社区  · 16 年前

    使用C#(用于通过System.Net.Mail发送)生成HTML电子邮件是否有比使用Stringbuilder执行以下操作更好的方法:

    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>");
    

    等等,等等?

    10 回复  |  直到 12 年前
        1
  •  184
  •   MartinHN    10 年前

    你可以使用 MailDefinition class .

    这是您使用它的方式:

    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());
    

    generate HTML e-mail body in C# using templates using the MailDefinition class .

        2
  •  28
  •   AnthonyWJones    16 年前

    使用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在缩进方面的选择有点古怪。

    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();
    
        3
  •  17
  •   Seth    8 年前

    最新答案 :

    文件 SmtpClient ,在这个答案中使用的类,现在读到,“过时”(“SmtpClient及其类型网络设计不良,我们强烈建议您使用 https://github.com/jstedfast/MailKit https://github.com/jstedfast/MimeKit 而是"。

    https://www.infoq.com/news/2017/04/MailKit-MimeKit-Official

    原始答案

    使用MailDefinition类是错误的方法。是的,它很方便,但它也很原始,并且依赖于web UI控件——这对于典型的服务器端任务来说没有意义。

    下面介绍的方法基于MSDN文档和 Qureshi's post on CodeProject.com .

    注意:本例从嵌入式资源中提取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();
    }
    
        4
  •  6
  •   jacobsgriffith    10 年前

    我用 dotLiquid

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

    //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));
    

    它也适用于集合,请参见 some online examples

        5
  •  5
  •   Leather    16 年前

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

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

        6
  •  4
  •   Mick    7 年前

    作为MailDefinition的替代方案,请看一下RazorEngine https://github.com/Antaris/RazorEngine

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

    归因于。。。

    how to send email wth email template c#

    using RazorEngine;
    using RazorEngine.Templating;
    using System;
    
    namespace RazorEngineTest
    {
        class Program
        {
            static void Main(string[] args)
            {
        string template =
        @"<h1>Heading Here</h1>
    Dear @Model.UserName,
    <br />
    <p>First part of the email body goes here</p>";
    
        const string templateKey = "tpl";
    
        // Better to compile once
        Engine.Razor.AddTemplate(templateKey, template);
        Engine.Razor.Compile(templateKey);
    
        // Run is quicker than compile and run
        string output = Engine.Razor.Run(
            templateKey, 
            model: new
            {
                UserName = "Fred"
            });
    
        Console.WriteLine(output);
            }
        }
    }
    

    哪个输出。。。

    <h1>Heading Here</h1>
    Dear Fred,
    <br />
    <p>First part of the email body goes here</p>
    

    到这里来

    亲爱的弗雷德:,

    电子邮件的第一部分

        7
  •  3
  •   Mark Dickinson    16 年前

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

        8
  •  1
  •   Simon Farrow    15 年前

    Spark 这是个好主意。

        9
  •  1
  •   Vladislav Zorov    13 年前

    如果您不想依赖完整的.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();
    

    它是开源的,你可以从 http://sourceforge.net/projects/htmlplusplus/

    免责声明:我是这个库的作者,它的编写正是为了解决同样的问题——从应用程序发送HTML电子邮件。

        10
  •  1
  •   Geovani Martinez    5 年前

    我在生产中使用的一个商业版本,可以方便地进行维护 LimiLabs Template Engine

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

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