无法使用 JavaMail 在 Office365 上对 IMAP 进行身份验证

2023-11-24

我们正在尝试使用 OAUTH2 身份验证将 javamail (1.6) 客户端连接到托管在 Office365 上的 Office365 邮箱。

无论我们做什么,我们都会不断收到 A1 NO AUTHENTICATE failed。

我们已经注册了我们的应用程序

API权限

1

我们遵循了所有说明

https://learn.microsoft.com/en-us/exchange/client-developer/legacy-protocols/how-to-authenticate-an-imap-pop-smtp-application-by-using-oauth

包括运行 powershell 命令来使用应用程序 ID 和对象 ID 创建主体,并且我们授予应用程序对我们想要访问的电子邮件箱的完全访问权限。

对于身份验证,我们执行如下 HTTP POST,生成访问令牌

这是具有共享秘密的客户端凭证流,如此处所述https://learn.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-client-creds-grant-flow

https://login.microsoftonline.com/{我们的租户 ID}/oauth2/v2.0/token 和

client_id=...
client_secret=...
grant_type=client_credentials
scope=https://outlook.office365.com/.default

我们的javamail配置

mail.store.protocol="imap"
mail.imap.host="outlook.office365.com"
mail.imap.port="993"
mail.imap.ssl.enable="true"
mail.imap.starttls.enable="true"
mail.imap.auth="true"
mail.imap.auth.mechanisms="XOAUTH2"
mail.imap.user="<email box>"

然后在我们的 java 代码中,我们将商店与从上述 HTTP POST 获取的访问令牌连接起来

store.connect(host, user, oauth2_access_token);

我们还尝试了这个 powershell 脚本,它返回相同的错误

https://github.com/DanijelkMSFT/ThisandThat/blob/main/Get-IMAPAccessToken.ps1

我不认为该问题是 JavaMail 特有的。

确定访问令牌是否具有正确的权限或者是否存在其他阻止身份验证的因素非常困难

我们还能尝试什么?

Update 1

如果我们使用powershell脚本

https://github.com/DanijelkMSFT/ThisandThat/blob/main/Get-IMAPAccessToken.ps1

仅传递客户端 ID 和redirectUri,脚本会提示我进行批准,并且成功

但如果我们使用 clientsecret 授权失败

Update 2

我可以成功地将 javamail 与 powershell 脚本生成的访问令牌一起使用。

显然,使用 clientsecret 创建的令牌没有足够的权限来访问 IMAP 或邮箱

我开始怀疑使用客户端密钥的令牌请求是否不起作用,因为我们的 Azure Active Directory 启用了“安全默认值”。

可能是强制执行了 MFA,因此任何非交互式请求都会被阻止

Update 3

https://jwt.ms允许解码访问令牌

仅使用 clientid(代码授予流程)创建的令牌与使用 client_secret(客户端凭据流程)创建的令牌非常不同。

在“代码授予交互”的令牌中,有一个名为“scp”范围集的属性,它列出了范围,无论我在客户端应用程序 API 权限中拥有什么???

"scp": "IMAP.AccessAsUser.All Mail.Read Mail.Read.All Mail.Read.Shared Mail.ReadBasic User.Read"

客户端凭证流中的第二个令牌具有属性“角色”,但没有范围

"roles": ["IMAP.AccessAsApp"]

解决!

查看访问令牌,我们注意到客户端凭据流主题 (sub) 是我们未设置的 ID。

这里有一个问题:在使用 powershell 在线交换创建服务主体时,对于 serviceid,您必须使用企业应用程序的 objectid。

新ServicePrincipal -AppId {clientid}-ServiceId {企业应用程序对象ID}-组织{tenantid}

创建应用程序注册 Azure AD 时,您还创建企业应用程序

应用程序对象 ID 与企业应用程序对象 ID 不同。

客户端凭证流使用企业应用程序对象 ID 作为请求授权的用户。

使用 powershell 授予对邮箱的访问权限也是如此

添加MailboxPermission -Identity {email} -User-ServiceId {企业应用程序对象ID}-访问权限FullAccess

不幸的是认证过程如此繁琐


我对此的两分钱,如果您仍然面临 javamail 尝试连接到邮箱和阅读电子邮件的身份验证失败,首先确保 azure Active Directory 中的应用程序设置具有以下权限。

IMAP.AccessAsApp

邮件阅读

Mail.Send(用于发送)

其次,创建服务主体企业应用程序ID正如原帖中提到的。 一旦完成检查这里如果您生成的令牌具有您分配的所有角色。

即使您分配了必要的角色并且您可以通过 powershell 连接到邮箱,您仍然可能会得到身份验证失败来自javamail,因为您可能错误地使用了此属性(mail.imap.auth.mechanisms),请将mail.imap替换为mail.imap,它应该可以解决问题。

"mail.imaps.auth.mechanisms"="XOAUTH2"
"mail.imap.host"="outlookoffice365.com"
"mail.smtp.port"=993
"mail.store.protocol"="imaps"

session.getStore("imaps")
store.connect(host,port,user,token)

祝你好运 !!

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

无法使用 JavaMail 在 Office365 上对 IMAP 进行身份验证 的相关文章

随机推荐

  • 阻止 PHP 解析非 PHP 文件,例如 someFile.php.txt

    我刚刚安装了 phpdocumentor 但收到了奇怪的错误 我终于找到了问题所在 Phpdocumentor 创建各种文件 例如 someFile php txt 其中包含 PHP 代码 但不打算进行解析 事实证明 我的服务器正在解析它们
  • 如何更改 Bootstrap 4 上的导航栏悬停颜色?

    我需要将导航栏悬停颜色更改为其他颜色 我设法自己更改导航栏文本颜色 但在检查元素的悬停颜色中找不到要更改的正确颜色 然后我在堆栈溢出上查找了以前的答案 但它们对我的代码不起作用 任何投入将不胜感激
  • C 函数调用中的默认参数提升

    Setup 我对在 C 中调用函数时的默认参数提升有几个问题 这是第 6 5 2 2 节 函数调用 第 6 7 和 8 段C99 标准 pdf 为了便于阅读 添加了重点并分成列表 第 6 段 如果表示被调用函数的表达式的类型为不包括原型 对
  • Double 到 String 保持尾随零

    我尝试将双精度值转换为字符串并使用Replace 方法 将 替换为 这很好用 但只有当尾随数字不为零时 我的字符串中才需要零 即使该值为 1234 0 0 这对于十进制值效果很好 我尝试将双精度数转换为十进制数 但如果有零 我会丢失小数位
  • 调用 CallVoidMethod 时 JNI 崩溃

    我正在尝试从 Android 应用程序中的本机 C 代码调用 java 方法 使用 JNI 听起来很简单 但我的代码在最终调用方法本身时总是崩溃 这是我的代码 本机 C 代码 JNIEXPORT void JNICALL Java com
  • 如何更改 XAMPP 中 PHP 的默认路径?

    我正在使用 xampp 来部署 Web 应用程序 它将 PHP 模块包含在一个包中 现在我想做的是更改 PHP 的默认路径 以便我可以使用其他版本的 PHP 而无需覆盖现有模块 我的新 PHP 副本存在于桌面上 如何配置 Apache 以引
  • 将 JPanel 上的组件置于前面 (Java)

    在VB中 您可以使用zOrder 在 Net中 它是 SetChildIndex 在你问之前 不 在这种情况下我没有使用布局管理器 如果您有两个叠在一起的组件 那么在它们已经显示之后如何更改顺序 由于空间不足 我有一个按钮稍微重叠在另一个组
  • 与 Windows 10 相比,Android 模拟器在 ubuntu 17.04 上运行速度极慢

    我尝试从此链接安装 kvm https help ubuntu com community KVM Installation 但即使在尝试此操作之后 模拟器在软件 GLES 2 0 模式下运行时仍然很慢 并且当我选择硬件 GLES 2 0
  • (默认)为每个可变参数类型构造一个对象

    考虑这个代码片段 void Foo std string str1 std string str2 template
  • IE10 setInterval 内存泄漏的解决方法

    在测试我们的 Javascript 库期间 我认为我们在 IE10 v10 0 9200 16519 Windows 8 64 位 Javascript 实现中发现了严重的内存泄漏setInterval 一个简单的测试用例表明 如果在函数的
  • SQL - 源代码控制和架构/脚本管理

    我的公司刚刚完成年度审核流程 我终于说服他们 是时候找到更好的解决方案来管理我们的 SQL 模式 脚本了 目前 我们只有几个脚本需要手动更新 我曾在另一家公司使用过 VS2008 数据库版本 这是一个很棒的产品 我的老板让我看一下 Redg
  • “git submodule foreach git pull origin master”和“git pull origin master --recurse-submodules”有什么区别

    我有一个 dotfiles 存储库 其中所有 vim 插件都存储为子模块 因此在发生更改时很容易更新 我以为这两个命令做了同样的事情 但我注意到事实并非如此 我知道我有几个子模块需要更新 所以我跑了git pull origin maste
  • 进行定点数学运算的最佳方法是什么? [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心以获得指导 我需要为没有 FPU 的
  • 检测 iOS 上的飞行模式

    如何检测手机是否处于飞行模式 仅仅检测没有互联网连接是不够的 我必须能够区分这两种情况 尝试使用SCNetworkReachabilityGetFlags 系统配置框架 如果传回的flags变量为0且返回值为YES 则飞行模式开启 看看苹果
  • 简单的 shell 解决方案,用于为 stdout 的每一行执行命令[重复]

    这个问题在这里已经有答案了 这应该是一个非常简单的任务 我想获取任何旧命令的标准输出的每一行 并使用每个行来执行另一个命令并将其作为参数 例如 LS grep foo applycommand mv s bar 这将需要所有匹配的东西 fo
  • 将位图数组转换为 YUV (YCbCr NV21)

    如何转换返回的BitmapBitmapFactory decodeFile 转换为 YUV 格式 类似于相机 onPreviewFrame 以字节数组返回的形式 这是一些实际有效的代码 untested function byte getN
  • .net 应用程序图标存储在哪里?

    我试图找出我的应用程序的图标存储在 VS 2008 中的位置 在启动项目的应用程序属性中 我添加了一个带有 使用默认设置嵌入清单 设置的图标 我想以编程方式在应用程序中显示图标 但我无法弄清楚图标的存储位置 如何从代码中获取对应用程序图标的
  • 在 Angular 2 中指定服务提供者

    我正在尝试使用 Angular 2 的 DI 系统来自动处理我的服务的依赖项 我想在服务本身上使用注释 而不是使用第二个参数bootstrap 指定所有可注入服务 我有什么 低级服务 services role store ts expor
  • 角度路线包含#!在 url 中而不是 # [重复]

    这个问题在这里已经有答案了 最近我注意到 当使用ngRouteAngularJS 应用程序中的模块 该路由包含 在 URL 中 之前只是 例如 www webiste com login变成www website com login 我必须
  • 无法使用 JavaMail 在 Office365 上对 IMAP 进行身份验证

    我们正在尝试使用 OAUTH2 身份验证将 javamail 1 6 客户端连接到托管在 Office365 上的 Office365 邮箱 无论我们做什么 我们都会不断收到 A1 NO AUTHENTICATE failed 我们已经注册