当前位置: 首页 > news >正文

java 通过 microsoft graph 调用outlook(三)

这次会添加一个Reply接口,

并且使用6.10.0版本

直接上代码

一, POM

        <!--    office 365    --><dependency><groupId>com.microsoft.graph</groupId><artifactId>microsoft-graph</artifactId><version>6.10.0</version><!--x-release-please-end--></dependency><dependency><groupId>com.azure</groupId><artifactId>azure-identity</artifactId><version>1.11.0</version></dependency><!--    office 365    -->

二,Service / impl

主要讲一下Reply方法,Reply本质是添加评论,我们所有回复邮件,可以看到上下文时,实际都是添加了评论而已。(对比了outlook是一样的)

而Reply添加的附件,只有最后一份才会显示附件。

其他的附件,都只能在各自发送的邮件中找到,而Reply的连续回复中,只会有最后的附件。

package com.xxx.mail.service.impl;import com.azure.identity.ClientSecretCredential;
import com.azure.identity.ClientSecretCredentialBuilder;
import com.xxx.mail.service.IMailOffice365Service;
import com.microsoft.graph.models.*;
import com.microsoft.graph.serviceclient.GraphServiceClient;
import com.microsoft.graph.users.item.messages.item.reply.ReplyPostRequestBody;
import com.microsoft.graph.users.item.sendmail.SendMailPostRequestBody;
import okhttp3.Request;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;import javax.annotation.PostConstruct;
import java.util.*;
import java.util.List;@Service("mailOffice365Util")
public class MailOffice365Impl implements IMailOffice365Service {@Value("${mailOffice365.clientId}")private String clientId;@Value("${mailOffice365.tenantId}")private String tenantId;@Value("${mailOffice365.clientSecret}")private String clientSecret;//scopes = "https://graph.microsoft.com/.default"@Value("${mailOffice365.scopes}")private String scopes;GraphServiceClient graphClient;/*** auth 授权*/@PostConstructpublic void auth() {ClientSecretCredential credential = new ClientSecretCredentialBuilder().clientId(clientId).tenantId(tenantId).clientSecret(clientSecret).build();graphClient = new GraphServiceClient(credential, scopes);}/*** 获取用户信息** @param email 邮箱* @return*/public User getUser(String email) {User user = graphClient.users().byUserId(email).get(requestConfiguration -> {requestConfiguration.queryParameters.select = new String[]{"displayName", "mail", "userPrincipalName"};});return user;}/*** 邮件文件夹** @param email 邮箱* @return*/@Overridepublic MailFolderCollectionResponse getMailFolders(String email) {MailFolderCollectionResponse result = graphClient.users().byUserId(email).mailFolders().get();return result;}/*** 获取文件夹邮件** @param email 邮箱* @return*/public MessageCollectionResponse getFolderMails(String email, String folderId, int page, int size) {MessageCollectionResponse message = graphClient.users().byUserId(email).mailFolders().byMailFolderId(folderId).messages().get(requestConfiguration -> {requestConfiguration.queryParameters.select = new String[]{"id", "from", "isRead", "receivedDateTime", "subject"};requestConfiguration.queryParameters.skip = page * size;requestConfiguration.queryParameters.top = size;requestConfiguration.queryParameters.orderby = new String[]{"receivedDateTime DESC"};});return message;}/*** 获取邮件** @param email 邮箱* @return*/public MessageCollectionResponse getMails(String email, int page, int size) {MessageCollectionResponse message = graphClient.users().byUserId(email).messages().get(requestConfiguration -> {requestConfiguration.queryParameters.select = new String[]{"id", "from", "isRead", "receivedDateTime", "subject"};requestConfiguration.queryParameters.skip = page * size;requestConfiguration.queryParameters.top = size;requestConfiguration.queryParameters.orderby = new String[]{"receivedDateTime DESC"};});return message;}/*** 邮件详情** @param email     邮箱* @param messageId 邮件id* @return*/@Overridepublic Message getMailById(String email, String messageId) {Message message = graphClient.users().byUserId(email).messages().byMessageId(messageId).get(requestConfiguration -> {requestConfiguration.queryParameters.select = new String[]{"id", "from", "isRead", "receivedDateTime", "subject","body","hasAttachments"};requestConfiguration.queryParameters.expand = new String []{"attachments"};});//转换邮件中的图片message = getMailByIdWithAttachment(message);return message;}@Overridepublic List<Message> getMailByIds(String email, List<String> messageIds) {List<Message> messages = new ArrayList<>();if (!CollectionUtils.isEmpty(messageIds)) {for (String messageId : messageIds) {Message message = getMailById(email, messageId);messages.add(message);}}return messages;}/*** 获取带有图片的邮件** @param message 邮件* @return*/@Overridepublic Message getMailByIdWithAttachment(Message message) {//邮件内图片展示String emailBody = message.getBody().getContent();if(!CollectionUtils.isEmpty(message.getAttachments())) {for (Attachment attachment : message.getAttachments()) {if (attachment.getIsInline().booleanValue()) {if ((attachment instanceof FileAttachment) && (attachment.getContentType().contains("image"))) {FileAttachment fileAttachment = (FileAttachment) attachment;byte[] contentBytes = fileAttachment.getContentBytes();String imageContentIDToReplace = "cid:" + fileAttachment.getContentId();emailBody = emailBody.replace(imageContentIDToReplace,String.format("data:image;base64,%s", Base64.getEncoder().encodeToString(contentBytes)));}}}}message.getBody().setContent(emailBody);return message;}/*** 发送邮件** @param sender    发件人* @param recipient 收件人* @param subject   主题* @param body      内容* @throws Exception*/public Message sendMail(String sender, String recipient, String subject, String body) throws Exception {List<String> recipients = List.of(recipient);return sendMail(sender, recipients, subject, body, null);}/*** 发送邮件(多个收件人)** @param sender     发件人* @param recipients 多收件人* @param subject    主题* @param body       内容* @throws Exception*/public Message sendMail(String sender, List<String> recipients, String subject, String body) throws Exception {return sendMail(sender, recipients, subject, body, null);}@Overridepublic Message sendMail(String sender, List<String> recipients, String subject, String body, List<FileAttachment> files) throws Exception {// Ensure client isn't nullif (graphClient == null) {throw new Exception("Graph has not been initialized for user auth");}// Create a new messageSendMailPostRequestBody sendMailPostRequestBody = new SendMailPostRequestBody();Message message = new Message();message.setSubject(subject);ItemBody itemBody=new ItemBody();itemBody.setContent(body);itemBody.setContentType(BodyType.Html);message.setBody(itemBody);//收件人if (!CollectionUtils.isEmpty(recipients)) {List<Recipient> toRecipients=new ArrayList<>();for (String item : recipients) {Recipient recipient = new Recipient();EmailAddress emailAddress = new EmailAddress();emailAddress.setAddress(item);recipient.setEmailAddress(emailAddress);toRecipients.add(recipient);}message.setToRecipients(toRecipients);}//附件message = addAttarchment(message, files);// Send the messagesendMailPostRequestBody.setMessage(message);graphClient.users().byUserId(sender).sendMail().post(sendMailPostRequestBody);return message;}public Message replyMail(String messageId, String sender, String recipient, String body) throws Exception {List<String> recipients = List.of(recipient);return replyMail(messageId, sender, recipients, body, null);}public Message replyMail(String messageId, String sender, List<String> recipients, String body) throws Exception {return replyMail(messageId, sender, recipients, body, null);}@Overridepublic Message replyMail(String messageId, String sender, List<String> recipients, String body, List<FileAttachment> files) throws Exception {ReplyPostRequestBody replyPostRequestBody=new ReplyPostRequestBody();Message message = new Message();//附件message = addAttarchment(message, files);//收件人if (!CollectionUtils.isEmpty(recipients)) {List<Recipient> toRecipients=new ArrayList<>();for (String item : recipients) {Recipient recipient = new Recipient();EmailAddress emailAddress = new EmailAddress();emailAddress.setAddress(item);recipient.setEmailAddress(emailAddress);toRecipients.add(recipient);}message.setToRecipients(toRecipients);}replyPostRequestBody.setMessage(message);replyPostRequestBody.setComment(body);graphClient.users().byUserId(sender).messages().byMessageId(messageId).reply().post(replyPostRequestBody);return message;}@Overridepublic Message addAttarchment(Message message, List<FileAttachment> files) {if (files != null && files.size() > 0) {List<Attachment> attachmentList = new ArrayList<>();for (FileAttachment file : files) {FileAttachment attachment = new FileAttachment();attachment.setName(file.getName());attachment.setOdataType("#microsoft.graph.fileAttachment");attachment.setContentType(file.getContentType());attachment.setContentBytes(file.getContentBytes());attachment.setIsInline(file.getIsInline());attachment.setContentId(file.getContentId());attachmentList.add(attachment);}message.setAttachments(attachmentList);}return message;}@Overridepublic Message setRead(String sender, Message message) {if (!message.getIsRead()) {Message newMessage = new Message();newMessage.setIsRead(true);graphClient.users().byUserId(sender).messages().byMessageId(message.getId()).patch(newMessage);}return message;}}

三, Controller

package com.xxx.mail.controller;import com.xxx.common.core.domain.R;
import com.xxx.common.satoken.utils.LoginHelper;
import com.xxx.common.web.core.BaseController;
import com.xxx.mail.domain.MessageVo;
import com.xxx.mail.service.IMailOffice365Service;
import com.microsoft.graph.models.*;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;import java.util.List;@Validated
@RequiredArgsConstructor
@RestController
@RequestMapping("/mail365")
public class MailController extends BaseController {@AutowiredIMailOffice365Service mailOffice365Service;@GetMapping("/getUser")public R<User> getUser() {String account = LoginHelper.getLoginUser().getEmail();User user = mailOffice365Service.getUser(account);return R.ok(user);}@GetMapping("/getMailFolders")public R<List<MailFolder>> getMailFolders() {String account = LoginHelper.getLoginUser().getEmail();MailFolderCollectionResponse folder = mailOffice365Service.getMailFolders(account);return R.ok(folder.getValue());}@GetMapping("/getFolderMails")public R<List<Message>> getFolderMails(String folderId, int pageIndex) {String account = LoginHelper.getLoginUser().getEmail();MessageCollectionResponse mails = mailOffice365Service.getFolderMails(account, folderId, pageIndex, 10);return R.ok(mails.getValue());}@GetMapping("/getMails")public R<List<Message>> getMails(int pageIndex) {String account = LoginHelper.getLoginUser().getEmail();MessageCollectionResponse mails = mailOffice365Service.getMails(account, pageIndex, 10);return R.ok(mails.getValue());}@GetMapping("/getMailById")public R<Message> getMailById(String messageId) {String account = LoginHelper.getLoginUser().getEmail();Message mail = mailOffice365Service.getMailById(account, messageId);//设置已读mailOffice365Service.setRead(account,mail);return R.ok(mail);}@GetMapping("/getMailByIds")public R<List<Message>> getMailByIds(List<String> messageIds){String account = LoginHelper.getLoginUser().getEmail();List<Message> mails = mailOffice365Service.getMailByIds(account, messageIds);for(Message mail : mails){//设置已读mailOffice365Service.setRead(account,mail);}return R.ok(mails);}@PostMapping("/sendMail")public R<Message> sendMail(@RequestBody MessageVo req) throws Exception {String account = LoginHelper.getLoginUser().getEmail();mailOffice365Service.sendMail(account,req.getRecipients(),req.getSubject(),req.getBody(),req.getAttachments());return R.ok();}@PostMapping("/replyMail")public R<Message> replyMail(@RequestBody MessageVo req) throws Exception {String account = LoginHelper.getLoginUser().getEmail();Message message = mailOffice365Service.replyMail(req.getMessageId(), account, req.getRecipients(), req.getBody(), req.getAttachments());return R.ok(message);}}

MessageVo

这个类,纯粹是为了发送邮件时,带上附件一起调用接口。

package com.xxx.mail.domain;import com.microsoft.graph.models.Attachment;
import com.microsoft.graph.models.FileAttachment;
import lombok.Data;import java.util.ArrayList;
import java.util.List;@Data
public class MessageVo {private String messageId;private List<String> recipients;private String subject;private String body;private List<FileAttachment> attachments=new ArrayList<>();
}

相关文章:

java 通过 microsoft graph 调用outlook(三)

这次会添加一个Reply接口&#xff0c; 并且使用6.10.0版本 直接上代码 一&#xff0c; POM <!-- office 365 --><dependency><groupId>com.microsoft.graph</groupId><artifactId>microsoft-graph</artifactId><version>6.1…...

QT--TCP网络通讯工具编写记录

QT–TCP网络通讯工具编写记录 文章目录 QT--TCP网络通讯工具编写记录前言演示如下&#xff1a;一、服务端项目文件&#xff1a;【1.1】server_tcp.h 服务端声明文件【1.2】thread_1.h 线程处理声明文件【1.3】main.cpp 执行源文件【1.4】server_tcp.cpp 服务端逻辑实现源文件【…...

如何解决爬虫的IP地址受限问题?

使用代理IP池、采用动态IP更换策略、设置合理的爬取时间间隔和模拟正常用户行为&#xff0c;是解决爬虫IP地址受限问题的主要策略。代理IP池是通过集合多个代理IP来分配爬虫任务&#xff0c;从而避免相同的IP地址对目标网站进行高频次访问&#xff0c;减少被目标网站封禁的风险…...

harmony 文件上传

图片上传 1&#xff0c; 获取文件&#xff0c;这里指的是图片 在鸿蒙内部有一个API pick选择器&#xff0c;实现文件保存和文件选择的功能&#xff0c; 使用pick对象创建PhotoViewPicker实例 传入必要的参数&#xff0c;如选择图片的数量&#xff0c;和弹出窗口的位置&#xf…...

什么是安全左移如何实现安全左移

文章目录 一、传统软件开发面临的安全挑战二、什么是安全左移四、安全左移与安全开发生命周期&#xff08;SDL&#xff09;三、安全左移对开发的挑战五、从DevOps到DevSecOps六、SDL与DevSecOps 一、传统软件开发面临的安全挑战 传统软件开发面临的安全挑战主要包括以下几个方…...

将PCD点云投影到BEV平面得到图片

前言 点云数据作为一种丰富的三维空间信息表达方式&#xff0c;通常用于自动驾驶、机器人导航和三维建模等领域。然而&#xff0c;点云数据的直观性不如二维图像&#xff0c;这限制了它在一些需要快速视觉反馈的应用场景中的使用。本文将探讨如何将点云数据转换为二维图像&…...

计算机笔记14(续20个)

230.色彩的种类就是色相 饱和度就是彩度除以明度 231.RISC是精简指令集&#xff0c;CISC是复杂指令集 232.世界上第一台数字计算机&#xff0c;奠定了至今仍在使用计算机体系结构 233.数据传输中&#xff0c;电路交换的传输延迟最小 234.定点整数的小数点约定在最低…...

docker 使用桥接网

在Docker中使用桥接网络&#xff0c;你可以创建一个新的桥接网络或者使用默认的桥接网络&#xff08;如果已经存在的话&#xff09;。以下是创建新桥接网络和连接容器到这个网络的示例命令&#xff1a; 1.创建一个新的桥接网络&#xff08;如果你想创建一个新的&#xff09;&a…...

1金融风控相关业务介绍

金融风控相关业务介绍 学习目标 知道常见信贷风险知道机器学习风控模型的优势知道信贷领域常用术语含义1 信贷&风控介绍 信贷业务,就是贷款业务,是商业银行和互联网金融公司最重要的资产业务和主要赢利手段 通过放款收回本金和利息,扣除成本后获得利润。贷款平台预测有…...

521源码-免费教程-经常用到的Vue.js的Vue@Cli入门指导

更多网站源码学习教程&#xff0c;请点击&#x1f449;-521源码-&#x1f448;获取最新资源&#xff1a;521源码-网站源码-资源素材-免费下载 Vue.js是一款流行的JavaScript框架&#xff0c;它使得构建交互式的Web界面变得简单和快捷。VueCli是Vue.js官方提供的脚手架工具&…...

大数据技术原理(二):搭建hadoop伪分布式集群这一篇就够了

&#xff08;实验一 搭建hadoop伪分布式&#xff09; -------------------------------------------------------------------------------------------------------------------------------- 一、实验目的 1.理解Hadoop伪分布式的安装过程 实验内容涉及Hadoop平台的搭建和…...

中间件是什么?信创中间件有哪些牌子?哪家好用?

当今社会&#xff0c;中间件的重要性日益凸显&#xff0c;尤其是在信创背景下&#xff0c;选择适合的中间件产品对于推动企业数字化转型和升级具有重要意义。今天我们就来聊聊中间件是什么&#xff1f;信创中间件有哪些牌子&#xff1f;哪家好用&#xff1f;仅供参考哈&#xf…...

python实现520表白图案

今天是520哦&#xff0c;作为程序员有必要通过自己的专业知识来向你的爱人表达下你的爱意。那么python中怎么实现绘制520表白图案呢&#xff1f;这里给出方法&#xff1a; 1、使用图形库&#xff08;如turtle&#xff09; 使用turtle模块&#xff0c;你可以绘制各种形状和图案…...

【Linux】-Flink分布式内存计算集群部署[21]

注意&#xff1a; 本节的操作&#xff0c;需要前置准备好Hadoop生态集群&#xff0c;请先部署好Hadoop环境 简介 Flink同spark一样&#xff0c;是一款分布式内存计算引擎&#xff0c;可以支撑海量数据的分布式计算 Flink在大数据体系同样是明星产品&#xff0c;作为新一代的…...

《python程序语言设计》2018版第5章第44题利用python循环进行十进制变十六进制,依然是44题的旧问题。倒着打出来的16进制

它似乎也有上一道题同样道问题。就是结果可能是倒着的。我还不能用超纲的办法。似乎上一个问题的难点又传到了下面 note: 我建立了一个method_a的变量干脆把整数除16的第一次放到循环外。 这样是不是可以解决呢&#xff1f; 我感觉还是在整除和除于的概念中&#xff0c;没有解脱…...

【HarmonyOS4学习笔记】《HarmonyOS4+NEXT星河版入门到企业级实战教程》课程学习笔记(九)

课程地址&#xff1a; 黑马程序员HarmonyOS4NEXT星河版入门到企业级实战教程&#xff0c;一套精通鸿蒙应用开发 &#xff08;本篇笔记对应课程第 16 节&#xff09; P16《15.ArkUI-状态管理-任务统计案例》 1、实现任务进度卡片 怎么让进度条和进度展示文本堆叠展示&#xff1…...

海山数据库(He3DB)数据仓库发展历史与架构演进:(一)传统数仓

从1990年代Bill Inmon提出数据仓库概念后经过四十多的发展&#xff0c;经历了早期的PC时代、互联网时代、移动互联网时代再到当前的云计算时代&#xff0c;但是数据仓库的构建目标基本没有变化&#xff0c;都是为了支持企业或者用户的决策分析&#xff0c;包括运营报表、企业营…...

简单快捷的图片格式转换工具:认识webp2jpg-online

经常写博客或记笔记的朋友们可能会碰到图床不支持的图片格式或图片太大需要压缩的情况。通常&#xff0c;我们会在浏览器中搜索在线图片格式转换器&#xff0c;但这些转换器往往伴有烦人的广告或要求登录&#xff0c;并且支持的转换格式有限。最近&#xff0c;我在浏览 GitHub …...

iptablese防火墙【SNAT和DNAT】

目录 1.SNAT策略及应用 1.1SNAT原理与应用 1.2 SNAT策略的工作原理 1.3 实验操练 2.DNAT策略 2.1 DNAT策略的概述 2.2 DNAT原理与应用 2.3 实验操练 1.SNAT策略及应用 1.1SNAT原理与应用 SNAT 应用环境&#xff1a;局域网主机共享单个公网IP地址接入Internet&#xf…...

IT行业现状与未来趋势

随着技术的不断进步&#xff0c;IT行业已成为推动全球经济和社会发展的关键力量。从云计算、大数据、人工智能到物联网、5G通信和区块链&#xff0c;这些技术正在重塑我们的生活和工作方式。你眼中IT行业的现状及未来发展趋势是怎么样的&#xff1f;无论您是行业领袖、技术专家…...

Vim 调用外部命令学习笔记

Vim 外部命令集成完全指南 文章目录 Vim 外部命令集成完全指南核心概念理解命令语法解析语法对比 常用外部命令详解文本排序与去重文本筛选与搜索高级 grep 搜索技巧文本替换与编辑字符处理高级文本处理编程语言处理其他实用命令 范围操作示例指定行范围处理复合命令示例 实用技…...

[2025CVPR]DeepVideo-R1:基于难度感知回归GRPO的视频强化微调框架详解

突破视频大语言模型推理瓶颈,在多个视频基准上实现SOTA性能 一、核心问题与创新亮点 1.1 GRPO在视频任务中的两大挑战 ​安全措施依赖问题​ GRPO使用min和clip函数限制策略更新幅度,导致: 梯度抑制:当新旧策略差异过大时梯度消失收敛困难:策略无法充分优化# 传统GRPO的梯…...

黑马Mybatis

Mybatis 表现层&#xff1a;页面展示 业务层&#xff1a;逻辑处理 持久层&#xff1a;持久数据化保存 在这里插入图片描述 Mybatis快速入门 ![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/6501c2109c4442118ceb6014725e48e4.png //logback.xml <?xml ver…...

React第五十七节 Router中RouterProvider使用详解及注意事项

前言 在 React Router v6.4 中&#xff0c;RouterProvider 是一个核心组件&#xff0c;用于提供基于数据路由&#xff08;data routers&#xff09;的新型路由方案。 它替代了传统的 <BrowserRouter>&#xff0c;支持更强大的数据加载和操作功能&#xff08;如 loader 和…...

Qt Http Server模块功能及架构

Qt Http Server 是 Qt 6.0 中引入的一个新模块&#xff0c;它提供了一个轻量级的 HTTP 服务器实现&#xff0c;主要用于构建基于 HTTP 的应用程序和服务。 功能介绍&#xff1a; 主要功能 HTTP服务器功能&#xff1a; 支持 HTTP/1.1 协议 简单的请求/响应处理模型 支持 GET…...

前端开发面试题总结-JavaScript篇(一)

文章目录 JavaScript高频问答一、作用域与闭包1.什么是闭包&#xff08;Closure&#xff09;&#xff1f;闭包有什么应用场景和潜在问题&#xff1f;2.解释 JavaScript 的作用域链&#xff08;Scope Chain&#xff09; 二、原型与继承3.原型链是什么&#xff1f;如何实现继承&a…...

动态 Web 开发技术入门篇

一、HTTP 协议核心 1.1 HTTP 基础 协议全称 &#xff1a;HyperText Transfer Protocol&#xff08;超文本传输协议&#xff09; 默认端口 &#xff1a;HTTP 使用 80 端口&#xff0c;HTTPS 使用 443 端口。 请求方法 &#xff1a; GET &#xff1a;用于获取资源&#xff0c;…...

并发编程 - go版

1.并发编程基础概念 进程和线程 A. 进程是程序在操作系统中的一次执行过程&#xff0c;系统进行资源分配和调度的一个独立单位。B. 线程是进程的一个执行实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位。C.一个进程可以创建和撤销多个线程;同一个进程中…...

Git常用命令完全指南:从入门到精通

Git常用命令完全指南&#xff1a;从入门到精通 一、基础配置命令 1. 用户信息配置 # 设置全局用户名 git config --global user.name "你的名字"# 设置全局邮箱 git config --global user.email "你的邮箱example.com"# 查看所有配置 git config --list…...

pikachu靶场通关笔记19 SQL注入02-字符型注入(GET)

目录 一、SQL注入 二、字符型SQL注入 三、字符型注入与数字型注入 四、源码分析 五、渗透实战 1、渗透准备 2、SQL注入探测 &#xff08;1&#xff09;输入单引号 &#xff08;2&#xff09;万能注入语句 3、获取回显列orderby 4、获取数据库名database 5、获取表名…...