You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java通过IMAP访问Outlook邮箱组收件箱时认证成功但无法连接

问题:Azure客户端凭证模式OAuth2令牌登录后无法访问Outlook收件箱

背景

我正在开发Java代码,通过Azure客户端凭证模式的OAuth2令牌登录读取Outlook收件箱。已在Azure创建应用并配置必要权限,Office 365 Exchange Online管理员已完成权限同意。

由于组织内多个邮箱共享同一域名,仅需访问特定邮箱,因此通过管理员面板创建了一个组,添加相关邮箱ID,并为该组授予访问目标邮箱的所有必要权限。

获取令牌的Java代码

IConfidentialClientApplication app;
try {
    app = ConfidentialClientApplication.builder(CLIENT_ID, ClientCredentialFactory.createFromSecret(CLIENT_SECRET))
            .authority("https://login.microsoftonline.com/" + TENANT_ID)
            .build();

    ClientCredentialParameters credentialParameters = ClientCredentialParameters.builder(
            Collections.singleton(SCOPES))
            .build();

    CompletableFuture<IAuthenticationResult> future = app.acquireToken(credentialParameters);
    IAuthenticationResult result = future.get();
     ACCESS_TOKEN = result.accessToken();
     System.out.println("Access token is  : "+ACCESS_TOKEN);  

} catch (Exception e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}

解码后的JWT令牌内容

{
  "typ": "JWT",
  "nonce": "vG1KlJZibVbB_7pCJsxNwBNJS-hT8uCGZBigq7RiJoo",
  "alg": "RS256",
  "x5t": "T1St-dLTvyWRgxB_676u8krXS-I",
  "kid": "T1St-dLTvyWRgxB_676u8krXS-I"
}.{
  "aud": "https://outlook.office365.com",
  "iss": "https://sts.windows.net/4b8ccc43-30fb-4190-8324-f3551af91121/",
  "iat": 1702894960,
  "nbf": 1702894960,
  "exp": 1702898860,
  "aio": "E2VgYNBj6xEtDM/uf9pn11p2qJSz37bK58r6h+8tXSXbOrqmcQAA",
  "app_displayname": "WE2StarSGTSImap",
  "appid": "0e2sdfssfsdc-7cf8-4d3d-9237-ab626668c375",
  "appidacr": "1",
  "idp": "https://sts.windows.net/4b8ccc43-30fb-4190-8324-f3551af91121/",
  "oid": "fdfddrf9-253c-4e90-9631-a7cd341c26a6",
  "rh": "0.AUsAQ8yMS_swkEGDJPNVGvkRIQIAAAAAAPEPzgAAAAAAAABLAAA.",
  "roles": [
    "full_access_as_app",
    "Mail.ReadWrite",
    "Mail.Read",
    "Mail.Send",
    "IMAP.AccessAsApp"
  ],
  "sid": "3eddgfdgf7657-46c0-9745-d8c9d329cbda",
  "sub": "b1ea16c9-253c-4efdg0-9631-a7cd3fgdf1c26a6",
  "tid": "4bdfg43-30fb-4190-8324-f3551af91121",
  "uti": "V7HZsfgdfPBE-0YeTQ26BmAA",
  "ver": "1.0",
  "wids": [
    "09dfgf-0d1d-4acb-b408-d5ca73121e90"
  ]
}.[Signature]

访问收件箱的Java代码

Properties props = new Properties();
props.put("mail.store.protocol", "imap");
props.put("mail.imap.host", "outlook.office365.com");
props.put("mail.imap.port", "993");
props.put("mail.imap.ssl.enable", "true");
props.put("mail.imap.starttls.enable", "true");
props.put("mail.imap.auth", "true");
props.put("mail.imap.auth.mechanisms", "XOAUTH2");
props.put("mail.imap.user", "abc@xyz.COM");
props.put("mail.debug", "true");
props.put("mail.debug.auth", "true");
    
MailSSLSocketFactory sf = null;
try {
    sf = new MailSSLSocketFactory();
} catch (GeneralSecurityException e1) {

    e1.printStackTrace();
}
sf.setTrustAllHosts(true); 
props.put("mail.imap.ssl.trust", "*");
props.put("mail.imap.ssl.socketFactory", sf);

Store store = null;

try {
    Session session = Session.getInstance(props);
    session.setDebug(true);
    store = session.getStore("imap");
    store.connect("outlook.office365.com", "abc@xyz.COM", ReadMailSchedular.ACCESS_TOKEN);
        
    
    if(store.isConnected()){
        System.out.println("\n\n\n\n\n Connection Established using imap protocol successfully !\n\n\n\n\n");      
    }

    inbox = store.getFolder("INBOX");
    inbox.open(Folder.READ_WRITE);

错误日志

A1 OK AUTHENTICATE completed.
A2 CAPABILITY
* CAPABILITY IMAP4 IMAP4rev1 AUTH=PLAIN AUTH=XOAUTH2 SASL-IR UIDPLUS MOVE ID UNSELECT CLIENTACCESSRULES CLIENTNETWORKPRESENCELOCATION BACKENDAUTHENTICATE CHILDREN IDLE NAMESPACE LITERAL+
A2 OK CAPABILITY completed.
DEBUG IMAP: AUTH: PLAIN
DEBUG IMAP: AUTH: XOAUTH2
DEBUG IMAP: IMAPProtocol noop
A3 NOOP
A3 OK NOOP completed.
 Connection Established using imap protocol successfully !
DEBUG IMAP: connection available -- size: 1
A4 SELECT INBOX
A4 BAD User is authenticated but not connected.
A5 LOGOUT
* BYE Microsoft Exchange Server IMAP4 server signing off.
A5 OK LOGOUT completed.

已在微软连接测试工具中验证应用认证通过。

疑问

  1. 是否遗漏了必要的权限?
  2. 除了已在应用中设置的权限,是否还需要从管理员面板授予API权限?
  3. 导致认证成功但无法访问收件箱的原因是什么?

核心目标是访问Outlook收件箱,请问还缺少哪些步骤或细节?


解答

1. 权限相关排查

从令牌的roles字段看,已包含IMAP.AccessAsApp、Mail.Read等必要权限,但客户端凭证模式下,仅配置应用权限还不够,需要将Azure AD应用的服务主体直接授予目标邮箱的访问权限,而非通过组来分配。Exchange Online不支持通过安全组将应用权限映射到邮箱,必须直接对单个邮箱或所有邮箱授予应用访问权限。

2. 必要的补充步骤

需要使用Exchange Online PowerShell执行以下命令,为Azure AD应用授予目标邮箱的访问权限:

# 连接Exchange Online
Connect-ExchangeOnline -Organization <你的租户ID>

# 为特定邮箱授予应用访问权限
New-ApplicationAccessPolicy -AppId <你的Azure应用ID> -PolicyScopeGroupId <目标邮箱地址> -AccessRight RestrictAccess -Description "限制应用仅访问指定邮箱"

或者如果需要访问多个邮箱,可以创建一个邮件安全组,将目标邮箱添加进去,然后将权限授予该组:

New-ApplicationAccessPolicy -AppId <你的Azure应用ID> -PolicyScopeGroupId <邮件安全组ID> -AccessRight RestrictAccess -Description "限制应用仅访问组内邮箱"

注意:这里需要使用邮件安全组,而非普通的Azure AD安全组,Exchange Online仅识别邮件安全组作为权限范围。

3. 代码层面的优化

  • 移除MailSSLSocketFactory的setTrustAllHosts(true)配置,这会带来安全风险,Outlook的IMAP服务器证书是可信的,无需手动信任所有主机。
  • 确保SCOPES变量设置为https://outlook.office365.com/.default,客户端凭证模式下必须使用这个固定范围,不能指定单个权限。

4. 错误原因分析

User is authenticated but not connected错误的核心原因是:应用虽然通过OAuth2完成了身份认证,但Exchange Online并未授权该应用访问目标邮箱的权限。即使你通过管理员面板给组分配了邮箱权限,Exchange Online不会将组权限关联到Azure AD应用的服务主体,必须通过New-ApplicationAccessPolicy命令显式绑定应用与邮箱的访问关系。


内容的提问来源于stack exchange,提问作者Devendra Chouksey Bhopal

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 16:45:55