以前、Office365とPOP3プロトコルを使用した、自社用安否確認システムを作成したのだが、今年の10月以降、Office365にPOPアクセスするのに基本認証方式が使えなくなるとのアナウンスが去年辺りからあり、Office365のOAuth2による認証を試験していたのだが、どうもうまく行かなくて、結構悩んだのだが、単純にSCOPEの指定の仕方だったOrz
Office365用Azure AD管理ポータルで、アプリケーションを登録して、Microsoft GraphへPOP.AccessAsUser.Allアクセス許可を設定しているのだが、このプロパティを見ると、
“https://graph.microsoft.com/POP.AccessAsUser.All”
となっている。なので、SCOPEにも当然これを指定するのだろうと思って指定していたのだが、これが間違いの元。
アクセストークンは取得できるのだが、認証時に”Authentication failed.”のエラーが出て、POP3ログインに失敗する・・・
で、実際に指定するSCOPEは以下のようにしなければいけないのであった。
“https://outlook.office365.com/POP.AccessAsUser.All”
確かに、サンプルとか見ると、そうなっていました・・・
こんな事で結構ずーっと悩んでたんだよね・・・
で、自社用の安否確認システムはWindowsサービスで動作させているので、Office365のログインダイアログを出す事は出来ない。
そこで、あまりお薦めできないけれど、一番簡単な、ユーザ名とパスワードを使用した形で、アクセストークンを取得することにした。
以下のような形でアクセストークンの取得が可能。
// OAuth2アクセストークン取得
IPublicClientApplication app = PublicClientApplicationBuilder
.Create(ApplicationID) // アプリケーション(クライアント) IDの事
.WithAuthority(Authority) // https://login.microsoftonline.com/ + テナントID
.Build();
string[] scopes = new string[] { "https://outlook.office365.com/POP.AccessAsUser.All" };
SecureString secPass = new SecureString();
・・・
// 指定するのはOffice365にログインに使用するユーザー名とパスワード
AuthenticationResult res = await app.AcquireTokenByUsernamePassword(scopes, Pop3User, secPass).ExecuteAsync();
↑のスコープをずっと間違えていたんだよね・・・でも、この時点ではエラー出ないんだよ。
で、後はMailKit.Net.Pop3Clientでの認証用のOAuth2の情報を作成して、認証を行えばPOP3で、Office365(Exchange Online)からメールを取得できる。
// OAuth2用の認証機構を作成
var oauth2 = new SaslMechanismOAuth2(Pop3User, res.AccessToken);
Pop3Client cli = new Pop3Client();
// POP3サーバー接続
await cli.ConnectAsync(Pop3Host, Pop3Port, Pop3Security);
// 認証
await cli.AuthenticateAsync(oauth2);
int count = await cli.GetMessageCountAsync();
if (count != 0)
{
// POP3からメールの受信
var msgs = await cli.GetMessagesAsync(0, count);
foreach (var msg in msgs)
{
・・・
いや~、くだらないとこで引っかかってました・・・
追記:
このサンプルで、Office365のAOuth2アクセストークンを得るには、Micrsoft.Identity.Clientパッケージが必要。