今回はC#で簡単にEメール送信機能を作る方法を解説します。
本記事では、以下について説明します。
- C#でメール送信機能を作るにはどういう方法があるのか?
- Gmailのアプリパスワードを使ってSMTPでメール送信する方法
- Blazorアプリのアカウント認証にEメール送信を組み込む方法
次のような人にとって役立つ内容かと思います。
C#でとにかく簡単にEメール送信機能を作りたい!
Blazorアプリの認証機能でメール送信ってどうやって実装すればよいの?
BlazorアプリのHello Worldアプリの作り方については以下の記事で紹介しましたが、サンプルアプリの認証機能にはEメール送信機能がありませんでした。
認証基盤がここまでできているのに、「肝心なEメール送信機能だけない!!」と思った方もいるのではないでしょうか。
このBlazorのサンプルアプリを題材として、Eメール送信機能をつける方法も紹介します。
Eメール送信はWebアプリ開発で欠かせない機能の1つですね。
YouTubeの動画でも解説しています。
講義:C#でメール送信するにはどういう方法がある?
C#等のプログラムからメールを送信する場合、基本的には以下のようになります。
C#プログラムから外部のメール送信サービス(例:Gmail)へ、何らかの手続(例:SMTP)に従ってメール送信の指示を行います。
そして、メール送信サービスから実際にメールが送信され、ユーザへメールが届きます。
具体的な「メール送信サービス」の選択肢としては以下があります。
- 一般的なメールプロバイダ
- 専門のメール送信サービス
- ホスティングサービスのメール機能
- 自己ホスティングのSMTPサーバ
それぞれを解説します。
①一般的なメールプロバイダ
GmailやYahoo! Mailのような一般的なメールプロバイダを使ってメールを送信します。
例えばSMTP(Simple Mail Transfer Protocol)、OAuthといったプロトコルを用いて、 C#プログラムから接続してメール送信を行います。
これらのサービスは通常1日あたりの送信メール数に制限があるため、大量のメールを送信する場合は適していません。
比較的簡単なので、初心者におすすめできる方法です!
演習ではこれを使います。
②専門のメール送信サービス
専門のメール送信サービスは、大量のメール配信に特化しています。
SendGrid、Amazon SES(Simple Email Service)などがあります。
これらは、例えば提供されている専用ライブラリを使ってメール送信を行います。
③ホスティングサービスのメール機能
ConoHa等のウェブホスティングサービスを利用すると、独自ドメインのメールアドレスを利用してメールを送信できます。
ドメインとの連携やセキュリティの設定などで、一般的なメールプロバイダを使うよりもやや複雑になる場合もあります。
④自己ホスティングのメール機能
サーバー上で直接メールサービスを運営する方法です。
完全なコントロールとカスタマイズが可能になりますが、設定や管理が複雑で、セキュリティやスパム対策などの維持も自己責任となります。
どれを使えばよいのか?
①~④についてどれを使えばよいか、ざっくり整理すると以下になります。
- 小規模アプリや個人利用
→①一般的なメールプロバイダ - 中規模以上、メール送信量多い
→②専門のメール送信サービス、③ホスティングサービスのメール機能 - 特定のニーズがあり、高度な技術もある
→④自己ホスティングのメール機能
初心者にもおすすめな「①一般的なメールプロバイダ」のアプローチで、Gmail・アプリパスワードを使った簡単な方法を紹介します。
演習1:Eメールを送信するコンソールC#アプリ
Gmail・アプリパスワードを使い、C#からメール送信する機能を実装してみましょう。
まずは基本を理解するために、メール送信するだけのコンソールアプリとして実装します。
以下の手順になります。
- ①Googleアカウントを作成し、二段階認証を設定する
- ②Gmailでアプリパスワードを作成する
- ③C#でSMTPを使ってメールを送信する機能を実装する
ソースコード一式はGitHubに置きました。
①Googleアカウントを作成し、二段階認証を設定
この手順はWeb上などで解説記事が多くあるかと思うので、それを参考にしてください。
ここで二段階認証を設定しておかないとアプリパスワードの作成ができないため注意してください。
普段使っているGoogleアカウントを使うことも可能です。
ただし、万が一アプリパスワードが流出した場合に、自身のメールへも不正アクセスされるリスクがあります。
できればメール送信専用のアカウントを別途用意することを強くおすすめします。
②Gmailでアプリパスワードを設定
Googleアカウントのトップ画面で、「セキュリティ」を選択します。
次に「2段階認証プロセス」を選択します。
(あらかじめ、2段階認証を設定しておきましょう)
アプリパスワードの欄にある「>」アイコンをクリックしましょう。
アプリ名には任意の名前をつけ(ここでは「testapp1」)、「作成」をクリックします。
すると、生成されたアプリパスワード「xx xx xx xx」が表示されます。
一度画面を閉じると再度表示することはできないため、メモをとっておきましょう。
アプリパスワードを使うとメール情報へのアクセスが可能となります。
流出しないよう注意して保管してください。
これでGmail側の設定は完了です!
③C#でSMTPを使ってメールを送信する機能を実装
Visual Studio 2022をインストールしていることを前提とします。
Visual Studioのインストールについては以下の記事を参考にしてください。
まず、C#コンソールアプリのプロジェクトを作成します。
Visual Studioを起動して新規プロジェクト作成で「コンソール アプリ」を作成しましょう。途中のオプションは全てデフォルトのままでよいです。
プロジェクトが作成されて開かれたら、「Program.cs」を次のように修正しましょう。
using System.Net.Mail;
using System.Net;
class Program
{
static async Task Main(string[] args)
{
string fromEmail = Environment.GetEnvironmentVariable("GMAIL_ADDRESS");
string fromUserName = "メール自動送信システム";
var fromAddress = new MailAddress(fromEmail, fromUserName);
string fromPassword = Environment.GetEnvironmentVariable("GMAIL_APP_PASSWORD");
string toEmail = "destination@example.com"; // ★送信先メールアドレス
string toUserName = "Destination User"; // ★送信先ユーザー名
var toAddress = new MailAddress(toEmail, toUserName);
string subject = "テストメール";
string body = "これはテストメールです。";
using (var message = new MailMessage(fromAddress, toAddress)
{
Subject = subject,
Body = body
})
{
var smtp = new SmtpClient
{
Host = "smtp.gmail.com",
Port = 587,
EnableSsl = true,
DeliveryMethod = SmtpDeliveryMethod.Network,
UseDefaultCredentials = false,
Credentials = new NetworkCredential(fromAddress.Address, fromPassword)
};
await smtp.SendMailAsync(message);
}
}
}
プログラムコードの以下の部分は、テスト用の送信先のメールアドレスや名前を入力してください。
string toEmail = "destination@example.com"; // ★送信先メールアドレス
string toUserName = "Destination User"; // ★送信先ユーザー名
送信用Gmailアドレス、アプリパスワードはEnvironment.GetEnvironmentVariable(…)で環境変数から読み込むようにしています。
デバッグ実行用の環境変数は、Visual Studioの「デバッグ>【プロジェクト名】のデバッグプロパティ」を選択して設定しましょう。
以下のように、GMAIL_ADDRESSとGMAIL_APP_PASSWORDをそれぞれ設定しましょう。
GMAIL_ADDRESSは作成したアカウントのGmailアドレス、GMAIL_APP_PASSWORDは取得した「xx xx xx xx」という形式のアプリパスワードです。
設定すると、以下のようにプロジェクト配下にPropaties/launchSetting.jsonというファイルが自動生成されます。
ここに設定が保存されています。
デバッグ実行
プログラムをデバッグ実行してみましょう。(ショートカットキーだと「F5」)
送信先として設定したメールアドレスへメールが届くはずです。
アプリパスワードはコード中に直接記述してGitHubなどで意図せず公開してしまわないよう注意しましょう。
「Propaties/launchSetting.json」に記述しているため、Gitで管理する場合にはこのファイルを除外するなどしたほうがよいでしょう。
また、リリース版を実行するときにも環境変数GMAIL_ADDRESS、GMAIL_APP_PASSWORDを適切に設定する必要があります。
これで、C#でEメール送信を行う基本的な実装ができましたね!
演習2:BlazorアプリへEメール送信機能を組み込む
作りたいもの
C#によるEmail送信の応用として、BlazorサンプルアプリにEメール送信機能を組み込んでみましょう。
具体的には、サンプルアプリの認証基盤で未実装となっているユーザ登録時のEメール送信機能を作ってみましょう。
Blazorサンプルアプリを作成してデバッグ実行するまでの詳しい手順は以下の記事でも紹介しています。
まずはプロジェクトを配置するフォルダを作成し、シェル(PowerShell等)でそのフォルダへ移動しましょう。
そして以下のコマンドでBlazorサンプルアプリのプロジェクトを作成します。
dotnet new blazor -n BlazorMailApp -o BlazorMailApp -f net8.0 --interactivity Auto -au Individual --use-local-db false
BlazorMailAppフォルダに「BlazorMailApp.sln」ファイルができているので、これをVisual Studioで開きましょう。
このサンプルアプリには認証基盤がついていますが、ユーザが登録したメールアドレスへメールを送信して確認する機能は未実装です。
以下のように、「そのページで確認コード付きのリンクをクリックすればOK」という仮の実装になっています。
ちゃんと登録されたメールへ確認コードを送信しないと、本当に登録者の持っているメールアドレスかどうかがわかりませんね。。。
演習2では演習1と同じ方法を使って、この確認メールを送る機能を実装します。
Blazorへメール送信機能を実装
以下の手順で実装します。
- 手順1:CustomEmailSenderクラスを実装
- 手順2:BlazorMailAppプロジェクトのProgram.csを修正
- 手順3:環境変数を設定
ソースコード一式はGitHubに置きました。
手順1:CustomEmailSenderクラスを実装
Blazorではアプリケーションのサービスとして、メール送信を行うクラスを登録しておけば、登録時のメール送信時にそのクラスが使われます。
演習1のコードの大部分を流用して簡単に実装できます。
まずは、以下のようにメール送信を行うクラスを、IEmailSenderインターフェイスを実装して作成しましょう。
インターフェイスについては以下の記事でも解説しています。
例えば、BlazorMailAppプロジェクト(サーバ側プロジェクト)のDataフォルダに、Data/EmailSender/CustomEmailSender.csというファイルを作成します。
フォルダを選択し、「右クリック>追加」で「新しい項目/新しいフォルダー」を選択してC#ファイルやフォルダを追加しましょう。
CustomEmailSender.csは以下のように書きましょう。
using Microsoft.AspNetCore.Identity;
using System.Net.Mail;
using System.Net;
namespace BlazorMailApp.Data
{
public class CustomEmailSender : IEmailSender<ApplicationUser>
{
public async Task SendConfirmationLinkAsync(ApplicationUser user, string email, string confirmationLink)
{
string fromEmail = Environment.GetEnvironmentVariable("GMAIL_ADDRESS");
string fromUserName = "メール自動送信システム";
var fromAddress = new MailAddress(fromEmail, fromUserName);
string fromPassword = Environment.GetEnvironmentVariable("GMAIL_APP_PASSWORD");
string toEmail = email; //★(a)送信先メールアドレス
string toUserName = user.UserName; //★(b)送信先ユーザー名
var toAddress = new MailAddress(toEmail, toUserName);
string subject = "アカウント確認のリンク";
//★(c)HTMLエンコードされたリンクをデコードする
string decodedLink = System.Net.WebUtility.HtmlDecode(confirmationLink);
//★(d)メール本文へのリンクの埋め込み
string body = $"以下のリンクをクリックしてアカウントを確認してください: {decodedLink}";
using (var message = new MailMessage(fromAddress, toAddress)
{
Subject = subject,
Body = body
})
{
var smtp = new SmtpClient
{
Host = "smtp.gmail.com",
Port = 587,
EnableSsl = true,
DeliveryMethod = SmtpDeliveryMethod.Network,
UseDefaultCredentials = false,
Credentials = new NetworkCredential(fromAddress.Address, fromPassword)
};
await smtp.SendMailAsync(message);
}
}
public Task SendPasswordResetLinkAsync(ApplicationUser user, string email, string resetLink)
{
//Todo : パスワードリセット用のリンクを送信する
throw new NotImplementedException();
}
public Task SendPasswordResetCodeAsync(ApplicationUser user, string email, string resetCode)
{
//Todo : パスワードリセット用のコードを送信する
throw new NotImplementedException();
}
}
}
今回はSendConfirmationLinkAsyncのみを実装します。
インターフェイスを実装する場合、インターフェイスがもつメソッドを全て実装する必要があります。
なので、SendPasswordResetLinkAsync、SendPasswordResetCodeAsyncへとりあえずNotImplementedException例外を発生させる処理を実装しています。
SendConfirmationLinkAsyncが実装できれば、他のメソッドも同じ考え方で実装できるかと思います。
SendConfirmationLinkAsyncの実装をみると、ほとんど演習1のコードそのままであることがわかるかと思います。
ポイントは以下の(a)~(d)です。
…
public async Task SendConfirmationLinkAsync(ApplicationUser user, string email, string confirmationLink)
{
…
string toEmail = email; //★(a)送信先メールアドレス
string toUserName = user.UserName; //★(b)送信先ユーザー名
var toAddress = new MailAddress(toEmail, toUserName);
string subject = "アカウント確認のリンク";
//★(c)HTMLエンコードされたリンクをデコードする
string decodedLink = System.Net.WebUtility.HtmlDecode(confirmationLink);
//★(d)メール本文へのリンクの埋め込み
string body = $"以下のリンクをクリックしてアカウントを確認してください: {decodedLink}";
…
(a),(b)で登録されたメールアドレス・送信先ユーザ名について、メソッド引数user・emailを使って設定しています。
(c)では、HTMLエンコードされたリンクをデコードし、「&
」を「&
」に戻します。
(d)では、デコードしたリンクをメール本文へ埋め込んでいます。
手順2:BlazorMailAppプロジェクトのProgram.csを修正
BlazorMailAppのProgram.csで、メール送信サービス登録部分を以下のように修正しましょう。
もともと「IdentityNoOpEmailSender」となっていますが、これを自作した「CustomeEmailSender」へ入れ替えます。(Program.csの38行目あたりです。)
…
//(e) CustomeEmailSenderへ入れ替え
//builder.Services.AddSingleton<IEmailSender<ApplicationUser>, IdentityNoOpEmailSender>();
builder.Services.AddSingleton<IEmailSender<ApplicationUser>, BlazorMailApp.Data.EmailSender.CustomEmailSender>();
…
環境変数を設定
最後に演習1と同様、忘れずにデバッグ用の環境変数を設定しておきましょう。例えば、デバッグ実行にhttpsを使うならば、httpsの欄で設定しておきましょう。
GMAIL_ADDRESSは作成したアカウントのGmailアドレス、GMAIL_APP_PASSWORDは取得した「xx xx xx xx」という形式のアプリパスワードでしたね。
デバッグ実行でhttpsが選択されているかどうかは、以下を見るとわかります。
これで実装は完了です!
メール送信方法の基本がわかっていれば、それほど難しくはありませんね。
デバッグ実行
作ったプログラムをデバッグ実行してみましょう。
F5キーがデバッグ実行のショートカットキーですね!
RegisterをクリックしてRegister画面へ遷移し、メールアドレスを入力してユーザ登録をしてみましょう。
登録すると以下の「Eメールを確認してね」という画面へ遷移します。
登録したメールアドレスを確認してみると、以下のようなメールが届いているはずです。
リンクをクリックすると以下の画面が表示され、メールアドレスの確認が完了したとわかります。
これでユーザ登録が完了し、ログインできるようになっています。
認証基盤に確認リンク送信の機能を実装できました!
これで、認証基盤を本格的に使っていく土台ができましたね!
SendPasswordResetLinkAsync、SendPasswordResetCodeAsyncもほとんど同じようなコードで実装できるはずなので、試してみてくださいね。
まとめ
メール送信はWebアプリでは欠かせない機能の1つですね。
今回は、C#でメール送信機能を作る方法とその選択基準について解説しました。
Gmailのアプリパスワードを用いて、C#プログラムでSMTPによりメール送信する方法を紹介しました。
加えて、この方法を応用してBlazorアプリでユーザ登録する際に必要となるEメール送信機能を組み込むやり方も説明しました。
これで、Blazorアプリの認証基盤を実際のサービスで活用するイメージがつかめたのではないでしょうか。
引き続き、Webアプリ開発とBlazorを一緒に学んでいきましょう!