HTMLメールをASP.net の razor とかで処理しようとした件

  • 2
    Like
  • 0
    Comment

昨晩結構重めのリリースがあり、想定より時間とれずにアドベントできてねーじゃんってなり他の方々に非常に申し訳ないですが、何とかネタを振り絞って書きます。
ちょうど最近周りからHTMLメールに関する話を聞くのでHTMLメールについての話を書きます。
といってもHTMLメール一般的なのじゃなくて .net に限った話です。

razor って?

.NetFramework のwebフレームワークの ASP.net MVC の3から登場したビュー・エンジンです。

@using System.Globalization
<div>
  <p>@Model.Description</p>
</div>

みたいな感じに @ と書く事で namesapce の using や ViewModel の値を html に埋め込む事ができます。
今時 ASP.net MVC で開発していれば View は大体この記法で書いているかと思います。

この辺りが入門にはいいかもしれません。
新しいビュー・エンジン「Razor」の基本を理解しよう

razor で HTMLメール..?

で、普段から razor で Web の開発をやっていると 「HTML メールのテンプレートもできたら使い慣れた razor で管理できねーかな」って思うわけです。
そこで登場するのが Razoer Engine です。

A templating engine built on Microsoft's Razor parsing engine, RazorEngine allows you to use Razor syntax to build dynamic templates. You can find an introduction here. All you need to do is use the static Engine class (the Engine.Razor instance) in the 'RazorEngine' namespace:

って書いてあるように razor のシンタックスでテンプレートを利用できます。
これでHTMLメールも結局は htmlBody を string で渡せればいいので何とかできます。

利用方法

実際は大分簡略化しましたが、こんな感じでやりました。
まずは rezor で書かれた cshtml を作りコード内で扱うために Resouce 形式にしました。(直接File.IO使って読み取ってもいいけど同じ csproj 内で管理したかったため)
Resourceファイルを作成し、左上のメニューからファイルに変更します。
20161216-01704.jpg

その後、cshtml をドラッグアンドドロップで下の領域に置き保存すれば Resource として扱えます。
20161216-02227.jpg

で実際に RazorEngine を使ってパースするのは以下のような感じになります。

using System.Text;
using RazorEngine.Templating;

namespace Sansan.Mails
{
    public class HtmlMail
    {
        public string ParseHtmlMail()
        {
            var templateService = new TemplateService();
            var template = Resources.Template.htmlMail;
            var viewModel = new ViewModel();

            return templateService.Parse(Encoding.UTF8.GetString(template), viewModel, null, null);
        }
    }

    public class ViewModel
    {
        public string Hoge { get; set; }
    }
}

これで戻ってくる string は ViewModel の値の適用された html が string として返ってきます。
あとはこれをsmtpClient などに投げ込めば Htmlメールが投げれますね。

実際には他にも Culture の適用や、Template のキャッシングなんかもやってたりしますが、一旦今回は一旦こんな感じで締めておきます。(雑...)