2009-05-20 13 views
91

は、次の操作を行うのStringBuilderを使用するよりも、(System.Net.Mailを経由して送信するため)C#でHTMLメールを生成するための良い方法はあります、など?の生成HTMLメールの本文は

答えて

152

あなたはMailDefinition classを使用することができます。

MailDefinition md = new MailDefinition(); 
md.From = "[email protected]"; 
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("[email protected]", replacements, body, new System.Web.UI.Control()); 

はまた、私はどのようにgenerate HTML e-mail body in C# using templates using the MailDefinition classへのブログの記事を書いた:

これは、あなたがそれを使用する方法です。

+7

ダン!私はこのクラスについて全く知らなかった! +1 – Cerebrus

+0

恐ろしい。教育のために+1: –

+10

私は知っていなかったこれは存在し、純粋な天才それは... +1と受け入れ – Rob

3

マークアップがあまりにも複雑でない限り、このような手作りのHTMLは、おそらく最良の方法です。 stringbuilderは、約3回の連結の後に効率の点で払い戻しを開始するので、実際には単純なものstring + stringが行います。

これ以外にも、htmlコントロール(System.Web.UI.HtmlControls)の使用を開始し、それらをレンダリングすることができます。そのようにして、複雑な条件付きレイアウトのために継承したり、独自のクラスを作成することができます。

21

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

これは古くなったようです – Daniel

+0

これは私にとって最高の答えでした。シンプルでポイントに(確かにかなりclunky)。 MailDefinitionは面白かったが、私が探していたものではなかった。 – thehelix

+0

あなたの洞窟の男の歓声を出す! – tobias

4

何らかの種類のテンプレートを使用することをおすすめします。これにアプローチするにはさまざまな方法がありますが、本質的に電子メールのテンプレートを(データベースなどの)ディスク上に保存し、キーデータ(IE:受信者名など)をテンプレートに挿入するだけです。

これは、コードを変更することなく、必要に応じてテンプレートを変更できるので、はるかに柔軟です。私の経験では、エンドユーザーからのテンプレートの変更要求を受け取る可能性があります。あなたが豚全体に行きたい場合は、テンプレートエディタを含めることができます。

0

さて、私が見ているように、ソリューションには本当に依存しています。私はユーザー入力を取得し、異なるパターンから自動的に書式を設定することからすべてを行いました。私がメールの入力を知っていたので、私がhtmlメールで行った最善の解決策は実際にはxml + xsltの書式設定でした。

0

要件の複雑さによって異なります。私はかつてHTML電子メールでテーブルをレンダリングするアプリケーションを持っていました。そして、HTMLグリッドビューを使ってテーブルを生成するHTML連結文字列をレンダリングするのは面倒だったでしょう。

0

私は過去にも同様のアプローチ(XML + XSLT)を使用して、良い結果を得ています。これは多くの柔軟性を提供し、コードは、この電子メールが必要とする正確なデータに心配する必要がないことを意味します(関連するすべての情報を含むXML文書を生成し、XSLTが希望のビットを選ぶようにします)。

私が言うことは、XSLTに頭痛の種が少し入っていることがわかっていますが、最初の奇妙なことを過ぎるとうまくいきました。

1

現時点で利用可能なテンプレートフレームワークをいくつか見てみたいかもしれません。 MVCの結果としてスピンオフしているものもありますが、必須ではありません。 Sparkはいいです。

0

StackOverflow questionにはかなり包括的な回答が含まれています。個人的には、以前はASP.Netエンジンを使用してhtml電子メールコンテンツを生成しようとしていたテンプレートエンジンとしてNVelocityを使用しています。 NVelocityは多くの柔軟性を提供しながら使用するのがずっと簡単です。私はASP.Netを使用してそれが見つかりました.aspxテンプレートのファイルが動作したが、いくつかの予期しない副作用があった。

1

あなたは完全な.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メールを送信します。

14

回答更新:SmtpClientため

マニュアルを参照して、この答えに使用されるクラスは、廃止(「SmtpClientと種類のそのネットワークが不十分に設計されて、私たちは強くあなたがhttps://github.com/jstedfast/MailKithttps://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(); 
} 
+7

あなたのブログ記事へのリンクのみを表示してはいけません。あなたのブログが消えてしまった場合は、あなたの答えは無用になります。ここにあなたの答えに投稿の「キー」部分があります。 – Rob

+0

ここにブログ記事の内容を移動しました。ありがとう、@ Roh。 – Seth

+0

このコードはテスト済みで、プロダクションで使用されています応用。 – Seth

4

テンプレートをとり、特別な識別子に匿名オブジェクトの内容を埋め込みます。

//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を参照してください。

+0

can templateSourceは.htmlファイルですか?または.cshtmlカミソリファイルですか? – ozzy432836

+1

@Ozzy実際には任意の(テキスト)ファイルが可能です。 DotLiquidは、テンプレートファイルと干渉する場合に備えて、テンプレート構文を変更することさえできます。 – Marcel

関連する問題