最近 OAuth 2.0のサポート のサポートが発表されました。以下 ガイド を設定しましたアプリケーションのアクセス許可とIMAPおよびSMTP接続。アプリケーションはAccounts in any organizational directory (Any Azure AD directory - Multitenant)
として構成され、 認証コードフロー を使用します。
承認には以下のURLが使用されます。
また、次のDelegated Microsoft Graphスコープが追加されました。
スコープ、コードからのリクエスト:
final List<String> scopes = Arrays.asList(
"offline_access",
"email",
"openid",
"profile",
"User.Read",
"Mail.ReadWrite",
"https%3A%2F%2Foutlook.office365.com%2FIMAP.AccessAsUser.All",
"https%3A%2F%2Foutlook.office365.com%2FSMTP.Send"
);
アクセストークンと更新トークンを正常に受信しました。
{
"token_type": "Bearer",
"scope": "email IMAP.AccessAsUser.All Mail.ReadWrite openid profile SMTP.Send User.Read",
"expires_in": 3599,
"ext_expires_in": 3599,
"access_token": "edited",
"refresh_token": "edited",
"id_token": "edited"
}
IMAPへの接続に使用されるコードは次のとおりです。
Properties props = new Properties();
props.put("mail.imap.ssl.enable", "true");
props.put("mail.imaps.sasl.enable", "true");
props.put("mail.imaps.sasl.mechanisms", "XOAUTH2");
props.put("mail.imap.auth.login.disable", "true");
props.put("mail.imap.auth.plain.disable", "true");
props.put("mail.debug", "true");
props.put("mail.debug.auth", "true");
Session session = Session.getInstance(props);
session.setDebug(true);
String userEmail = "[email protected]";
String accessToken = "access_token_received_on_previous_step";
final Store store = session.getStore("imaps");
store.connect("Outlook.office365.com", 993, userEmail, accessToken);
次の出力が生成されます。
DEBUG: JavaMail version 1.6.2
DEBUG: successfully loaded resource: /META-INF/javamail.default.address.map
DEBUG: setDebug: JavaMail version 1.6.2
DEBUG: getProvider() returning javax.mail.Provider[STORE,imaps,com.Sun.mail.imap.IMAPSSLStore,Oracle]
DEBUG IMAPS: mail.imap.fetchsize: 16384
DEBUG IMAPS: mail.imap.ignorebodystructuresize: false
DEBUG IMAPS: mail.imap.statuscachetimeout: 1000
DEBUG IMAPS: mail.imap.appendbuffersize: -1
DEBUG IMAPS: mail.imap.minidletime: 10
DEBUG IMAPS: enable SASL
DEBUG IMAPS: SASL mechanisms allowed: XOAUTH2
DEBUG IMAPS: closeFoldersOnStoreFailure
DEBUG IMAPS: trying to connect to Host "Outlook.office365.com", port 993, isSSL true
* OK The Microsoft Exchange IMAP4 service is ready. [QQBNADc...]
A0 CAPABILITY
* CAPABILITY IMAP4 IMAP4rev1 AUTH=PLAIN AUTH=XOAUTH2 SASL-IR UIDPLUS MOVE ID UNSELECT CHILDREN IDLE NAMESPACE LITERAL+
A0 OK CAPABILITY completed.
DEBUG IMAPS: AUTH: PLAIN
DEBUG IMAPS: AUTH: XOAUTH2
DEBUG IMAPS: protocolConnect login, Host=Outlook.office365.com, [email protected], password=<non-null>
DEBUG IMAPS: SASL Mechanisms:
DEBUG IMAPS: XOAUTH2
DEBUG IMAPS:
DEBUG IMAPS: SASL client XOAUTH2
DEBUG IMAPS: SASL callback length: 2
DEBUG IMAPS: SASL callback 0: javax.security.auth.callback.NameCallback@17046283
DEBUG IMAPS: SASL callback 1: javax.security.auth.callback.PasswordCallback@5bd03f44
A1 AUTHENTICATE XOAUTH2 dXNlcj1o...
A1 NO AUTHENTICATE failed.
Exception in thread "main" javax.mail.AuthenticationFailedException: AUTHENTICATE failed.
at com.Sun.mail.imap.IMAPStore.protocolConnect(IMAPStore.Java:732)
at javax.mail.Service.connect(Service.Java:366)
また、SMTPへの接続には次のコードが使用されます。
Properties props = new Properties();
props.put("mail.smtp.auth", "true");
props.put("mail.transport.protocol", "smtp");
props.put("mail.smtp.starttls.enable", "true");
props.put("mail.smtp.auth.mechanisms", "XOAUTH2");
props.put("mail.smtp.auth.login.disable","true");
props.put("mail.smtp.auth.plain.disable","true");
props.put("mail.debug.auth", "true");
Session session = Session.getInstance(props);
session.setDebug(true);
String userEmail = "[email protected]";
String accessToken = "access_token_received_on_previous_step";
Transport transport = session.getTransport("smtp");
transport.connect("smtp.office365.com", 587, userEmail, accessToken);
以下の出力を提供します:
DEBUG: setDebug: JavaMail version 1.6.2
DEBUG: getProvider() returning javax.mail.Provider[TRANSPORT,smtp,com.Sun.mail.smtp.SMTPTransport,Oracle]
DEBUG SMTP: useEhlo true, useAuth true
DEBUG SMTP: trying to connect to Host "smtp.office365.com", port 587, isSSL false
220 AM5PR0701CA0005.Outlook.office365.com Microsoft ESMTP MAIL Service ready at Mon, 4 May 2020 15:52:28 +0000
DEBUG SMTP: connected to Host "smtp.office365.com", port: 587
EHLO ubuntu-B450-AORUS-M
250-AM5PR0701CA0005.Outlook.office365.com Hello [my ip here]
250-SIZE 157286400
250-PIPELINING
250-DSN
250-ENHANCEDSTATUSCODES
250-STARTTLS
250-8BITMIME
250-BINARYMIME
250-CHUNKING
250 SMTPUTF8
DEBUG SMTP: Found extension "SIZE", arg "157286400"
DEBUG SMTP: Found extension "PIPELINING", arg ""
DEBUG SMTP: Found extension "DSN", arg ""
DEBUG SMTP: Found extension "ENHANCEDSTATUSCODES", arg ""
DEBUG SMTP: Found extension "STARTTLS", arg ""
DEBUG SMTP: Found extension "8BITMIME", arg ""
DEBUG SMTP: Found extension "BINARYMIME", arg ""
DEBUG SMTP: Found extension "CHUNKING", arg ""
DEBUG SMTP: Found extension "SMTPUTF8", arg ""
STARTTLS
220 2.0.0 SMTP server ready
EHLO ubuntu-B450-AORUS-M
250-AM5PR0701CA0005.Outlook.office365.com Hello [my ip here]
250-SIZE 157286400
250-PIPELINING
250-DSN
250-ENHANCEDSTATUSCODES
250-AUTH LOGIN XOAUTH2
250-8BITMIME
250-BINARYMIME
250-CHUNKING
250 SMTPUTF8
DEBUG SMTP: Found extension "SIZE", arg "157286400"
DEBUG SMTP: Found extension "PIPELINING", arg ""
DEBUG SMTP: Found extension "DSN", arg ""
DEBUG SMTP: Found extension "ENHANCEDSTATUSCODES", arg ""
DEBUG SMTP: Found extension "AUTH", arg "LOGIN XOAUTH2"
DEBUG SMTP: Found extension "8BITMIME", arg ""
DEBUG SMTP: Found extension "BINARYMIME", arg ""
DEBUG SMTP: Found extension "CHUNKING", arg ""
DEBUG SMTP: Found extension "SMTPUTF8", arg ""
DEBUG SMTP: protocolConnect login, Host=smtp.office365.com, [email protected], password=<non-null>
DEBUG SMTP: Attempt to authenticate using mechanisms: XOAUTH2
DEBUG SMTP: Using mechanism XOAUTH2
AUTH XOAUTH2 dXNlcj1obW9kaUB...
535 5.7.3 Authentication unsuccessful [AM5PR0701CA0005.eurprd07.prod.Outlook.com]
Exception in thread "main" javax.mail.AuthenticationFailedException: 535 5.7.3 Authentication unsuccessful [AM5PR0701CA0005.eurprd07.prod.Outlook.com]
at com.Sun.mail.smtp.SMTPTransport$Authenticator.authenticate(SMTPTransport.Java:965)
at com.Sun.mail.smtp.SMTPTransport.authenticate(SMTPTransport.Java:876)
at com.Sun.mail.smtp.SMTPTransport.protocolConnect(SMTPTransport.Java:780)
at javax.mail.Service.connect(Service.Java:366)
私が試したもの:
https://graph.Microsoft.com/SMTP.Send
およびSMTP.Send
として指定するhttps://login.microsoftonline.com/common/
urlを使用結果は常に同じです。
それは私が間違っていることですか、それともマイクロソフト側からのサポートのどこかにバグがありますか?
更新1:
コマンドラインから試したが、同じ結果:
$ openssl s_client -crlf -connect Outlook.office365.com:993
... connection part omitted
* OK The Microsoft Exchange IMAP4 service is ready. [QQBNADYAUAAxADkAMgBDAEEAMAAwADkAMQAuAEUAVQBSAFAAMQA5ADIALgBQAFIATwBEAC4ATwBVAFQATABPAE8ASwAuAEMATwBNAA==]
C01 CAPABILITY
* CAPABILITY IMAP4 IMAP4rev1 AUTH=PLAIN AUTH=XOAUTH2 SASL-IR UIDPLUS ID UNSELECT CHILDREN IDLE NAMESPACE LITERAL+
C01 OK CAPABILITY completed.
A01 AUTHENTICATE XOAUTH2 dXNlcj1obW9kaUBjb...
A01 NO AUTHENTICATE failed.
* BYE Connection is closed. 13
read:errno=0
更新2:
次の権限を持つAzure Portalで新しいアプリケーションを作成しようとしました:
スコープの同意を試みたときに、次の画面が表示されます。
Azureポータルからのアクセス許可では管理者の同意が必要であることが指定されておらず、IMAPおよびSMTPスコープが要求されたときに以前のアプリ登録でそのような画面が表示されないため、これは奇妙です。
更新3:
この投稿へのコメントのおかげで、次のスコープを試しました。
public static final List<String> SCOPES = Arrays.asList(
"offline_access",
"https%3A%2F%2Foutlook.office365.com%2FIMAP.AccessAsUser.All",
"https%3A%2F%2Foutlook.office365.com%2FSMTP.Send"
);
これは私に以下のトークンを与えました:
{
"token_type": "Bearer",
"scope": "https://Outlook.office365.com/IMAP.AccessAsUser.All https://Outlook.office365.com/SMTP.Send",
"expires_in": 3599,
"ext_expires_in": 3599,
"access_token": "eyJ0eXAiOiJKV1....",
"refresh_token": "OAQABAAAAAAAm...."
}
IMAP/SMTP authは成功しましたそして、受信トレイを読んだり、メールを送信したりできました!
しかし、私のアプリケーションでは、いくつかのMS Graph APIエンドポイント(ユーザープロファイルの読み取り、メッセージのサブスクリプション、メッセージの削除)を使用するために、他のスコープもいくつか必要です。
だから私は別のスコープを試しました:
public static final List<String> SCOPES = Arrays.asList(
"offline_access",
"User.Read",
"Mail.ReadWrite",
"https%3A%2F%2Foutlook.office365.com%2FIMAP.AccessAsUser.All",
"https%3A%2F%2Foutlook.office365.com%2FSMTP.Send"
);
これはトークンを与えました(スコープの値は実際に機能したトークンとは異なり、アクセス許可にはOutlookのURLがないことに注意してください):
{
"token_type": "Bearer",
"scope": "IMAP.AccessAsUser.All Mail.ReadWrite SMTP.Send User.Read profile openid email",
"expires_in": 3599,
"ext_expires_in": 3599,
"access_token": "eyJ0eXAiOiJKV1Q...",
"refresh_token": "OAQABAAAAAAAm..."
}
以前に得た結果につながった:
A1 NO AUTHENTICATE failed.
すべてのスコープをURLとして試す:
public static final List<String> SCOPES = Arrays.asList(
"offline_access", // or "https%3A%2F%2Fgraph.Microsoft.com%2Foffline_access"
"https%3A%2F%2Fgraph.Microsoft.com%2FUser.Read",
"https%3A%2F%2Fgraph.Microsoft.com%2FMail.ReadWrite",
"https%3A%2F%2Foutlook.office365.com%2FIMAP.AccessAsUser.All",
"https%3A%2F%2Foutlook.office365.com%2FSMTP.Send"
);
トークンの取得時に次のエラーが発生します(同意ステップが正常に渡されます)。
{
"error": "invalid_request",
"error_description": "AADSTS28000: Provided value for the input parameter scope is not valid because it contains more than one resource. Scope offline_access https://graph.Microsoft.com/user.read https://graph.Microsoft.com/mail.readwrite https://Outlook.office365.com/imap.accessasuser.all https://Outlook.office365.com/smtp.send is not valid.\r\nTrace ID: c3282396-6231-4e11-8300-77bc2ca57f00\r\nCorrelation ID: 5f5145bf-7114-4e6c-ab11-30e7ff84a056\r\nTimestamp: 2020-05-06 08:08:48Z",
"error_codes": [
28000
],
"timestamp": "2020-05-06 08:08:48Z",
"trace_id": "c3282396-6231-4e11-8300-77bc2ca57f00",
"correlation_id": "5f5145bf-7114-4e6c-ab11-30e7ff84a056"
}
そして、すべてのスコープにMicrosoftグラフ(Azureポータルからコピーされたもの)を持たせると
public static final List<String> SCOPES = Arrays.asList(
"https%3A%2F%2Fgraph.Microsoft.com%2Foffline_access",
"https%3A%2F%2Fgraph.Microsoft.com%2FUser.Read",
"https%3A%2F%2Fgraph.Microsoft.com%2FMail.ReadWrite",
"https%3A%2F%2Fgraph.Microsoft.com%2FIMAP.AccessAsUser.All",
"https%3A%2F%2Fgraph.Microsoft.com%2FSMTP.Send"
);
次のトークンを返します(offline_accessが要求されていても、更新トークンなし)
{
"token_type": "Bearer",
"scope": "profile openid email https://graph.Microsoft.com/IMAP.AccessAsUser.All https://graph.Microsoft.com/Mail.ReadWrite https://graph.Microsoft.com/SMTP.Send https://graph.Microsoft.com/User.Read",
"expires_in": 3599,
"ext_expires_in": 3599,
"access_token": "eyJ0eXAiOiJKV1..."
}
失敗:
A1 NO AUTHENTICATE failed.
したがって、スコープにOutlookのURLを指定しない場合は、おそらくIMAPとSMTPを介した認証を許可しないグラフのURLと見なされるようです。
更新4:
同意ステップで必要なすべてのスコープを要求し、最初のアクセストークンをGraphスコープのみで取得し、2番目のアクセストークンをOutlookスコープを指定する更新トークンエンドポイントを使用して取得しました。認証コードによってアクセストークンを取得しようとすると、次のエラーが発生するため、2番目のアクセストークンを取得するためのトークンリフレッシュメソッドが使用されます。
{
"error": "invalid_grant",
"error_description": "AADSTS54005: OAuth2 Authorization code was already redeemed, please retry with a new valid code or use an existing refresh token.\r\nTrace ID: 09fc80f4-f5fd-4e52-938f-d56b71dd0900\r\nCorrelation ID: 4f35e05c-23c8-4fdc-a5a7-2fcde5a73b44\r\nTimestamp: 2020-05-08 12:13:30Z",
"error_codes": [
54005
],
"timestamp": "2020-05-08 12:13:30Z",
"trace_id": "09fc80f4-f5fd-4e52-938f-d56b71dd0900",
"correlation_id": "4f35e05c-23c8-4fdc-a5a7-2fcde5a73b44"
}
したがって、管理する必要のあるリソースに応じて、2つの個別のトークンを使用する必要はありません。
IMAP、SMTPスコープは、グラフではなくExchangeリソースを対象としています。一方、User.Read、Mail.ReadWriteはGraphリソース用です。
2つのリソース用のトークンの生成はサポートされていません。したがって、「入力パラメータースコープに指定された値には複数のリソースが含まれているため、その値は無効です。
/ tokenを2回呼び出して、2つのトークンを別々に生成する必要があります。 1. Exchangeリソース用に生成されたIMAP、SMTPスコープを持つもの。 2. Graphリソース用のGraphスコープ(User.Read、Mail.ReadWrite)を持つもう1つ。
@ldniov、私がやったことと違うものを見つけることができませんでした。参照用に以下で使用したコマンドを提供します。
/* Url where users would be redirected to give consent */
https://login.microsoftonline.com/common/oauth2/v2.0/authorize?
client_id=0c56e5c5-0a9e-4ddf-a931-54de274c2e03
&response_type=code
&redirect_uri=https%3A%2F%2Fimap2.mailboxsync.com%2Fredirect%2F
&response_mode=query
&scope=offline_access%20https%3A%2F%2Foutlook.office365.com%2FIMAP.AccessAsUser.All%20https%3A%2F%2Foutlook.office365.com%2FSMTP.Send
&state=12345
/*After user provides consent, exchanging auth code for refresh and access token */
curl -XPOST https://login.microsoftonline.com/test.onmicrosoft.com/oauth2/v2.0/token -d "client_id=0c56e5c5-0a9e-4ddf-a931-54de274c2e03&scope=offline_access%20https%3A%2F%2Foutlook.office365.com%2FIMAP.AccessAsUser.All%20https%3A%2F%2Foutlook.office365.com%2FSMTP.Send&code=OAQABAAIAAAAm-06blBE1TpVMil8KPQ41HA4-ey0WVgK6WhqDDWBLoHBXdigqd8S_gE-uJBqH8f3z5U61GGQ_c_uJ__1n2r_IqwzTwjkmrd_VumomR-DaTz6tk0YUD6MdD5wZFC6ZET9N6clCnjSPnsBJ0Ee95qrLywipGqp9NL3Puea8AWZr06ltVrruvMpS9JOawOMgBMtbuUQjT_-C8EFmCz7yS-Iv-VjJYwlZ0S5jKnmRv9Iku8xt42VNjNsrRUVUJpvjbvRJWrmX6GYCD82VlQPntlwcTABqTsn-oNlFmFtbuE9fggTdvmRjq4diEPlwFHp0Fhjzolsmodh8tSIj0z2jHZXWFw3nbetaz_n71NSVc2DfKsKlr4sl-Zyew2xexOOwoHIkI33HVI3Hl0W-93zRkWMh5QxyDnU1R8pLVCU0GF1COThUvj1qaTpUW26nOgWdG1q0hXbLyhHe0HaLCY-RA0yg2fe49jCHNhOFiimkOgLrLD1a_-ICLhlAYkRUbd-aXdpbYZNOphvhNDkMqNILwk9LOHW3Cbsk6YDi1bwBTB2XTOvjyzb4uLz0_1exGc0XyA7wrSHf5l97k66sHgN6gEBKq-fgAOIgPMKPpovZ1ZiplS8Cd7ifcFmPfnAL5_ZJbt_0SCltNTX8v_qJRedCk8lNIoz18104eOdOyPyjFixlVi0MVpSFBoR6gEydFqoAeiwgAA&state=12345&session_state=1fab1545-2dc5-4102-b145-6258ea1ce97e&state=12345&redirect_uri=https%3A%2F%2Fimap2.mailboxsync.com%2Fredirect%2F&client_secret=xxxx&grant_type=authorization_code"
/*Exchanging refresh token for new access token*/
curl -XPOST https://login.microsoftonline.com/test.onmicrosoft.com/oauth2/v2.0/token -d "client_id=0c56e5c5-0a9e-4ddf-a931-54de274c2e03&scope=offline_access%20https%3A%2F%2Foutlook.office365.com%2FIMAP.AccessAsUser.All%20https%3A%2F%2Foutlook.office365.com%2FSMTP.Send&refresh_token=OAQABAAAAAAAm-06blBE1TpVMil8KPQ41c8A8SyRZDLkMDX7Vm5ay9zjRE7DfM5Mwo26ooW2zeB6pgKGZr1KPKko7XMSHM8DJj71i8TnCOrg4doYCsuGKGCw5fC74KKtp2wLD7w1mJ4BQJqldj2-42VqN63x8U9wGibI_DqBTn2VxGxaHbtpIGtNwzR4xwQgDt9-BiotNIuYksxmF9ZCIr6X_uMLvI4DLsBXxe67YsSlvR9VrU8cH-xJddMGPaDyJisWDcR0uW0-yk0b24zYaj4G203ksEji5wiPbuT_PeBrjV5b638s26AX_nMfvXSAjJfq-jWHouynq-3VYZp63eJ2o36yQWDUUMAXZ6-OT2Kl9-n4Y2kVkGNdepp_RBBQ7BDceip7J2nf5tHQKDm4S3nPGkfUNIyzk3I5jurLm9tyK8bVHzSEMz8TSg5slj_6Vsk0Oa1BWwW4tgdwWjsUm344jTMpfhc9iGDbc98o_47v7BfnUYZCtWLFQQxd68i01JPZvcyEp4T8aE42rQVtR55DqN3_7NYfPQBzdK_qX1Ue4r7ptOs7BIrRQgvSvuTE--ATVYwqD6s_XEeBZnnX8x1_2-o0VOmnTP8_2FvhvhgCj93F7VK0yZ6PxrBaT9No5AyDVWkHmURxziLJWAl7qEaO0cLuKKWLew1zbzuld5ahhdmwFVYtFMEmOBNlikcP8-8WGgYcjIiw03975Vty4oxoYY4-DOvAWcupTn-E69VBSRFwfWo3y8M9XimKL7TyqoXKqQnMRnpqGezAtGnMWScKKVC179w5V5KVSxuQGeWqE-z6YfVT-16rEqBlkByyFrLyF3VvR5nYgAA&grant_type=refresh_token&client_secret=xxx"
IMAPデバッグログ
A1 AUTHENTICATE XOAUTH2 dXNlcj11c2VyXz ...
A1 OK AUTHENTICATEが完了しました。
A2機能
* CAPABILITY IMAP4 IMAP4rev1 AUTH = PLAIN AUTH = XOAUTH2 SASL-IR UIDPLUS MOVE ID UNSELECT CLIENTACCESSRULES CLIENTNETWORKPRESENCELOCATION BACKENDAUTHENTICATE CHILDREN IDLE NAMESPACE LITERAL +
A2 OK CAPABILITYが完了しました。
デバッグIMAPS:AUTH:PLAIN
デバッグIMAPS:AUTH:XOAUTH2
XOAUTH2を使用して[email protected]に接続しました
javax.mailの例 XOAUTHおよびO365 SMTPを使用してメールを送信する
私は、電子メールの送信に必要なスコープのみを要求します...(グラフは使用しません)。おそらく、不要な権限をいくつか設定しました。
他の応答はすでに指摘しています:/authorize
エンドポイントで無関係なスコープを同時に承認できますが、/token
エンドポイントへの各呼び出しには、関連するスコープのサブセットのみが含まれる場合があります。
質問といくつかの回答では、次の問題も発生します。IMAP/ POP/SMTPのスコープの前にhttps://graph.Microsoft.com/
またはhttps://Outlook.office365.com/
を付ける必要がありますか?実際、 Microsoftドキュメント スコープ名の前にhttps://Outlook.office.com/
を付ける必要があります。
Protocol Permission scope string
-------- -----------------------
IMAP https://Outlook.office.com/IMAP.AccessAsUser.All
POP https://Outlook.office.com/POP.AccessAsUser.All
SMTP https://Outlook.office.com/SMTP.Send