はじめに
Microsoft365のメールサーバを利用して、Windows上の.NET コンソールプログラムからメール送信をするのに、基本認証が使用出来なくなってしまったようで(※2022/12/8現在)、OAuthなる認証を使用して、Tokenを取得してからのメール送信までやってみました。
送信元となるアカウントはMicrosoft365の管理者権限を保有しないユーザを想定していますが、一部に管理者権限を必要とする操作があります。
Azure Potalでの設定(管理者権限なし)
STMP送信のAPIを利用可能なアプリの登録をします。
-
名前
には任意の名称を入力します。(ここではsend_mailとしました)
サポートされているアカウントの種類
はデフォルトのこの組織ディレクトリのみに含まれるアカウント
を選択します。
登録
ボタンを押します。
-
新規アプリが作成され、各種IDが生成されています。(マスクで隠している箇所です)
アプリケーション (クライアント) ID
、ディレクトリ (テナント) ID
はToken取得の際に必要な項目となります。
APIのアクセス許可
をクリックします。
-
検索窓
に”smtp”と入力すると、下にアクセス許可の候補として表示されます。
SMTP.Send
をチェックをして、アクセス許可の追加
ボタンを押します。
-
リダイレクト URI
はhttps://login.microsoftonline.com/common/oauth2/nativeclient
をチェックし、構成
ボタンを押します。
これはToken取得の際に必要な項目となります。
-
サポートされているアカウントの種類
はデフォルトのこの組織ディレクトリのみに含まれるアカウント
をチェックします。
パブリック クライアント フローを許可する
ー次のモバイルとデスクトップのフローを有効にする
をはい
にして、保存
ボタンを押します。
Azure Potalでの設定(※管理者権限あり)
送信元アカウントで作成したアプリに、許可を付与します。
Microsoft365管理センターでの設定(※管理者権限あり)
送信元アカウントの認証済みSMTPを有効化します。
-
送信元アカウントをクリックします。(ここではguest1@xxx.onmicrosoft.com)
メール送信(.NET C#)
Windows10Pro21H2 .NET6.0.11にて検証しました。
追加ライブラリはMicrosoft.Identity.Client 4.48.1、MailKit 3.4.3 です。
Codespaces上でも動作したので、Linux・MacOSでもいけるはず。
// Azure Portalで登録したアプリのアプリケーション (クライアント)ID
private static string CLIENT_ID = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx";
// Azure Portalで登録したアプリのディレクトリ (テナント) ID
private static string TENAMT_ID = "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx";
// M365メールのアカウント(送信元アカウント)
private static string USER_ACCOUNT = "xxx@zzz.onmicrosoft.com";
// M365メールのパスワード
private static string USER_PASSWORD = "*****";
// 送信先メールアドレス
private static string TO_MAIL_ADDRESS = "aaai@bbb.com";
static void Main(string[] args)
{
try
{
// トークン取得
var accessToken = GetAccessToken();
accessToken.Wait();
// メール送信
SendMail(accessToken.Result).Wait();
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
throw;
}
}
/// <summary>
/// トークン取得
/// </summary>
/// <returns>認証結果</returns>
public static async Task<AuthenticationResult> GetAccessToken()
{
var options = new PublicClientApplicationOptions
{
ClientId = CLIENT_ID,
TenantId = TENAMT_ID,
RedirectUri = "https://login.microsoftonline.com/common/oauth2/nativeclient" // Azure PortalのリダイレクトURI
};
var publicClientApplication = PublicClientApplicationBuilder
.CreateWithApplicationOptions(options)
.Build();
var scopes = new string[] {
"https://outlook.office.com/SMTP.Send",
};
var user = USER_ACCOUNT;
var password = USER_PASSWORD;
AuthenticationResult authToken = await publicClientApplication.AcquireTokenByUsernamePassword(scopes, user, password).ExecuteAsync();
return authToken;
}
/// <summary>
/// メール送信
/// </summary>
/// <param name="authToken">認証結果</param>
static async Task SendMail(AuthenticationResult authToken)
{
var oauth2 = new SaslMechanismOAuth2(authToken.Account.Username, authToken.AccessToken);
var message = new MimeKit.MimeMessage();
// 送信元アドレス
message.From.Add(new MimeKit.MailboxAddress("ユーザー", USER_ACCOUNT));
// 送信先アドレス
message.To.Add(new MimeKit.MailboxAddress("テスト", TO_MAIL_ADDRESS));
// CC、BCCを設定
// message.Cc.Add("a@b.com");
// message.Bcc.Add("aa@bb.com");
// メールタイトル
message.Subject = "subject";
// 本文作成
var textPart = new MimeKit.TextPart(MimeKit.Text.TextFormat.Plain);
textPart.Text = "body";
// MimeMessage作成
message.Body = textPart;
using (var client = new MailKit.Net.Smtp.SmtpClient())
{
await client.ConnectAsync("smtp.office365.com", 587, SecureSocketOptions.Auto);
await client.AuthenticateAsync(oauth2);
await client.SendAsync(message);
await client.DisconnectAsync(true);
}
return;
}
参考サイト