使用证书认证方式调用Microsoft Graph Api发送邮件案例

这篇具有很好参考价值的文章主要介绍了使用证书认证方式调用Microsoft Graph Api发送邮件案例。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

项目需求:

 

        以证书认证获取授权调用MS Graph API发送邮件,代替原有的SMTP协议以用户名密码认证的方式。

操作步骤:

        1.在Microsoft Azure 应用中心注册你的应用,申请需要使用的api权限

使用证书认证方式调用Microsoft Graph Api发送邮件案例

 使用证书认证方式调用Microsoft Graph Api发送邮件案例

注册好后你会得到如下信息:

使用证书认证方式调用Microsoft Graph Api发送邮件案例

 在权限中添加你需要的,发送邮件的如下:

使用证书认证方式调用Microsoft Graph Api发送邮件案例

 到这里基本注册流程结束。

        2.上代码

        (​​​​​​这个api的java示例不好使,我也调了很久没调通,就用了Http方式实现)

        首先在你的项目配置中加入


		<dependency>
			<groupId>com.microsoft.graph</groupId>
			<artifactId>microsoft-graph</artifactId>
			<version>[5.0,)</version>
		</dependency>
		<dependency>
			<groupId>com.azure</groupId>
			<artifactId>azure-identity</artifactId>
			<version>[1.3,)</version>
		</dependency>

        加好后通过证书换取授权令牌

    /**
     * 授权令牌初始化
     */
    protected void initToken(String sendMail) {
        try {
            //匹配clientId
            InputStream resource = new FileUtil().getResource(crtUrl.concat("applicationId.json"));
            String fileStr = FileUtil.getFileStr(resource);
            if (Objects.isNull(resource)) {
                throw new BwCustomizeBizException("用户邮箱信息读取异常:配置文件不存在");
            }
            BaseMailInfo mailInfo = new BaseMailInfo();
            List<BaseMailInfo> mailInfos = JSONArray.parseArray(fileStr, BaseMailInfo.class);
            if (null != mailInfos && !mailInfos.isEmpty()) {
                mailInfo = mailInfos.stream().filter(x -> x.getMail().equals(sendMail)).findFirst().orElse(null);
            }
            if (Objects.isNull(mailInfo)) {
                log.error("未获取到邮箱:{} 的配置信息,请检查applicationId.json配置文件", sendMail);
                throw new BwCustomizeBizException("MS graph 邮箱未注册,请更新配置文件");
            }
            client_id = mailInfo.getApplication_id();
            //匹配私钥和证书
            keyPath = crtUrl.concat(sendMail).concat(".der");
            certPath = crtUrl.concat(sendMail).concat(".crt");
            //设置令牌
            buildConfidentialClientObject();
            IAuthenticationResult result = getAccessTokenByClientCredentialGrant();
            accessToken = result.accessToken();
            log.info("【Microsoft_Graph_mail】 - get the accessToken = {}", accessToken);
        } catch (Exception ex) {
            log.error("【Microsoft_Graph_mail】 - 授权认证失败:{}", ex.getStackTrace());
            throw new BwCustomizeBizException("授权认证失败:" + ex.getMessage());
        }
    }


//项目发布后是Jar包形式,需要以getResourceAsStream方法获取jar中的文件
  public InputStream getResource(String fileName) throws IOException{
        return this.getClass().getClassLoader().getResourceAsStream(fileName);
    }
applicationId.json 文件我放在根目录,数据格式为json,支持多个证书配置
[
  {
    "index": 1,
    "mail": "....com",
    "application_id": "...",
    "application_owner": "..."
  },
  {
    "index": 2,
    "mail": "....com",
    "application_id": "...",
    "application_owner": "..."
  },
  {
    "index": 3,
    "mail": "....com",
    "application_id": "...",
    "application_owner": "..."
  }
]

证书也放在根目录下了,以及根据证书.crt通过openssl 生成的秘钥文件.der, 其中.crt文件没用到

使用证书认证方式调用Microsoft Graph Api发送邮件案例

 继续上代码:方法buildConfidentialClientObject()

    /**
     * 创建认证客户端
     *
     * @throws Exception
     */
    private void buildConfidentialClientObject() throws Exception {
        InputStream keyResoutce = new FileUtil().getResource(keyPath);
        PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(FileUtil.read(keyResoutce));
        PrivateKey key = KeyFactory.getInstance("RSA").generatePrivate(spec);

        InputStream certStream = new FileUtil().getResource(certPath);
        X509Certificate cert = (X509Certificate) CertificateFactory.getInstance("X.509").generateCertificate(certStream);
        app = ConfidentialClientApplication.builder(
                        client_id,
                        ClientCredentialFactory.createFromCertificate(key, cert))
                .authority(authority)
                .build();
    }

        方法

getAccessTokenByClientCredentialGrant()
    /**
     * 获取授权令牌
     * With client credentials flows the scope is ALWAYS of the shape "resource/.default", as the
     * application permissions need to be set statically (in the portal), and then granted by a tenant administrator
     */
    private IAuthenticationResult getAccessTokenByClientCredentialGrant() throws Exception {
        ClientCredentialParameters clientCredentialParam = ClientCredentialParameters.builder(
                        Collections.singleton(scope))
                .build();
        CompletableFuture<IAuthenticationResult> future = app.acquireToken(clientCredentialParam);
        return future.get();
    }

到此授权已经ok了,后面发邮件方法及读取邮件等等其他的,都可以这个令牌操作,再贴个完整方法吧,学弟们可以直接用哈哈。。。


/**
 * MS graph api 邮箱实现辅助类
 */
@Service
@Slf4j
public class MSGraphHandler {
    //应用ID
    private static String client_id = "";
    //私钥存放目录
    private static String keyPath = "";
    //证书存放目录
    private static String certPath = "";
    //邮箱客户端访问令牌
    private static String accessToken = "";

    @Value("${msgraphMail.authority}")
    private String authority;
    @Value("${msgraphMail.scope}")
    private String scope;
    @Value("${msgraphMail.sendAddress}")
    private String sendAddress;
    @Value("${msgraphMail.crtUrl}")
    private String crtUrl;

    private static ConfidentialClientApplication app;


    /**
     * 发送邮件
     */
    public void sendGraphMail(GraphMessageDTO message, String sendMail) {
        try {
            initToken(sendMail);
            if (StringUtils.isBlank(accessToken)) {
                throw new BwCustomizeBizException("【Microsoft_Graph_mail】 - 授权认证失败: accessToken不存在");
            }
            sendAddress = sendAddress.replace("%%", sendMail);
            //组成邮件内容
            GraphMailDTO<GraphMessageDTO> graphMailDTO = new GraphMailDTO();
            graphMailDTO.setMessage(message);
            graphMailDTO.setSaveToSentItems("true");
            log.info("【Microsoft_Graph_mail】打印邮件内容:{}", JSON.toJSONString(graphMailDTO));
            SimpleClientHttpRequestFactory requestFactory = new SimpleClientHttpRequestFactory();
            requestFactory.setConnectTimeout(10000);// 设置超时
            requestFactory.setReadTimeout(10000);
            RestTemplate restTemplate = new RestTemplate(requestFactory);
            HttpHeaders httpHeaders = new HttpHeaders();
            httpHeaders.add("Authorization", "Bearer " + accessToken);
            httpHeaders.setContentType(MediaType.APPLICATION_JSON);
            HttpEntity<String> httpEntity = new HttpEntity<>(JSON.toJSONString(graphMailDTO), httpHeaders);
            ResponseEntity<String> responseEntity = restTemplate.exchange(sendAddress, HttpMethod.POST, httpEntity, String.class);
            log.info("【Microsoft_Graph_mail】获取发送结果:{}", JSON.toJSONString(responseEntity));
        } catch (Exception e) {
            throw new BwCustomizeBizException("邮件发送失败:" + e.getMessage());
        }

    }

    /**
     * 授权令牌初始化
     */
    protected void initToken(String sendMail) {
        try {
            //匹配clientId
            InputStream resource = new FileUtil().getResource(crtUrl.concat("applicationId.json"));
            String fileStr = FileUtil.getFileStr(resource);
            if (Objects.isNull(resource)) {
                throw new BwCustomizeBizException("用户邮箱信息读取异常:配置文件不存在");
            }
            BaseMailInfo mailInfo = new BaseMailInfo();
            List<BaseMailInfo> mailInfos = JSONArray.parseArray(fileStr, BaseMailInfo.class);
            if (null != mailInfos && !mailInfos.isEmpty()) {
                mailInfo = mailInfos.stream().filter(x -> x.getMail().equals(sendMail)).findFirst().orElse(null);
            }
            if (Objects.isNull(mailInfo)) {
                log.error("未获取到邮箱:{} 的配置信息,请检查applicationId.json配置文件", sendMail);
                throw new BwCustomizeBizException("MS graph 邮箱未注册,请更新配置文件");
            }
            client_id = mailInfo.getApplication_id();
            //匹配私钥和证书
            keyPath = crtUrl.concat(sendMail).concat(".der");
            certPath = crtUrl.concat(sendMail).concat(".crt");
            //设置令牌
            buildConfidentialClientObject();
            IAuthenticationResult result = getAccessTokenByClientCredentialGrant();
            accessToken = result.accessToken();
            log.info("【Microsoft_Graph_mail】 - get the accessToken = {}", accessToken);
        } catch (Exception ex) {
            log.error("【Microsoft_Graph_mail】 - 授权认证失败:{}", ex.getStackTrace());
            throw new BwCustomizeBizException("授权认证失败:" + ex.getMessage());
        }
    }


    /**
     * 创建认证客户端
     *
     * @throws Exception
     */
    private void buildConfidentialClientObject() throws Exception {
        InputStream keyResoutce = new FileUtil().getResource(keyPath);
        PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(FileUtil.read(keyResoutce));
        PrivateKey key = KeyFactory.getInstance("RSA").generatePrivate(spec);

        InputStream certStream = new FileUtil().getResource(certPath);
        X509Certificate cert = (X509Certificate) CertificateFactory.getInstance("X.509").generateCertificate(certStream);
        app = ConfidentialClientApplication.builder(
                        client_id,
                        ClientCredentialFactory.createFromCertificate(key, cert))
                .authority(authority)
                .build();
    }

    /**
     * 获取授权令牌
     * With client credentials flows the scope is ALWAYS of the shape "resource/.default", as the
     * application permissions need to be set statically (in the portal), and then granted by a tenant administrator
     */
    private IAuthenticationResult getAccessTokenByClientCredentialGrant() throws Exception {
        ClientCredentialParameters clientCredentialParam = ClientCredentialParameters.builder(
                        Collections.singleton(scope))
                .build();
        CompletableFuture<IAuthenticationResult> future = app.acquireToken(clientCredentialParam);
        return future.get();
    }

}

使用证书认证方式调用Microsoft Graph Api发送邮件案例

 以上为本次踩坑日记,希望对你有所帮助!若有不理解的地方欢迎私信。。。文章来源地址https://www.toymoban.com/news/detail-458044.html

到了这里,关于使用证书认证方式调用Microsoft Graph Api发送邮件案例的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Kubernetes客户端认证——基于CA证书的双向认证方式

    Kubernetes集群的访问权限控制由API Server负责,API Server的访问权限控制由身份验证(Authentication)、授权(Authorization)和准入控制(Admission control)三个步骤组成,这个三个步骤是按序进行的(详细介绍请参见《(转)使用kubectl访问Kubernetes集群时的身份验证和授权》)。 其中身份验证

    2023年04月10日
    浏览(25)
  • 关于使用C#调用Win32API,抓取第三方句柄,模拟鼠标点击,键盘发送事件(C2Prog.exe)

    因为最近工作需要用就把基本知识整理了一下 主要操作这个软件写程序和选配置   下面例子和Win32以及自己封装的库全在工程文件里面 2023.7.10 :以前写的代码丢了重新写了一下优化了不少 ,所以特此更新一下 以前是1.7的版本目前用的是1.9版本有些不一样需要注意  这里放最新

    2024年02月14日
    浏览(33)
  • IT资质认证证书如何查询?这篇文章教你查询方式

    目前IT行业企业常见的体系和资质认证已经超过了30种,如此众多的体系或资质认证品类,查询渠道也不尽相同,今天小编简要介绍下几种常见证书查询方式,方便大家需要时使用。 ITSS运维维护标准 证书示例 ITSS信息技术服务标准是我国自主研发制定的信息技术服务领域的标

    2024年02月06日
    浏览(39)
  • 【ssl认证、证书】java中的ssl语法API说明(SSLContext)、与keytool 工具的联系

    相关文章: //-----------Java SSL begin---------------------- 【ssl认证、证书】SSL双向认证和SSL单向认证的区别(示意图) 【ssl认证、证书】java中的ssl语法API说明(SSLContext)、与keytool 工具的联系 【ssl认证、证书】SSL双向认证java实战、keytool创建证书 【ssl认证、证书】Wireshark抓包分析 【s

    2024年02月10日
    浏览(35)
  • 用Restful方式调用WebService接口(需认证)

    一个可以调用的 WebService接口 调用WebService接口的 SoapUI工具 调用Rest接口的 Postman/Apipost工具 首先接口在浏览器里访问是这样的,一个需要认证的接口 打开SoapUI工具,new一个Project,自定义一下名称和粘贴你的wsdl地址    解析wsdl的时候弹出提示输入账号密码,跟浏览器那边一样

    2024年02月13日
    浏览(26)
  • 【Docker从入门到入土 6】Consul详解+Docker https安全认证(附证书申请方式)

    服务注册与发现是 微服务架构 中不可或缺的重要组件。 起初服务都是单节点的,不保障高可用性,也不考虑服务的压力承载,服务之间调用单纯的通过接口访问。 直到后来出现了多个节点的分布式架构,起初的解决手段是在服务前端负载均衡,这样前端必须要知道所有后端

    2024年02月02日
    浏览(24)
  • FreeRTOS中断调用API消息队列发送函数导致系统死机(memcpy函数卡死)

    背景:写一组在FreeRTOS系统下的串口驱动 ,芯片使用的是杰发科的 AC781x系列 , ARM® CortexM3 内核,96MHz主频。 项目场景:计划使用dma接收数据,设置dma半满中断与全满中断,在半满中断中把前半部分数据传入消息队列,在全满中断中把后半部分数据传入消息队列。 问题1: 在中

    2024年02月15日
    浏览(30)
  • Node.js环境调用百度智能云(百度云)api鉴权认证三步走

    Postman脚本下载 下载Postman pre-request Script 设置 Authorization 示例脚本 签名计算工具 https://cloud.baidu.com/signature/index.html 百度智能云提供了在线生成签名工具,用户仅需填写必要请求信息、访问密钥(包含访问密钥ID(AK)和秘密访问密钥(SK)),可快速生成认证字符串。 文档地址 https:

    2024年04月11日
    浏览(25)
  • 【Ambari】Python调用Rest API 获取集群状态信息并发送钉钉告警

    🦄 个人主页——🎐开着拖拉机回家_大数据运维-CSDN博客 🎐✨🍁 🪁🍁 希望本文能够给您带来一定的帮助🌸文章粗浅,敬请批评指正!🍁🐥 🪁🍁🪁🍁🪁🍁🪁🍁 🪁🍁🪁🍁🪁🍁🪁 🪁🍁🪁🍁🪁🍁🪁🍁🪁🍁🪁🍁 感谢点赞和关注 ,每天进步一点点!加油!

    2024年02月09日
    浏览(27)
  • Docker版 E5续订的E5调用API续订服务:Microsoft 365 E5 Renew X

    本文是基于作者SundayRX提出的E5 调用API续订服务:Microsoft 365 E5 Renew X的基础上提出的Docker版本的E5调用API续订服务。 基础的账号注册等过程见SundayRX的博客:账号注册 更新日志:具体看github链接 【20240115更新】内测:更新了通用版本。支持了多种CPU架构,包括linux/amd64,linux/a

    2024年02月08日
    浏览(35)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包