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接口, 并且使用6.10.0版本 直接上代码 一, POM <!-- office 365 --><dependency><groupId>com.microsoft.graph</groupId><artifactId>microsoft-graph</artifactId><version>6.1…...
QT--TCP网络通讯工具编写记录
QT–TCP网络通讯工具编写记录 文章目录 QT--TCP网络通讯工具编写记录前言演示如下:一、服务端项目文件:【1.1】server_tcp.h 服务端声明文件【1.2】thread_1.h 线程处理声明文件【1.3】main.cpp 执行源文件【1.4】server_tcp.cpp 服务端逻辑实现源文件【…...
如何解决爬虫的IP地址受限问题?
使用代理IP池、采用动态IP更换策略、设置合理的爬取时间间隔和模拟正常用户行为,是解决爬虫IP地址受限问题的主要策略。代理IP池是通过集合多个代理IP来分配爬虫任务,从而避免相同的IP地址对目标网站进行高频次访问,减少被目标网站封禁的风险…...
harmony 文件上传
图片上传 1, 获取文件,这里指的是图片 在鸿蒙内部有一个API pick选择器,实现文件保存和文件选择的功能, 使用pick对象创建PhotoViewPicker实例 传入必要的参数,如选择图片的数量,和弹出窗口的位置…...
什么是安全左移如何实现安全左移
文章目录 一、传统软件开发面临的安全挑战二、什么是安全左移四、安全左移与安全开发生命周期(SDL)三、安全左移对开发的挑战五、从DevOps到DevSecOps六、SDL与DevSecOps 一、传统软件开发面临的安全挑战 传统软件开发面临的安全挑战主要包括以下几个方…...
将PCD点云投影到BEV平面得到图片
前言 点云数据作为一种丰富的三维空间信息表达方式,通常用于自动驾驶、机器人导航和三维建模等领域。然而,点云数据的直观性不如二维图像,这限制了它在一些需要快速视觉反馈的应用场景中的使用。本文将探讨如何将点云数据转换为二维图像&…...
计算机笔记14(续20个)
230.色彩的种类就是色相 饱和度就是彩度除以明度 231.RISC是精简指令集,CISC是复杂指令集 232.世界上第一台数字计算机,奠定了至今仍在使用计算机体系结构 233.数据传输中,电路交换的传输延迟最小 234.定点整数的小数点约定在最低…...
docker 使用桥接网
在Docker中使用桥接网络,你可以创建一个新的桥接网络或者使用默认的桥接网络(如果已经存在的话)。以下是创建新桥接网络和连接容器到这个网络的示例命令: 1.创建一个新的桥接网络(如果你想创建一个新的)&a…...
1金融风控相关业务介绍
金融风控相关业务介绍 学习目标 知道常见信贷风险知道机器学习风控模型的优势知道信贷领域常用术语含义1 信贷&风控介绍 信贷业务,就是贷款业务,是商业银行和互联网金融公司最重要的资产业务和主要赢利手段 通过放款收回本金和利息,扣除成本后获得利润。贷款平台预测有…...
521源码-免费教程-经常用到的Vue.js的Vue@Cli入门指导
更多网站源码学习教程,请点击👉-521源码-👈获取最新资源:521源码-网站源码-资源素材-免费下载 Vue.js是一款流行的JavaScript框架,它使得构建交互式的Web界面变得简单和快捷。VueCli是Vue.js官方提供的脚手架工具&…...
大数据技术原理(二):搭建hadoop伪分布式集群这一篇就够了
(实验一 搭建hadoop伪分布式) -------------------------------------------------------------------------------------------------------------------------------- 一、实验目的 1.理解Hadoop伪分布式的安装过程 实验内容涉及Hadoop平台的搭建和…...
中间件是什么?信创中间件有哪些牌子?哪家好用?
当今社会,中间件的重要性日益凸显,尤其是在信创背景下,选择适合的中间件产品对于推动企业数字化转型和升级具有重要意义。今天我们就来聊聊中间件是什么?信创中间件有哪些牌子?哪家好用?仅供参考哈…...
python实现520表白图案
今天是520哦,作为程序员有必要通过自己的专业知识来向你的爱人表达下你的爱意。那么python中怎么实现绘制520表白图案呢?这里给出方法: 1、使用图形库(如turtle) 使用turtle模块,你可以绘制各种形状和图案…...
【Linux】-Flink分布式内存计算集群部署[21]
注意: 本节的操作,需要前置准备好Hadoop生态集群,请先部署好Hadoop环境 简介 Flink同spark一样,是一款分布式内存计算引擎,可以支撑海量数据的分布式计算 Flink在大数据体系同样是明星产品,作为新一代的…...
《python程序语言设计》2018版第5章第44题利用python循环进行十进制变十六进制,依然是44题的旧问题。倒着打出来的16进制
它似乎也有上一道题同样道问题。就是结果可能是倒着的。我还不能用超纲的办法。似乎上一个问题的难点又传到了下面 note: 我建立了一个method_a的变量干脆把整数除16的第一次放到循环外。 这样是不是可以解决呢? 我感觉还是在整除和除于的概念中,没有解脱…...
【HarmonyOS4学习笔记】《HarmonyOS4+NEXT星河版入门到企业级实战教程》课程学习笔记(九)
课程地址: 黑马程序员HarmonyOS4NEXT星河版入门到企业级实战教程,一套精通鸿蒙应用开发 (本篇笔记对应课程第 16 节) P16《15.ArkUI-状态管理-任务统计案例》 1、实现任务进度卡片 怎么让进度条和进度展示文本堆叠展示࿱…...
海山数据库(He3DB)数据仓库发展历史与架构演进:(一)传统数仓
从1990年代Bill Inmon提出数据仓库概念后经过四十多的发展,经历了早期的PC时代、互联网时代、移动互联网时代再到当前的云计算时代,但是数据仓库的构建目标基本没有变化,都是为了支持企业或者用户的决策分析,包括运营报表、企业营…...
简单快捷的图片格式转换工具:认识webp2jpg-online
经常写博客或记笔记的朋友们可能会碰到图床不支持的图片格式或图片太大需要压缩的情况。通常,我们会在浏览器中搜索在线图片格式转换器,但这些转换器往往伴有烦人的广告或要求登录,并且支持的转换格式有限。最近,我在浏览 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 应用环境:局域网主机共享单个公网IP地址接入Internet…...
IT行业现状与未来趋势
随着技术的不断进步,IT行业已成为推动全球经济和社会发展的关键力量。从云计算、大数据、人工智能到物联网、5G通信和区块链,这些技术正在重塑我们的生活和工作方式。你眼中IT行业的现状及未来发展趋势是怎么样的?无论您是行业领袖、技术专家…...
【磁盘】每天掌握一个Linux命令 - iostat
目录 【磁盘】每天掌握一个Linux命令 - iostat工具概述安装方式核心功能基础用法进阶操作实战案例面试题场景生产场景 注意事项 【磁盘】每天掌握一个Linux命令 - iostat 工具概述 iostat(I/O Statistics)是Linux系统下用于监视系统输入输出设备和CPU使…...
屋顶变身“发电站” ,中天合创屋面分布式光伏发电项目顺利并网!
5月28日,中天合创屋面分布式光伏发电项目顺利并网发电,该项目位于内蒙古自治区鄂尔多斯市乌审旗,项目利用中天合创聚乙烯、聚丙烯仓库屋面作为场地建设光伏电站,总装机容量为9.96MWp。 项目投运后,每年可节约标煤3670…...
如何在最短时间内提升打ctf(web)的水平?
刚刚刷完2遍 bugku 的 web 题,前来答题。 每个人对刷题理解是不同,有的人是看了writeup就等于刷了,有的人是收藏了writeup就等于刷了,有的人是跟着writeup做了一遍就等于刷了,还有的人是独立思考做了一遍就等于刷了。…...
基于matlab策略迭代和值迭代法的动态规划
经典的基于策略迭代和值迭代法的动态规划matlab代码,实现机器人的最优运输 Dynamic-Programming-master/Environment.pdf , 104724 Dynamic-Programming-master/README.md , 506 Dynamic-Programming-master/generalizedPolicyIteration.m , 1970 Dynamic-Programm…...
USB Over IP专用硬件的5个特点
USB over IP技术通过将USB协议数据封装在标准TCP/IP网络数据包中,从根本上改变了USB连接。这允许客户端通过局域网或广域网远程访问和控制物理连接到服务器的USB设备(如专用硬件设备),从而消除了直接物理连接的需要。USB over IP的…...
【Android】Android 开发 ADB 常用指令
查看当前连接的设备 adb devices 连接设备 adb connect 设备IP 断开已连接的设备 adb disconnect 设备IP 安装应用 adb install 安装包的路径 卸载应用 adb uninstall 应用包名 查看已安装的应用包名 adb shell pm list packages 查看已安装的第三方应用包名 adb shell pm list…...
SQL Server 触发器调用存储过程实现发送 HTTP 请求
文章目录 需求分析解决第 1 步:前置条件,启用 OLE 自动化方式 1:使用 SQL 实现启用 OLE 自动化方式 2:Sql Server 2005启动OLE自动化方式 3:Sql Server 2008启动OLE自动化第 2 步:创建存储过程第 3 步:创建触发器扩展 - 如何调试?第 1 步:登录 SQL Server 2008第 2 步…...
渗透实战PortSwigger靶场:lab13存储型DOM XSS详解
进来是需要留言的,先用做简单的 html 标签测试 发现面的</h1>不见了 数据包中找到了一个loadCommentsWithVulnerableEscapeHtml.js 他是把用户输入的<>进行 html 编码,输入的<>当成字符串处理回显到页面中,看来只是把用户输…...
CppCon 2015 学习:Time Programming Fundamentals
Civil Time 公历时间 特点: 共 6 个字段: Year(年)Month(月)Day(日)Hour(小时)Minute(分钟)Second(秒) 表示…...
Linux-进程间的通信
1、IPC: Inter Process Communication(进程间通信): 由于每个进程在操作系统中有独立的地址空间,它们不能像线程那样直接访问彼此的内存,所以必须通过某种方式进行通信。 常见的 IPC 方式包括&#…...
