gpt4 book ai didi

java - 使用 OAUTH2 服务器端的 IMAP 连接到 Outlook

转载 作者:行者123 更新时间:2023-12-03 02:10:53 25 4
gpt4 key购买 nike

我目前一直在尝试通过 IMAP 协议(protocol)访问 Office 365 帐户。我正在使用 Jakarta Mail (Javax.mail) 来尝试连接。当我尝试进行身份验证时,出现以下错误:

DEBUG IMAP: trying to connect to host "imap-mail.outlook.com", port 993, isSSL true
* OK The Microsoft Exchange IMAP4 service is ready. [...]
A0 CAPABILITY
* CAPABILITY IMAP4 IMAP4rev1 AUTH=PLAIN AUTH=XOAUTH2 SASL-IR UIDPLUS ID UNSELECT CHILDREN IDLE NAMESPACE LITERAL+
A0 OK CAPABILITY completed.
DEBUG IMAP: AUTH: PLAIN
DEBUG IMAP: AUTH: XOAUTH2
DEBUG IMAP: protocolConnect login, host=imap-mail.outlook.com, user=[...], password=<non-null>
DEBUG IMAP: SASL Mechanisms:
DEBUG IMAP: XOAUTH2
DEBUG IMAP:
DEBUG IMAP: SASL client XOAUTH2
DEBUG IMAP: SASL callback length: 2
DEBUG IMAP: SASL callback 0: javax.security.auth.callback.NameCallback@11d86b9d
DEBUG IMAP: SASL callback 1: javax.security.auth.callback.PasswordCallback@6dce59e
A1 AUTHENTICATE XOAUTH2 [...]
A1 NO AUTHENTICATE failed.

对于我正在制作的系统,我不必每次都从登录链接手动获取访问 token 。就这一点而言,我认为最明智的举动是使用 grant_type=client_credentials。但是,我还没有让它发挥作用。

我用于连接的代码如下:

    Properties props = new Properties();

// SMTP
props.put("mail.smtp.host", "smtp-mail.outlook.com");
props.put("mail.smtp.port", "587");
props.put("mail.smtp.starttls.enable", "true");

// IMAP
props.put("mail.imap.ssl.enable", "true"); // required for Gmail
props.put("mail.imap.sasl.enable", "true");
props.put("mail.imap.sasl.mechanisms", "XOAUTH2");
props.put("mail.imap.auth.login.disable", "true");
props.put("mail.imap.auth.plain.disable", "true");

// Debug
props.put("mail.debug", "true");
props.put("mail.debug.auth", "true");

Session session = Session.getInstance(props);
session.setDebug(true);

String accessToken = renewToken();
try {
Store mailStore = session.getStore("imap");
mailStore.connect("imap-mail.outlook.com", System.getenv("MAIL_USERNAME"), accessToken);
} catch (MessagingException e) {
throw new RuntimeException(e);
}

并且 renewToken() 如下所示:

  @Nullable
private String renewToken() {
if(System.currentTimeMillis() > tokenExpires) {
try {
String request = "client_id=" + URLEncoder.encode(System.getenv("CLIENT_ID"), StandardCharsets.UTF_8)
+ "&client_secret=" + URLEncoder.encode(System.getenv("CLIENT_SECRET"), StandardCharsets.UTF_8)
+ "&scope=" + URLEncoder.encode("https://outlook.office365.com/.default", StandardCharsets.UTF_8)
+ "&grant_type=client_credentials";
HttpURLConnection conn = (HttpURLConnection) new URL(TOKEN_URL).openConnection();
conn.setDoOutput(true);
conn.setRequestMethod("POST");
PrintWriter out = new PrintWriter(conn.getOutputStream());
out.print(request);
out.flush();
out.close();
conn.connect();
HashMap<String,Object> result = new ObjectMapper().readValue(conn.getInputStream(), new TypeReference<>() {});
tokenExpires = System.currentTimeMillis()+(((Number)result.get("expires_in")).intValue()* 1000L);
return (String)result.get("access_token");
} catch (IOException e) {
LOGGER.error(e.getMessage());
}
}
return null;
}

最后,CLIENT_AUTHORITY 定义为 https://login.microsoftonline.com/{tenant}/oauth2/v2.0/token其中 {tenant} 替换为 https://portal.azure.com 中的租户 ID

现在,我不太确定为什么会收到错误,也不太明白“NO AUTHENTICATE failed”错误的含义。唯一想到的是访问 token 要么生成错误,要么我没有请求正确的权限。

还应该提到的是,我尝试过使用主机“outlook.office365.com”而不是“imap-mail.outlook.com”,但没有任何运气。

最佳答案

按照本指南,我得到了它的工作:

Authentication Failure for IMAP using Client Credential flow for OAuth2.0 | Java | Exchange Online

对我来说,错误是 https://learn.microsoft.com 上提供的指南网站没有解释如何使用正确启用OAuth2.0所需的命令。

关于java - 使用 OAUTH2 服务器端的 IMAP 连接到 Outlook,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/73392053/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com