Graph API でメールを読むコードを書き、いざ実行したら AADSTS で始まるエラーが返ってきた。調べてみると、原因はコードではなくアプリ登録の設定だった、という流れはよくあります。特に多いのが、「委任されたアクセス許可」と「アプリケーションのアクセス許可」の取り違えと、サポートするアカウントの種類の選び間違いです。
この二つは登録の最初の段階で決まり、後から見直す人が少ない項目です。ここでは Microsoft Entra 管理センターでアプリを登録し、Mail.Read 権限を付けて動作確認するまでを、判断が必要な箇所に重点を置いて説明します。
この記事でわかること
- 委任されたアクセス許可とアプリケーションのアクセス許可の違い
- 個人用アカウントを対象にする時のアカウントの種類の選び方
- アプリ登録から Mail.Read の追加、同意までの手順
- 登録設定が原因で起きる代表的なエラーと直し方
最初に決める:委任かアプリケーションか
Mail.Read には、性質の異なる2種類があります。どちらを選ぶかで、使えるアカウントも、必要な手続きも変わります。
| 項目 | 委任されたアクセス許可 | アプリケーションのアクセス許可 |
|---|---|---|
| 誰として動くか | サインインしたユーザー本人 | アプリ自身(ユーザー不在) |
| 読めるメール | サインインしたユーザーのメールボックス | 組織内のメールボックス(制限しなければ全員分) |
| 個人用アカウント | 使える | 使えない |
| 同意 | ユーザー本人の同意で足りることが多い | 管理者の同意が必須 |
| 認証の方法 | デバイスコード、ブラウザでのサインインなど | クライアント シークレットまたは証明書 |
@outlook.com や @hotmail.com などの個人用アカウントのメールを読むなら、選択肢は委任されたアクセス許可だけです。アプリケーションのアクセス許可は、組織の Exchange Online を対象にしたバッチ処理などで使うもので、個人用アカウントには適用されません。
サポートするアカウントの種類も先に決める
登録画面の「サポートされているアカウントの種類」では、主に次の選択肢が表示されます。ここで個人用アカウントを含めないと、Outlook.com のアカウントではサインインできません。
- この組織ディレクトリのみに含まれるアカウント(シングル テナント)
- 任意の組織ディレクトリ内のアカウント(マルチテナント)
- 任意の組織ディレクトリ内のアカウントと個人用 Microsoft アカウント
- 個人用 Microsoft アカウントのみ
個人用アカウントだけを対象にするなら最後の選択肢、職場のアカウントも併用するなら3番目を選びます。選択はトークンを取得する時の認証先(authority)と対応していて、個人用アカウントでは https://login.microsoftonline.com/consumers、両方を受け付けるなら /common を使います。組み合わせが合わないとサインインの段階でエラーになります。
アプリを登録する手順
2026年10月時点の Microsoft Entra 管理センターでの手順です。Azure ポータルの「アプリの登録」からでも同じ画面に進めます。
- Microsoft Entra 管理センターにサインインし、「アプリの登録」→「新規登録」を開きます。
- アプリの名前を入力します。この名前はユーザーの同意画面にも表示されるので、用途がわかる名前にします。
- 前の章を参考に「サポートされているアカウントの種類」を選びます。
- リダイレクト URI は後から設定できるので、この時点では空欄でも構いません。
- 「登録」を押すと「概要」画面が開きます。「アプリケーション (クライアント) ID」が client_id です。控えておきます。
アプリは何らかのディレクトリ(テナント)に属する形で登録されます。個人で開発する場合も、Azure の利用登録などで用意されたディレクトリの中に登録することになります。client_id がどのように使われるかは、refresh_token と client_id の関係で詳しく説明しています。
「認証」画面の設定
スクリプトやデスクトップアプリから使う場合は、「認証」画面で次の2点を設定します。
プラットフォームの追加
「プラットフォームを追加」で「モバイル アプリケーションとデスクトップ アプリケーション」を選びます。ブラウザでサインインさせる対話型の方式を使うなら、リダイレクト URI に http://localhost を追加しておきます。Python の msal などのライブラリは、この URI で一時的に応答を受け取ります。
パブリック クライアント フローを許可する
画面下部の「パブリック クライアント フローを許可する」を「はい」にします。デバイスコードフローなど、クライアント シークレットを持たないアプリからトークンを取得する方式に必要です。この設定を忘れると、後述する AADSTS7000218 のエラーになります。
スクリプトにクライアント シークレットを埋め込むのは避けてください。配布したり共有したりした時点で、シークレットが第三者の手に渡ります。ユーザー本人がサインインする使い方なら、パブリック クライアントとして構成するのが基本です。
Mail.Read を追加して同意する
- 「API のアクセス許可」を開き、「アクセス許可の追加」を選びます。
- 「Microsoft Graph」→「委任されたアクセス許可」を選びます。
- 検索欄に Mail と入力し、
Mail.Readにチェックを入れて追加します。 - リフレッシュトークンを使って長期間動かすなら、
offline_accessも追加します。既定で入っているUser.Readはそのままで構いません。
個人用アカウントの場合、同意は初回サインイン時にユーザー本人が行います。組織のアカウントで、テナントの設定によりユーザー自身が同意できない場合は、管理者が「管理者の同意を与えます」を実行します。アプリケーションのアクセス許可を使う場合は、管理者の同意が必ず必要です。
必要以上の権限は付けないのが原則です。読むだけなら Mail.Read で足り、Mail.ReadWrite や Mail.Send は不要です。権限が増えるほど、トークンが漏れた時の影響も大きくなります。
組織でアプリケーションのアクセス許可を使う場合は、Exchange Online 側でアプリがアクセスできるメールボックスを絞り込む仕組みも用意されています。対象を限定できるなら設定しておくと安全です。仕様は Microsoft Graph のアクセス許可のリファレンスで確認できます。
動作を確認する
トークンが取得できたら、最新のメールを1件だけ取得して、権限が正しく効いているかを確かめます。$ACCESS_TOKEN には取得したアクセストークンを入れます。
curl -H "Authorization: Bearer $ACCESS_TOKEN" \
"https://graph.microsoft.com/v1.0/me/messages?\$top=1&\$select=subject,receivedDateTime"
件名と受信日時が JSON で返ってくれば成功です。403 が返る場合は、トークンに Mail.Read が含まれていない可能性があります。jwt の中身を確認できるツールでアクセストークンの scp を見ると、実際に付与された権限がわかります(個人用アカウントのトークンは中身を読めない形式のこともあります)。Python で続きを書く場合は、Microsoft Graph API でメールを取得する方法のコードがそのまま使えます。
登録設定が原因のエラー
| エラー | 原因 | 見直す場所 |
|---|---|---|
AADSTS700016 | client_id が見つからない。登録先と認証先の組み合わせが合っていない | 概要の client_id と、authority の指定 |
AADSTS7000218 | シークレットなしでトークンを要求したが、パブリック クライアントが許可されていない | 認証画面の「パブリック クライアント フローを許可する」 |
AADSTS65001 | ユーザーまたは管理者がまだ同意していない | API のアクセス許可と同意の状態 |
AADSTS50011 | リダイレクト URI が登録されたものと一致しない | 認証画面のリダイレクト URI |
| サインイン時に個人用アカウントが拒否される | アカウントの種類に個人用が含まれていない | サポートされているアカウントの種類 |
なお、IMAP で接続する場合は Graph の Mail.Read ではなく、IMAP 用のスコープが必要です。一つのアクセストークンは一つのリソース向けに発行されるため、Graph 用のトークンで IMAP にログインすることはできません。IMAP を使う方法はPython で Outlook に XOAUTH2 接続する方法で扱っています。
よくある質問
Mail.Read と Mail.ReadBasic の違いは何ですか?
Mail.ReadBasic では本文や添付ファイルを除いた情報だけが読めます。件名や差出人だけで足りる用途なら、より範囲の狭い Mail.ReadBasic を選ぶ方法もあります。
登録したアプリを削除するとどうなりますか?
その client_id で発行されたトークンは使えなくなり、リフレッシュトークンによる更新もできなくなります。使っていないアプリは削除しておくのが安全です。
他人の Outlook.com のメールを読めるように設定できますか?
委任されたアクセス許可では、読めるのはサインインした本人のメールだけです。他人のメールを読むには、その人自身がサインインして同意する必要があります。
クライアント シークレットには有効期限がありますか?
はい。作成時に期限を選び、期限が切れると使えなくなります。シークレットを使う構成では、期限が来る前に新しいものを発行して差し替える運用が必要です。
まとめ
- 個人用アカウントのメールを読むなら、委任されたアクセス許可の Mail.Read を使う
- アカウントの種類と authority(/consumers・/common)の組み合わせを合わせる
- スクリプトから使う時は「パブリック クライアント フローを許可する」をオンにする
- 権限は必要最小限にし、長期運用なら offline_access を追加する
Graph API や OAuth2 での接続を検証したい方向けに、Hotmail・Outlook(OAuth2対応)のアカウントも取り扱っています。



