Azure.Identity+MailKitでOAuth2 POP3

Microsoftは、SMTPやPOP3,IMAPの基本認証プロトコルでのアクセス許可を9月30日よりサイト毎に順次停止していく予定だ。

これにより、基本認証を使用してPOP3やIMAPなどでメールを受信するプログラムが動作しなくなる可能性が高くなる。

これは私も承知していて、MailKitのSaslMechanismOAuth2クラスを使用してOAuth2対応にするよう修正していたのだが、その際に使用したMicrosoft.Identity.ClientMicrosoft.Graph.Authライブラリが以前書いたように、非推奨となってしまったので、Azure.Identityに変更してみた。

基本はMicrosoft Graphを使う場合と同じなのだが、注意点として、ユーザーやグループを捜査するMS GraphではスコープのPrefixが必要では無かったのだが、POP3やIMAP,SMTP等では、”https://outlook.office365.com/”のPrefix(ネームスペースなのかな?)が必要となる事。

POP3の場合は以下のようなコードとなる。

・・・
using MimeKit;
using MailKit;
using MailKit.Net.Pop3;
using MailKit.Security;
using MimeKit.Text;

using Azure.Core;
using Azure.Identity;
・・・
// この例では、Resource Owner Password Credentialsフローを使用

// スコープ
string[] scopes = new string[] { "https://outlook.office365.com/POP.AccessAsUser.All" };

var options = new TokenCredentialOptions
{
    AuthorityHost = AzureAuthorityHosts.AzurePublicCloud
};

// ユーザー名,パスワード,テナントID,アプリケーションID(Client ID)から資格情報を得る
var cred = new UsernamePasswordCredential(PopUser,PopPass,Authority,AppID,options); 

// スコープを指定してAccess Tokenの取得
var req = new TokenRequestContext(scopes);
var token = await cred.GetTokenAsync(req);

// ユーザー名とAccess Tokenを使用してOAuth2用の認証機構を作成
var oauth2 = new SaslMechanismOAuth2(PopUser, token.Token);

using (Pop3Client cli = new Pop3Client())
{
    await cli.ConnectAsync("outlook.office365.com", 995, SecureSocketOptions.SslOnConnect);
    // OAuth2で認証
    await cli.AuthenticateAsync(oauth2);
	・・・

最初、Authentication Failが発生したので、アカウントを変えたり、色々してみたが、全然だめなので、もしやと思い、スコープにPrefixを付けたら、うまく動作した。

OAuth2対応についてはネットで調べても、Microsoft.Identity.Clientを使用した例ばかりで、解決に結構時間が掛かってしまった。

takezou について

ソフトウェア開発会社(ITと言う言葉は大嫌い)で働く、元技術者。 未だに、社内システム位は作ってますが・・・ プログラミング言語はC#が好き。 好きなことだけ拾って投稿しているので、内容にはあまり期待しないでねw
カテゴリー: .NET, C#, OAuth2, 技術系 パーマリンク

Azure.Identity+MailKitでOAuth2 POP3 への9件のフィードバック

  1. takezou のコメント:

    ちなみに、SCOPEに”POP.AccessAsUser.All”と”SMTP.Send”の2つを指定して、同じトークンでSMTPの認証を行なうとエラーとなった。POPはOK。
    色々調べたが、よく分からないので、POPはPOP、SMTPはSMTPだけでトークンを取得したら、SMTP認証OK。
    全く異なるSCOPEだからなのだろうか?
    AccessToken自体は同じ物が帰ってきているようなのだが・・・
    結局サービス毎にAccessToken取らなきゃダメなのかな・・・

  2. takezou のコメント:

    色々試してみたら、SaslMechanismOAuth2で作成したSASLを使い回すことがNGのようで、SASLだけ作り直したら、ちゃんと動きました。

  3. takezou のコメント:

    ↑SaslMechanismOAuth2内にIsAuthenticatedプロパティがあって、一度認証されると、これがセットされ、それ以降は認証に使えないようだ。
    (ソース追ったらそんな感じでした。)

  4. 山下博 のコメント:

    いつもこちらの記事内容を勉強させていただいております。感謝申し上げます。
    本稿の内容についてお力を貸していただけないかと思いこちらに質問させて頂きます。
    2020年6月24日の「MailKitとOAuth2を使ったOffice365へのPOP3アクセス」の内容を参考にメール受信処理を作成し正常に受信することに成功しました。
    次のステップとしてAzureの設定内容は成功時から変更せずに本稿の内容を参考にメールの受信処理を作成しています。
    しかし、認証処理の await cli.AuthenticateAsync(oauth2); を実行すると「Authentication failed.」エラーになりメール受信ができませんでした。

    行っている内容
    scope:本稿と同じ内容を使用しています。
    POPサーバー:成功時と同じ
    ユーザー、パスワード:成功時と同じ

    この内容ならエラーの原因などお気づきの点がありましたら大変恐縮ですがご教示頂ければ幸いです。

    以上 よろしくお願いいたします。

    • takezou のコメント:

      質問ありがとうございます。
      本番で動いているプロジェクトをまるごと他のマシンに移して実行したところ、同じ現象が発生しました。
      本番機はWindows10でコピー先はWindows11です。
      原因は特定できていませんが、環境の問題だと思われます。
      答えになっていなくて申し訳ないです。

      • takezou のコメント:

        どうも、ネットワークの関係のようです。
        社内から接続した場合はOS等関係無く動作しているので。
        詳細は調べてみないと分かりませんが・・・
        DNSでも参照しているのかもしれません。

        • takezou のコメント:

          同じ端末で、インターネット接続を切替えると同じプログラムが認証NGになるので、何らかのチェックをしているのだろうと思います。
          何かは今のところハッキリしていませんが・・・

  5. 山下博 のコメント:

    ご回答を頂きありがとうございます。
    OSやネットワークに関係しているかもしれないということで大変助かります。こちらも調査を進めていきます。
    私の場合は社内ネットワーク内からwindows10で開発環境(VisualStudio2019 FW4.7.2)でデバッグモードで動作させています。

    • takezou のコメント:

      理由はわかりませんが、本日、同じプログラムを動作させたところ、モバイルWiFiからでも認証できました。
      原因が特定できていないのでチョット嫌らしいですが、MS側の問題でしょうかね?

山下博 へ返信する コメントをキャンセル

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください