Java Oauth2 使用 Office 365 发送电子邮件

2024-02-22

我正在使用 Java 1.8、Jakarta 电子邮件(版本 2.1.0)连接到 Microsoft 365,并使用 OAuth 进行 SMTP 身份验证。客户端需要使用 Oauth 身份验证,而不是基本的 smtp 身份验证。阅读文档后https://learn.microsoft.com/en-us/exchange/client-developer... https://learn.microsoft.com/en-us/exchange/client-developer/legacy-protocols/how-to-authenticate-an-imap-pop-smtp-application-by-using-oauth以及我已将 AD 配置为此权限的许多其他资源:

Microsoft Graph    offline_access
Microsoft Graph    User.Read
Microsoft Graph    Mail.Send
Microsoft Graph    openid
Microsoft Graph    IMAP.AccessAsUser.All
Microsoft Graph    SMTP.Send

Office 365 Exchange Online    full_access_as_app
Office 365 Exchange Online    POP.AccessAsApp
Office 365 Exchange Online    Mail.Send
Office 365 Exchange Online    IMAP.AccessAsApp

在 Azure 上使用 PowerShell 激活 SMTP 客户端身份验证https://learn.microsoft.com/en-us/exchange/clients... https://learn.microsoft.com/en-us/exchange/clients-and-mobile-in-exchange-online/authenticated-client-smtp-submission

PS C:\Users\dx-2102> Get-TransportConfig | Format-List SmtpClientAuthenticationDisabled   
SmtpClientAuthenticationDisabled : False

发送电子邮件的实现代码(Java):

Properties prop = new Properties();
prop.put("mail.smtp.auth", "true");
prop.put("mail.smtp.starttls.enable", "true");
prop.put("mail.smtp.host", emailSettings.getSmtp().getHostname());
prop.put("mail.smtp.port", emailSettings.getSmtp().getPort());
prop.put("mail.debug", "true");
prop.put("mail.debug.auth", "true");
prop.put("mail.smtp.auth.xoauth2.disable", "false");
prop.put("mail.smtp.auth.mechanisms", "XOAUTH2");
prop.put("mail.transport.protocol", "smtp");
prop.put("mail.smtp.auth.login.disable", "true");
prop.put("mail.smtp.auth.plain.disable", "true");

session = Session.getInstance(prop);
session.setDebug(true);
String accessToken = getOAuth2AccessToken();

transport = session.getTransport("smtp");
transport.connect(emailSettings.getSmtp().getHostname(), emailSettings.getSmtp().getPort(), emailSettings.getSmtp().getUsername(), tokenForSmtp(emailSettings.getSmtp().getUsername(), accessToken));
/* -- */ 
transport.sendMessage(mimeMessage, mimeMessage.getAllRecipients());
transport.close();

从 Azure AD 调用/获取令牌的方法,作为响应,我们得到一个带有过期时间的令牌。

String url = "https://login.microsoftonline.com/" + Tenant_ID + "/oauth2/token";

MultiValueMap<String, String> map = new LinkedMultiValueMap<>();
map.add("grant_type", "client_credentials");
map.add("response_type", "code");
map.add("client_id", ClientId);
map.add("client_secret", ClientSecret);
map.add("scope","openid offline_access https%3A%2F%2Foutlook.office365.com%2FSMTP.Send ");

RestTemplate restTemplate = new RestTemplate();
ResponseEntity<AzureResponse> response = restTemplate.postForEntity(url, map, AzureResponse.class);

在 SMTP 发送邮件过程中准备发送令牌的方法

private String tokenForSmtp(String userName, String accessToken) {
    final String ctrlA=Character.toString((char) 1);
    final String coded= "user=" + userName + ctrlA+"auth=Bearer " + accessToken + ctrlA+ctrlA;
    return Base64.getEncoder().encodeToString(coded.getBytes());
    //base64("user=" + userName + "^Aauth=Bearer " + accessToken + "^A^A")
}

发送 SMTP 电子邮件后,我收到错误:

AUTH XOAUTH2 dXNlcj1zb2ZhQHNvbHV0aW9uZmFjdG9yeWFnLm9ub...=
535 5.7.3 Authentication unsuccessful [VI1PR0202CA0024.eurprd02.prod.outlook.com]
Error on sending email: 535 5.7.3 Authentication unsuccessful [VI1PR0202CA0024.eurprd02.prod.outlook.com]

除了 openid、offline_access 和之外,我是否需要 Azure AD 中的其他令牌范围https://outlook.office.com/SMTP.Send https://outlook.office.com/SMTP.Send?或者我错过了 Azure 配置中的其他内容吗?有人有一个 Java 示例说明如何完成此操作,请随时附上。另外,如果您有一些有关在 Azure 帐户上设置的内容的屏幕截图。


None

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

Java Oauth2 使用 Office 365 发送电子邮件 的相关文章

  • 来自行号的方法名称

    给定特定类源代码 Java C 的行号 是否有一种简单的方法来获取它所属的方法的名称 如果它落入其中 大概使用抽象语法树 这对于将 checkstyle 的输出限制为仅触及的方法很有用 我假设您必须使用抽象语法树来执行 Line gt Me
  • 如何重复一段文本中的每个字母?爪哇语

    就像在口吃中一样 如果文本为 dean 并且乘数为 3 则结果将是 dddeeeaaannn 由提供的乘数指定的次数 public static void repeatLetters String text dean int n 3 Str
  • 如何杀死 Java Future?

    我正在开发的服务使用 Future 来并行运行多个任务 每个任务最多可能需要一分钟才能完成 然而 外部库似乎有问题 因为在某些情况下 2 的时间 它不会返回 在这些情况下 我想给出 2 分钟的等待时间 如果还没有返回 我想杀死 future
  • 传递自定义类型查询参数

    如何接受自定义类型查询参数 public String detail QueryParam request final MYRequest request 上面的行在启动服务器时出现错误 jersey server model ModelV
  • 使用 https 的 Web 服务身份验证给出错误

    我编写了一个简单的 Web 服务 并使用摘要和 HTTPS 身份验证来保护它 我已经使用 Java 中的 keytool 生成了我的证书 当我通过创建 war 文件在 Tomcat 中部署 Web 服务时 axis 的欢迎页面正确显示 但是
  • Spring 从 JBoss 上下文加载 PropertySourcesPlaceholderConfigurer

    我有一个使用 PropertySourcesPlaceholderConfigurer 的 spring 3 1 应用程序加载设置 我想管理测试和生产环境 只需从服务器上下文加载设置覆盖本地文件属性中指定的设置 下一个示例在 Tomcat
  • 将 Azure Blob 与 Azure 网站结合使用

    我正在制作一个MVC Windows Azure涉及用户上传图像的网站 我想将图像存储在 blob 中 我搜索了教程 但大多数都涉及Webapps而不是 MVC 网站 我发现的唯一有用的教程是 http www codeproject co
  • 生成一定长度的所有排列

    假设我们有一个字母表 abcdefghiklimnop 如何以有效的方式以五个一组的形式重复该字母表来递归生成排列 几天来我一直在为此苦苦挣扎 任何反馈都会有帮助 本质上这与 生成给定字符串的所有排列 https stackoverflow
  • java.exe 以非零退出值 1 结束

    只是为了开始 我并不是真正尝试从 Android 中的 xlsx 文件中读取单元格 我已经尝试了几乎所有我在 Google 上搜索到的内容 但是每次 在两台不同的 PC 上 都是 Java 1 7 0 79 当我尝试构建 运行 这个应用程序
  • 从字符串中删除重音符号

    Android 中有没有什么方法 据我所知 没有 java text Normalizer 可以从字符串中删除任何重音 例如 变成 eau 如果可能的话 我想避免解析字符串来检查每个字符 java text NormalizerAndroi
  • java绕中心旋转矩形

    我想围绕其中心点旋转一个矩形 它应该保留在应该绘制的位置并在该空间中旋转 这是我的代码 AffineTransform transform new AffineTransform transform rotate Math toRadian
  • 在约束验证器中使用 Guice 进行依赖注入

    我有一个在 ConstraintValidator 的实现中注入类的用例 我正在使用 Google guice 进行依赖项注入 目前无法在验证器内注入 我的场景的简化形式 内部模块 Provides Singleton public Ser
  • 为 REST API 生成 Swagger UI 文档

    我使用 Java 中的 JAX RS Jersey 开发了 REST API 我想为其转换 生成基于 Swagger 的 UI 文档 谁能以简单的方式告诉我如何做到这一点的精确 步骤 很抱歉 他们网站上给出的步骤对我来说有点模糊 有多种方法
  • log4j.properties 在 Wildfly 上无法正常工作

    我的类路径中有一个 log4j properties 文件 它位于 APP XX jar log4j properties 位置 我注意到在ear文件中我还可以在lib文件夹中找到log4j 1 2 17 jar 但无论我在 log4j p
  • 使用 Hibernate Envers 的复合表

    我有一个带有复合表的应用程序 其中包含一个额外的列 一切正常 直到我们添加 Hibernate Envers Audited org hibernate MappingException 无法读取 no pack response Resp
  • 用于生成 ISO 文件的 Maven 插件

    有没有可以生成ISO镜像的maven插件 我需要获取一些模块的输出 主要是包含 jar 的 zip 文件 并将它们组合成一个 ISO 映像 Thanks 现在有一个 ISO9660 maven 插件可以完成这项工作 https github
  • 亚马逊 Linux - 安装 openjdk-debuginfo?

    我试图使用jstack在 ec2 实例上amazon linux 所以我安装了openjdk devel包裹 sudo yum install java 1 7 0 openjdk devel x86 64 但是 jstack 引发了异常j
  • 假布尔值=真?

    我在一本书中找到了这段代码 并在 Netbeans 中执行了它 boolean b false if b true System out println true else System out println false 我只是不明白为什
  • Axis2 的 wsdl2java 在 RPC/Encoded 样式 Web 服务上失败

    Axis2 有替代方案吗 或者让它工作的方式 例如不同的数据绑定 Retrieving document at Exception in thread main org apache axis2 wsdl codegen CodeGener
  • Graphics2D setfont() 严重减慢了 java 应用程序的启动速度

    我正在用java制作一个游戏 它每秒刷新60次 每次执行循环时 我都会使用 g2d 来绘制图像和字符串 如果我这样做的话一切都会很好g2d setFont new Font Arial Font PLAIN 8 和抽绳 这将是正常的 但如果

随机推荐

  • Project Reactor:如何控制通量排放

    我有一个能发出一些光的通量Date This Date映射到我在某些设备上运行的 1024 个模拟 HTTP 请求Executer 我想做的是等待所有 1024 个 HTTP 请求 然后再发出下一个请求Date 目前运行时 onNext 被
  • 使用 xsltc.exe XslCompiledTransforms 时如何解析具有相对路径的 元素?

    作为我们的 Web 应用程序构建过程的一部分 我设置了要使用的 XSLT 样式表来构建微软的xsltc exe http msdn microsoft com en us library bb399405 aspx每当我们运行完整编译时 在
  • SwiftUI:选取器中的 ForEach 不更新

    我有一个元素数组 我想使用其中选择一个元素Picker 我有一个Button它只是将一个新元素添加到数组中 问题是 当我添加一个元素时 Picker选择未更新 它不适用于DefaultPickerStyle 但适用于SegmentedPic
  • Android studio 中的 testCompile 结果无法解决依赖关系

    我的测试位于 MainProject Project src test 中 我正在使用 Jake Wharton 的 gradle android test plugin 每当我使用 testCompile 指定依赖项时 它都不会在 IDE
  • MacVim 中的 Vim powerline (Lokaltog's) 奇怪字符

    我正在尝试使用电力线插件 https github com Lokaltog vim powerline https github com Lokaltog vim powerline 第一次 插件好像已经安装了 我通过以下命令使用 vun
  • 将python程序安全连接到mysql

    我想使用 MySQLdb 从我的 python 程序连接到 MySQL 我很担心 因为我需要将用户名和密码输入 py为了连接MySQL数据库 还要进入inno setup 没有人能找到用户名和密码并访问我的数据库吗 我该如何解决这个问题 我
  • Android 列表视图的自定义布局

    我正在使用列表视图 如下所示 String Shows new String Dexter Breaking Bad The Big Bang Theory Leverage ListView tv show list ListView v
  • SQL Server 选择不同的最新值

    我有一个包含大量行 gt 10K 的表 大多数行都有重复role与相关的值username 我想做的是按不同和最新选择行role添加者请求ID 我几乎已经拥有了 但是让我感到不安的部分是null某些值请求ID字段 因为这些请求是在添加该列之
  • Subversion 存储库工作副本结构的最佳实践?

    我刚刚开始学习如何使用 Subversion 构建我的 Web 应用程序 所以请耐心等待 以下是我的设置方法 我的域之一将托管我所有项目的存储库 我有标准的标签 分支 主干结构 它位于公共文件夹中 因此其他开发人员可以访问它 我的实时服务器
  • React 表不包含默认导出

    我想使用react table库在react中创建一个表 版本 react table 7 0 0 rc 15 当我尝试这个时 import ReactTable from react table import react table re
  • 将 .NET Guid 转换为 MongoDB ObjectID

    如何将 NET GUID 转换为 MongoDB ObjectID 在 C 中 另外 我可以将其再次从 ObjectID 转换回相同的 GUID 吗 你无法转换ObjectId into GUID反之亦然 因为它们是两个不同的东西 不同的大
  • Android Studio 中的 appLocale 设置

    我创建了广播组 用户可以在其中选择他们想要的语言 并将应用程序语言更改为所选语言 但我无法使用这些功能 不知道如何 我做了什么 我做了settingsActivity 我添加了广播组 我写过setAppLocale功能 我已经设置了onRa
  • 创建自己的 Wordpress 循环的最佳方法是什么?

    使用其内置函数从 Wordpress 输出内容似乎有三种主要方法 WP Query作为推荐之一 WP Query http codex wordpress org Function Reference WP Query 查询帖子 http
  • symfony2 - assetic assetic:dump 命令无法正确创建样式表

    由于某种原因 我无法加载 css 文件 这是我使用的包的结构 BD WebsiteBundle public css 这是我尝试加载 css 文件的方法 stylesheets bundles bdwebsite css filter cs
  • 如何在 Android Q 中请求外部文件访问权限?

    Heard 安卓Q引入了一项新的安全功能 称为 范围存储 它限制访问外部存储中的文件 我的问题是我必须将文本文档从应用程序保存到用户指定的位置 这是否需要任何形式的许可而不是READ EXTERNAL STORAGE and WRITE E
  • 如何将嵌套字典列表转换为pandas DataFrame?

    我有一些包含嵌套字典的数据 如下所示 mylist a 1 b c 2 d 3 a 3 b c 4 d 3 如果我们将其转换为 pandas DataFrame import pandas as pd result dataframe pd
  • PHP 数组递归循环

    我想在 PHP 中循环遍历一个数组 循环必须是递归的 因为我现在不知道有多少个数组中的数组 它用于阅读 Symfony2 中的翻译 输出格式为 a d e a f g b h i c j k l m c n o 与示例数组 array ar
  • 在没有双重调度/访问者模式的情况下解决 Java 的静态方法调度问题

    我正在使用一个类Foo提供了这些方法 String overloadedMethod Object String overloadedMethod Goo 由于 Java 在非接收者参数上静态分派 我不能只传递我的value 这是一个Obj
  • “grails clean”脚本实际上是做什么的?

    我很好奇grails clean命令 有一次我将错误的包导入到域类中 java util regex 我用它来执行正则表达式替换命令 但事实证明一切都没有改变 所以我认为我的正则表达式是错误的 但我把它留在那里以供将来完善 我的本地主机中的
  • Java Oauth2 使用 Office 365 发送电子邮件

    我正在使用 Java 1 8 Jakarta 电子邮件 版本 2 1 0 连接到 Microsoft 365 并使用 OAuth 进行 SMTP 身份验证 客户端需要使用 Oauth 身份验证 而不是基本的 smtp 身份验证 阅读文档后h