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

进化算法驱动机械爪设计优化:从原理到EvoClaw项目实践

1. 项目概述与核心价值最近在GitHub上看到一个挺有意思的项目&#xff0c;叫“EvoClaw”。光看这个名字&#xff0c;可能有点摸不着头脑&#xff0c;但点进去一看&#xff0c;发现这是一个关于“进化算法驱动的机械爪设计优化”的开源项目。简单来说&#xff0c;就是利用计算机…...

如何免费解锁WeMod专业版:2026年终极完整指南

如何免费解锁WeMod专业版&#xff1a;2026年终极完整指南 【免费下载链接】Wand-Enhancer Advanced UX and interoperability extension for Wand (WeMod) app 项目地址: https://gitcode.com/gh_mirrors/we/Wand-Enhancer 还在为WeMod专业版的高昂费用而烦恼吗&#xf…...

终极免费城通网盘直连解析工具:告别下载限速的完整指南

终极免费城通网盘直连解析工具&#xff1a;告别下载限速的完整指南 【免费下载链接】ctfileGet 获取城通网盘一次性直连地址 项目地址: https://gitcode.com/gh_mirrors/ct/ctfileGet 还在为城通网盘下载速度慢、等待时间长而烦恼吗&#xff1f;ctfileGet是一款专为城通…...

Unlock Music Electron:3步解锁你的加密音乐文件,重获音乐自由终极指南

Unlock Music Electron&#xff1a;3步解锁你的加密音乐文件&#xff0c;重获音乐自由终极指南 【免费下载链接】unlock-music-electron Unlock Music Project - Electron Edition 在Electron构建的桌面应用中解锁各种加密的音乐文件 项目地址: https://gitcode.com/gh_mirro…...

基于PIR传感器与LIFX智能灯泡的物联网运动感应照明系统实战

1. 项目概述与核心价值如果你对智能家居自动化感兴趣&#xff0c;并且想亲手打造一个既实用又有趣的照明项目&#xff0c;那么这个基于Adafruit FunHouse和LIFX智能灯泡的运动感应照明系统&#xff0c;绝对是一个绝佳的起点。它不仅仅是一个“开灯关灯”的简单触发器&#xff0…...

AI模型部署实战:基于FastAPI与Tauri构建OpenClaw模型GUI应用

1. 项目概述与核心价值最近在AI应用开发圈里&#xff0c;一个名为“GrahamMiranda-AI/openclaw-model-gui”的项目引起了我的注意。乍一看这个标题&#xff0c;它融合了“openclaw-model”和“gui”两个关键部分&#xff0c;这让我立刻联想到一个典型的场景&#xff1a;一个已经…...

fold命令行工具:高效文本数据聚合与分析的瑞士军刀

1. 项目概述&#xff1a;一个为“折叠”而生的高效工具 最近在折腾一些数据处理和文件整理的工作流时&#xff0c;我一直在寻找一个能让我“折叠”起来思考的工具。我说的“折叠”&#xff0c;不是物理上的&#xff0c;而是逻辑上的——把复杂的、多维度的信息&#xff0c;按照…...

别再拷贝exe到NXBIN了!用批处理文件搞定NX二次开发外部exe的环境变量(附VS2015/NX12配置)

告别手动拷贝&#xff1a;用批处理智能管理NX二次开发环境变量 每次修改完NX二次开发的外部exe程序&#xff0c;都要手动拷贝到NXBIN目录&#xff1f;这种重复劳动不仅低效&#xff0c;还容易导致版本混乱。其实只需一个简单的批处理脚本&#xff0c;就能彻底解决环境变量配置问…...

终极ThinkPad风扇控制指南:告别噪音,拥抱静音高效

终极ThinkPad风扇控制指南&#xff1a;告别噪音&#xff0c;拥抱静音高效 【免费下载链接】TPFanCtrl2 ThinkPad Fan Control 2 (Dual Fan) for Windows 10 and 11 项目地址: https://gitcode.com/gh_mirrors/tp/TPFanCtrl2 你是否曾经因为ThinkPad风扇的"直升机起…...

碳排放混合时间窗集装箱运输调度【附算法】

✨ 长期致力于集装箱运输VRP、混合时间窗、碳排放、多目标优化、NSGA-Ⅱ、蚁群算法研究工作&#xff0c;擅长数据搜集与处理、建模仿真、程序编写、仿真设计。 ✅ 专业定制毕设、代码 ✅ 如需沟通交流&#xff0c;点击《获取方式》 &#xff08;1&#xff09;经济性与紧急性双目…...