Stringbuilder를 사용하여 다음을 수행하는 것보다 C # (System.Net.Mail을 통해 보내기)에서 HTML 이메일을 생성하는 더 좋은 방법이 있습니까?
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>");
기타 등등?
답변
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());
또한 MailDefinition 클래스를 사용하여 템플릿을 사용하여 C #에서 HTML 전자 메일 본문 을 생성 하는 방법에 대한 블로그 게시물을 작성했습니다 .
답변
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();
답변
업데이트 된 답변 :
SmtpClient
이 답변에 사용 된 클래스에 대한 설명서는 이제 ‘Obsolete ( “SmtpClient 및 해당 유형의 네트워크가 잘못 설계되었습니다. https://github.com/jstedfast/MailKit 및 https : // github 를 사용하는 것이 좋습니다 . .com / jstedfast / MimeKit 대신 “) ‘.
출처 : https://www.infoq.com/news/2017/04/MailKit-MimeKit-Official
원래 답변 :
MailDefinition 클래스를 사용하는 것은 잘못된 접근 방식입니다. 예, 편리하지만 원시적이며 웹 UI 컨트롤에 따라 달라집니다. 일반적으로 서버 측 작업에는 의미가 없습니다.
아래에 제시된 접근 방식은 MSDN 문서와 CodeProject.com에 대한 Qureshi의 게시물을 기반으로 합니다.
참고 :이 예제는 포함 된 리소스에서 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();
}
답변
정확히이 작업에 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));
컬렉션에서도 작동합니다 . 온라인 예제를 참조하십시오 .
답변
일종의 템플릿을 사용하는 것이 좋습니다. 이에 접근하는 방법에는 여러 가지가 있지만 본질적으로 이메일 템플릿을 어느 곳에 (디스크, 데이터베이스 등) 보유하고 단순히 키 데이터 (IE : 수신자 이름 등)를 템플릿에 삽입합니다.
코드를 변경하지 않고도 필요에 따라 템플릿을 변경할 수 있기 때문에 훨씬 더 유연합니다. 제 경험상 최종 사용자로부터 템플릿 변경 요청을받을 가능성이 높습니다. 돼지 전체를 다루고 싶다면 템플릿 편집기를 포함 할 수 있습니다.
답변
MailDefinition의 대안으로 RazorEngine https://github.com/Antaris/RazorEngine을 살펴보세요 .
이것은 더 나은 해결책처럼 보입니다.
원인 …
예
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>
여기로
프레드에게,
이메일 본문의 첫 부분이 여기에 표시됩니다.
답변
마크 업이 너무 복잡하지 않은 한 이렇게 손으로 만든 html을 내보내는 것이 아마도 가장 좋은 방법 일 것입니다. stringbuilder는 약 세 번의 연결 후에 만 효율성 측면에서 보상하기 시작하므로 정말 간단한 물건의 경우 string + string이 할 것입니다.
그 외에는 html 컨트롤 (System.Web.UI.HtmlControls)을 사용하고 렌더링 할 수 있습니다. 그런 식으로 가끔 상속하고 복잡한 조건부 레이아웃에 대한 자신 만의 클래스를 만들 수 있습니다.