Генерация HTML-тела письма в C # - PullRequest
107 голосов
/ 20 мая 2009

Есть ли лучший способ создания электронной почты в формате HTML в C # (для отправки через System.Net.Mail), чем использование 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 ]

174 голосов
/ 20 мая 2009

Вы можете использовать MailDefinition класс .

Вот как вы его используете:

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

Кроме того, я написал сообщение в блоге о том, как генерировать тело письма в формате HTML в C #, используя шаблоны с использованием класса MailDefinition .

25 голосов
/ 20 мая 2009

Используйте класс 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();
15 голосов
/ 14 декабря 2012

Обновленный ответ :

Документация для SmtpClient, класса, используемого в этом ответе, теперь гласит: "Устаревший (" SmtpClient и его сеть типов плохо спроектированы, мы настоятельно рекомендуем использовать https://github.com/jstedfast/MailKit и https://github.com/jstedfast/MimeKit вместо ")".

Источник: https://www.infoq.com/news/2017/04/MailKit-MimeKit-Official

Оригинальный ответ :

Использование класса MailDefinition - неправильный подход. Да, это удобно, но также примитивно и зависит от элементов управления веб-интерфейса - это не имеет смысла для чего-то, что обычно является задачей на стороне сервера.

Подход, представленный ниже, основан на документации MSDN и пост Куреши на 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 голосов
/ 17 февраля 2015

Я использую 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));

Он также работает с коллекциями, см. некоторые онлайн-примеры .

4 голосов
/ 20 мая 2009

Я бы рекомендовал использовать какие-то шаблоны. Существуют различные способы решения этой проблемы, но, по сути, они содержат шаблон электронной почты, где-то (на диске, в базе данных и т. Д.), И просто вставляют данные ключа (IE: имя получателя и т. Д.) В шаблон.

Это гораздо более гибко, потому что это означает, что вы можете изменять шаблон по мере необходимости, не изменяя свой код. По моему опыту, вы, вероятно, получите запросы на изменение шаблонов от конечных пользователей. Если вы хотите использовать все возможности, вы можете включить редактор шаблонов.

3 голосов
/ 06 февраля 2014

В качестве альтернативы MailDefinition, взгляните на RazorEngine https://github.com/Antaris/RazorEngine.

Это выглядит как лучшее решение.

Приписывается ...

как отправить электронное письмо с шаблоном электронной почты c #

1012 * например *

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>

Heading Here

Дорогой Фред,

Первая часть письма тело идет сюда

3 голосов
/ 20 мая 2009

Создание подобного html-кода вручную, вероятно, является наилучшим способом, если разметка не слишком сложна. Строитель строк начинает окупать себя с точки зрения эффективности только после трех конкатенаций, поэтому для действительно простых вещей подойдет строка + строка.

Кроме этого, вы можете начать использовать элементы управления html (System.Web.UI.HtmlControls) и отображать их, так что вы можете иногда наследовать их и создавать собственные условия для сложной условной компоновки.

2 голосов
/ 20 февраля 2010

Возможно, вы захотите взглянуть на некоторые шаблоны, которые доступны в данный момент. Некоторые из них являются дополнительными в результате MVC, но это не обязательно. Искра хорошая.

1 голос
/ 15 апреля 2012

Если вы не хотите зависеть от полной версии .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-сообщение из приложения.

0 голосов
/ 15 ноября 2010

Есть похожий вопрос StackOverflow , который содержит несколько довольно полных ответов. Лично я использую NVelocity в качестве механизма шаблонов, ранее пытаясь использовать механизм ASP.Net для генерации HTML-содержимого электронной почты. NVelocity намного проще в использовании, но при этом обеспечивает большую гибкость. Я обнаружил, что использование ASP.Net .aspx файлов для шаблонов работает, но имеет некоторые непредвиденные побочные эффекты.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...