当前位置: 首页 > 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;无论您是行业领袖、技术专家…...

未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?

编辑&#xff1a;陈萍萍的公主一点人工一点智能 未来机器人的大脑&#xff1a;如何用神经网络模拟器实现更智能的决策&#xff1f;RWM通过双自回归机制有效解决了复合误差、部分可观测性和随机动力学等关键挑战&#xff0c;在不依赖领域特定归纳偏见的条件下实现了卓越的预测准…...

QMC5883L的驱动

简介 本篇文章的代码已经上传到了github上面&#xff0c;开源代码 作为一个电子罗盘模块&#xff0c;我们可以通过I2C从中获取偏航角yaw&#xff0c;相对于六轴陀螺仪的yaw&#xff0c;qmc5883l几乎不会零飘并且成本较低。 参考资料 QMC5883L磁场传感器驱动 QMC5883L磁力计…...

连锁超市冷库节能解决方案:如何实现超市降本增效

在连锁超市冷库运营中&#xff0c;高能耗、设备损耗快、人工管理低效等问题长期困扰企业。御控冷库节能解决方案通过智能控制化霜、按需化霜、实时监控、故障诊断、自动预警、远程控制开关六大核心技术&#xff0c;实现年省电费15%-60%&#xff0c;且不改动原有装备、安装快捷、…...

Matlab | matlab常用命令总结

常用命令 一、 基础操作与环境二、 矩阵与数组操作(核心)三、 绘图与可视化四、 编程与控制流五、 符号计算 (Symbolic Math Toolbox)六、 文件与数据 I/O七、 常用函数类别重要提示这是一份 MATLAB 常用命令和功能的总结,涵盖了基础操作、矩阵运算、绘图、编程和文件处理等…...

Netty从入门到进阶(二)

二、Netty入门 1. 概述 1.1 Netty是什么 Netty is an asynchronous event-driven network application framework for rapid development of maintainable high performance protocol servers & clients. Netty是一个异步的、基于事件驱动的网络应用框架&#xff0c;用于…...

MacOS下Homebrew国内镜像加速指南(2025最新国内镜像加速)

macos brew国内镜像加速方法 brew install 加速formula.jws.json下载慢加速 &#x1f37a; 最新版brew安装慢到怀疑人生&#xff1f;别怕&#xff0c;教你轻松起飞&#xff01; 最近Homebrew更新至最新版&#xff0c;每次执行 brew 命令时都会自动从官方地址 https://formulae.…...

Linux系统部署KES

1、安装准备 1.版本说明V008R006C009B0014 V008&#xff1a;是version产品的大版本。 R006&#xff1a;是release产品特性版本。 C009&#xff1a;是通用版 B0014&#xff1a;是build开发过程中的构建版本2.硬件要求 #安全版和企业版 内存&#xff1a;1GB 以上 硬盘&#xf…...

Vue ③-生命周期 || 脚手架

生命周期 思考&#xff1a;什么时候可以发送初始化渲染请求&#xff1f;&#xff08;越早越好&#xff09; 什么时候可以开始操作dom&#xff1f;&#xff08;至少dom得渲染出来&#xff09; Vue生命周期&#xff1a; 一个Vue实例从 创建 到 销毁 的整个过程。 生命周期四个…...

深度解析:etcd 在 Milvus 向量数据库中的关键作用

目录 &#x1f680; 深度解析&#xff1a;etcd 在 Milvus 向量数据库中的关键作用 &#x1f4a1; 什么是 etcd&#xff1f; &#x1f9e0; Milvus 架构简介 &#x1f4e6; etcd 在 Milvus 中的核心作用 &#x1f527; 实际工作流程示意 ⚠️ 如果 etcd 出现问题会怎样&am…...

CentOS 7.9安装Nginx1.24.0时报 checking for LuaJIT 2.x ... not found

Nginx1.24编译时&#xff0c;报LuaJIT2.x错误&#xff0c; configuring additional modules adding module in /www/server/nginx/src/ngx_devel_kit ngx_devel_kit was configured adding module in /www/server/nginx/src/lua_nginx_module checking for LuaJIT 2.x ... not…...