.NET CoreでFluentEmailを使用してメールを送信する

.NET CoreでFluentEmailを使用してメールを送信する

実際のプロジェクト開発では、プログラムを介してメールを送信する必要がある場面が多くあります。例えば、異常アラート、メッセージ、進捗通知などです。

最終更新 2020/11/28 9:18
yi念之间
読了目安 9 分
カテゴリ
.NET
タグ
.NET C# Web API メール送信 FluentEmail

はじめに

実際のプロジェクト開発では、プログラムからメールを送信する必要がある場面に数多く遭遇します。例えば、異常アラート、通知、進捗通知などです。通常はネイティブのSmtpClientクラスライブラリを使用することが多く、ほとんどのシナリオで対応できます。しかし、使い方が簡潔ではなく、多くの場面で自分でメソッドをカプセル化して実装する必要があり、コード量が多くなりがちです。幸いなことに、ほとんどのアプリケーションシナリオに対応できる非常に優れたコンポーネントがあります。それが本日紹介するFluentEmailです。これは私たちが実際のプロジェクトで使用しているメール送信コンポーネントでもあります。.NET Coreでメール送信のニーズがある場合は、ぜひ試してみることをお勧めします。

FluentEmail

FluentEmailは、GitHub上でオープンソースかつ無料で提供されている、.NETおよび.NET Coreに対応したメール送信コンポーネントです。現在Star数は1000を超えており、ここ数年は.NET Coreの成熟に伴って、その成長傾向は非常に顕著です。GitHubのアドレスはhttps://github.com/lukencode/FluentEmail です。機能は非常に強力で実用的であり、Razorベースのメールテンプレート、SendGrid、MailGun、SMTPを使用したメール送信をサポートし、使い方も非常にシンプルです。

NuGet コンポーネント

FluentEmailは強力で、さまざまなシナリオに対応する独立したNuGetパッケージが用意されています。この疎結合な分割により、依存関係が明確になるだけでなく、不要なコードの取り込みを防ぐことができます。具体的な機能は以下のコンポーネントパッケージに含まれています。

  • FluentEmail.Core - 基本コアパッケージ。基本的なモデル定義とデフォルト設定が含まれており、以下の参照パッケージはすべてこのコアパッケージを含んでいます。
  • FluentEmail.Smtp - SMTPサービスを使用してメールを送信するためのパッケージ。
  • FluentEmail.Razor - Razorテンプレートを使用してメール内容を生成します。
  • FluentEmail.Mailgun - MailgunのRESTインターフェースを使用してメールを送信します。
  • FluentEmail.SendGrid - SendGridのインターフェースを使用してメールを送信します。
  • FluentEmail.Mailtrap - FluentEmail.Smtpパッケージを使用してMailtrapにメールを送信します。
  • FluentEmail.MailKit - MailKitメールライブラリを使用してメールを送信します。

通常のメール送信方法

次に、FluentEmailを使用してメールを送信する方法を実演します。私たちの実際の業務ではほとんどがSMTPを使用してメールを送信しているため、これを例として説明します。まず、プロジェクトにFluentEmail.Smtpパッケージを追加します。現在の最新バージョンは2.8.0です。

<PackageReference Include="FluentEmail.Smtp" Version="2.8.0" />

これでコードを書く準備ができました。コーディングの方法は非常にシンプルで簡潔であり、主にチェーン方式で記述します。

//smtpサービスを使用してメールを送信するには、smtpサービスの情報を設定する必要があります。
SmtpClient smtp = new SmtpClient
{
    //smtpサーバーアドレス(ここでは126メールを例にしています。実際に使用するメールに応じて設定してください)
    Host = "smtp.126.com",
    UseDefaultCredentials = true,
    DeliveryMethod = SmtpDeliveryMethod.Network,
    //ここにsmtpサーバーのユーザー名とパスワードを入力します
    Credentials = new NetworkCredential("メールユーザー名", "メールパスワード")
};
//デフォルトの送信情報を設定
Email.DefaultSender = new SmtpSender(smtp);
var email = Email
    //送信者
    .From("zhangsan@126.com")
    //受信者
    .To("lisi@qq.com")
    //CC
    .CC("admin@126.com")
    //メールタイトル
    .Subject("メールタイトル")
    //メール本文
    .Body("メール内容");
//送信結果に基づいて成功したかどうかを判断
var result = email.Send();
//または非同期で送信
//await email.SendAsync();
if (result.Successful)
{
    //送信成功のロジック
}
else
{
    //送信失敗の場合、result.ErrorMessagesで失敗理由を確認できます
}

メールの内容にHTML形式を含める場合は、次のようにします。

var email = Email
    //送信者
    .From("zhangsan@126.com")
    //受信者
    .To("lisi@qq.com")
    //CC
    .CC("admin@126.com")
    //メールタイトル
    .Subject("メールタイトル")
    //第2引数をtrueに設定するだけ
    .Body("<h1 align=\"center\">.NET大法好</h1><p>是的,一点毛病都没有</p>",true);
//送信
var result = email.Send();

Bodyメソッドの宣言を見ると、第2引数がHTML形式かどうかを示しており、デフォルトはfalseであることがわかります。

IFluentEmail Body (string body, bool isHtml = false);

メールの受信者が複数のメールアドレスである場合は、Toメソッドの別のオーバーロードを使用してList<FluentEmail.Core.Models.Address>を受け取ることができます。

var email = Email
    //送信者
    .From("zhangsan@126.com")
    //メールタイトル
    .Subject("メールタイトル")
    //メール本文
    .Body("<h1 align=\"center\">.NET大法好</h1><p>是的,一点毛病都没有</p>",true);

//複数の受信者メールアドレスを構築
string toUserStr = "oldwang@126.com;xiaoming@163.com;xiaoli@qq.com";
List<FluentEmail.Core.Models.Address> toUsers = toUserStr.Split(";")
    .Select(i => new FluentEmail.Core.Models.Address { EmailAddress = i }).ToList();
//Addressコレクションを渡すことが可能
email.To(toUsers)
//CCコレクション
.CC(toUsers);
//送信
var result = email.Send();

メールに添付ファイルを追加する必要がある場合は、Attachメソッドを使用します。

var email = Email
        //送信者
        .From("zhangsan@qq.com")
        //受信者
        .To("lisi@126.com")
        //CC
        .CC("admin@126.com")
        //メールタイトル
        .Subject("关于.NET Core怎么样")
        //メール本文
        .Body("<h1 align=\"center\">.NET Core</h1><p>.NET Core很优秀吗?是的,一点毛病都没有!!!</p>",true);

//添付ファイルを構築
var stream = new MemoryStream();
var sw = new StreamWriter(stream);
sw.WriteLine("您好,这是文本里的内容");
sw.Flush();
stream.Seek(0, SeekOrigin.Begin);
var attachment = new FluentEmail.Core.Models.Attachment
{
    Data = stream,
    ContentType = "text/plain",
    Filename = "Hello.txt"
};
//添付ファイルを追加
email.Attach(attachment);
var result = email.Send();

複数の添付ファイルが必要な場合、AttachメソッドはAttachmentのコレクションを受け取ることができます。

//添付ファイルを構築
var stream = new MemoryStream();
var sw = new StreamWriter(stream);
sw.WriteLine("您好,这是文本里的内容");
sw.Flush();
stream.Seek(0, SeekOrigin.Begin);
//添付ファイル1
var attachment = new FluentEmail.Core.Models.Attachment
{
    Data = stream,
    ContentType = "text/plain",
    Filename = "Hello.txt"
};

//添付ファイル2
var attachment2 = new FluentEmail.Core.Models.Attachment
{
    Data = File.OpenRead(@"D:\test.txt"),
    ContentType = "text/plain",
    Filename = "test.txt"
};

//添付ファイルを追加
email.Attach(new List<FluentEmail.Core.Models.Attachment> { attachment, attachment2 });
var result = email.Send();

Razorテンプレートの使用

上記では、FluentEmailを使用した通常のメール送信方法を紹介しました。しかし、動的な内容や複雑なスタイルのHTMLページを送信する必要がある場合もあります。通常、ネイティブのSmtpClientを使用する場合はHTMLコードを連結する方法を取りますが、これは比較的時間と労力がかかります。.NETプログラマにとって、Razorエンジンは動的HTMLページを構築する最もおなじみの方法です。FluentEmailはまさにそのRazorテンプレートをサポートしています。まず、先ほどの構成にFluentEmail.Razorテンプレートサポートコンポーネントを追加します。

<PackageReference Include="FluentEmail.Razor" Version="2.8.0" />

ASP.NET Core 2.2以降、デフォルトでビューコンパイル機能が有効になり、ビューはプロジェクト名.Views.dllにコンパイルされます。ただし、FluentEmail.Razorはビューファイルの内容を読み取る必要があるため、csprojファイルに次の内容を追加する必要があります。

<MvcRazorExcludeRefAssembliesFromPublish>true</MvcRazorExcludeRefAssembliesFromPublish>

これでRazorテンプレートを使用してメール内容を生成できます。具体的な使用方法は次のとおりです。

//Razor方式を使用することを宣言
Email.DefaultRenderer = new RazorRenderer();
//Razor内容
var template = "你好@Model.Name先生, 请核实您的电话号码是否为@Model.Phone";
var email = Email
    .From("lisi@126.com")
    .To("zhangsan@qq.com")
    .Subject("手机号核实")
    //カスタムPOCOクラスを渡す
    //.UsingTemplate<UserInfo>(template, new UserInfo { Name = "张三", Phone吗 = "100110119120" })
    //または匿名オブジェクトを渡す
    .UsingTemplate(template, new { Name = "张三", Phone吗 = "100110119120" });
var result = await email.SendAsync();

もちろん、サポートされているのはRazor文字列だけではありません。Razorビューファイルも渡すことができます。

var email = Email
    .From("lisi@126.com")
    .To("zhangsan@qq.com")
    .Subject("手机号核实")
    //カスタムPOCOクラスを渡す
    //.UsingTemplateFromFile<UserInfo>($"{Directory.GetCurrentDirectory()}/template.cshtml",
    //     new UserInfo { Name = "张三", Phone吗 = "100110119120" });
    //第1引数はビューファイルのパス、第2引数はモデルオブジェクト
    .UsingTemplateFromFile($"{Directory.GetCurrentDirectory()}/template.cshtml",
       new { Name = "张三", Phone吗 = "100110119120" });
var result = await email.SendAsync();

FluentEmail.Razorが強力なRazorテンプレートエンジンをサポートできるのは、内部でRazorLightを統合しているからです。RazorLightは非常に強力なRazorエンジンであり、Razorテンプレート文字列やRazorビューファイルを解析して具体的な文字列結果を生成します。詳細はRazorLightの公式GitHubアドレスhttps://github.com/toddams/RazorLight を参照してください。現時点の正式版は.NET Coreをサポートしていませんが、ベータ版をダウンロードできます。

Install-Package RazorLight -Version 2.0.0-beta10

その使用方法も非常にシンプルです。

//Razor文字列方式
var engine = new RazorLightEngineBuilder()
	.UseEmbeddedResourcesProject(typeof(Program))
	.UseMemoryCachingProvider()
	.Build();
string template = "Hello, @Model.Name. Welcome to RazorLight repository";
ViewModel model = new ViewModel {Name = "John Doe"};
//resultは解析後の文字列
string result = await engine.CompileRenderStringAsync("templateKey", template, model);

またはRazorビューファイル方式

var engine = new RazorLightEngineBuilder()
	.UseFileSystemProject("${Directory.GetCurrentDirectory()}")
	.UseMemoryCachingProvider()
	.Build();
var model = new {Name = "John Doe"};
string result = await engine.CompileRenderAsync("template.cshtml", model);

もちろん、サポートされているのはこれら2つの方法だけではありません。利便性や機能面でも非常に強力です。興味のある方はRazorLightのGitHubアドレスを参照してください。詳細に説明されています。ここではRazorLightの使用方法についてこれ以上詳しくは触れません。

メールの内容について、重要な注意点があります。公共メール事業者(NetEaseやTencentなど)は、SMTPサービスを手動で有効にする必要がある場合があります。具体的な設定方法はhttps://blog.csdn.net/c13_tianming/article/details/47660635 を参照してください。もう1つ重要な点は、公共メール事業者のメールを使用する場合、メールのタイトルや内容に対する制限が大きく、問題が発生しやすいことです。また、SMTPサービスを有効にするにはSMS認証が必要な場合があります。幸い、ほとんどの企業には独自のメールシステムがあるため、実際のメール送信ではそれほど問題は発生しないでしょう。

依存関係注入との組み合わせ

.NET Coreの実際の開発では、依存関係注入は欠かせない開発パターンとなっています。もし.NET Coreでプロジェクトを開発しているのに依存関係注入に触れたことがないのであれば、まずは自己反省が必要です。FluentEmailは時代に即したコンポーネントであり、依存関係注入と組み合わせて使用することもできます。この方法を使えば、登録時にいくつかのデフォルト設定を一括で構成できます。この操作には追加のパッケージは必要ありません。Smtpを使用する場合はFluentEmail.Smtpパッケージを、Razorテンプレートを使用する場合はFluentEmail.Razorパッケージを導入してください。注入に関するこの部分の機能は、FluentEmail.Coreパッケージに含まれています。

public void ConfigureServices(IServiceCollection services)
{
    SmtpClient smtp = new SmtpClient
    {
        //smtpサーバーアドレス(ここでは126メールを例にしています。実際に使用するメールに応じて設定してください)
        Host = "smtp.qq.com",
        UseDefaultCredentials = true,
        DeliveryMethod = SmtpDeliveryMethod.Network,
        //ここにsmtpサーバーのユーザー名とパスワードを入力します
        Credentials = new NetworkCredential("zhangsan@qq.com", "zhangsan")
    };
    //注入時にデフォルト設定を追加できます
    services
        //デフォルト送信者を設定
        .AddFluentEmail("zhangsan@qq.com")
        //razorテンプレートサポートを追加
        //.AddRazorRenderer($"{Directory.GetCurrentDirectory()}/Views")
        .AddRazorRenderer()
        //デフォルトのsmtpサービス情報を設定
        .AddSmtpSender(smtp);
}

メールを送信するクラスでは、IFluentEmailを直接注入します。心配はいりません。上記で使用したEmailクラスはIFluentEmailインターフェースを実装しているため、使用方法は完全に同じです。

public async Task<IActionResult> SendEmail([FromServices]IFluentEmail email)
{
     var result = await email
        //送信者
        .From("zhangsan@126.com")
        //受信者
        .To("lisi@qq.com")
        //CC
        .CC("admin@126.com")
        //メールタイトル
        .Subject("メールタイトル")
        //メール本文
       .Body("メール内容").SendAsync();
    return View();
}

Razorビューテンプレート関連の内容を送信する必要がある場合も、おなじみのレシピ、おなじみの味で、全く違いはありません。登録時に追加したデフォルト設定を省略するだけです。

public async Task<IActionResult> SendEmail([FromServices]IFluentEmail email)
{
     var template = "你好@Model.Name先生, 请核实您的电话号码是否为@Model.Phone";
     var result = await email
        .From("lisi@126.com")
        .To("zhangsan@qq.com")
        .Subject("手机号核实")
        //カスタムPOCOクラスを渡す
        //.UsingTemplate<UserInfo>(template, new UserInfo { Name = "张三", Phone吗 = "100110119120" })
        //または匿名オブジェクトを渡す
        .UsingTemplate(template, new { Name = "张三", Phone吗 = "100110119120" })
        .SendAsync();
    return View();
}

まとめ

FluentEmailの基本的な使用方法についてはこれくらいにします。個人的には、その機能は非常に強力で、使用方法も非常にシンプルだと感じています。正直なところ、以前FluentEmailに触れるまでは、他の言語で統合されたメール送信コンポーネント(例えばSpring Bootのspring-boot-starter-mail)の強力さをよく見かけていました。後に偶然FluentEmailを知り、非常に嬉しく思いました。その強力な機能と使いやすさ、そして.NET Coreと組み合わせてさらに使用方法を最適化できる点が素晴らしいです。少なくとも.NETや.NET Coreでも、非常に便利なメール送信コンポーネントを手に入れたと言えるでしょう。FluentEmailの作者は、より多くの開発者にFluentEmailの開発と実践に参加してほしいと呼びかけています。最後に、再度GitHubアドレスhttps://github.com/lukencode/FluentEmail を掲載します。興味のある方はぜひ学んでみてください。ついでにStarを忘れずに。

さらに探索

関連読書

その他の記事
同じカテゴリ / 同じタグ 2024/01/19

.NET ベースの FluentValidation 検証チュートリアル

FluentValidationは、.NETベースの検証フレームワークで、オープンソースかつ無料、そしてエレガントです。チェーン操作をサポートし、理解しやすく、機能が充実しています。さらに、MVC5、WebApi2、ASP.NET Coreと深く統合でき、コンポーネント内には十数種類の一般的なバリデーターが用意されており、拡張性が高く、カスタムバリデーターをサポートし、ローカライズ多言語にも対応しています。

続きを読む
同じカテゴリ / 同じタグ 2023/01/11

gRPC入門と実践(.NET編)

長らく、フロントエンドとバックエンドのやり取りにはWebApi + JSON方式を使用し、バックエンドサービス間の呼び出しも同様でした

続きを読む