java 通过 microsoft graph 调用outlook(三)
这次会添加
1 reply回复接口
2 根据会话ID获取邮件组的接口(一次发送和一次reply具有相同的会话ID)
3 根据单值属性获取邮件(将额外信息添加到邮件,可以根据额外信息获取所有相关邮件)
并且使用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 xxxx.service.impl; import com.azure.identity.ClientSecretCredential; import com.azure.identity.ClientSecretCredentialBuilder; import com.helka.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 org.apache.dubbo.config.annotation.DubboReference; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import org.springframework.util.CollectionUtils; import org.springframework.util.StringUtils; 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; @Value("${mailOffice365.scopes}") private String scopes; /** * auth 授权 */ @PostConstruct public GraphServiceClient graphClient() { ClientSecretCredential credential = new ClientSecretCredentialBuilder() .clientId(clientId) .tenantId(tenantId) .clientSecret(clientSecret) .build(); GraphServiceClient graphClient = new GraphServiceClient(credential, scopes); return graphClient; } /** * 获取用户信息 * * @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 */ @Override public 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","toRecipients", "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 List<Message> getMails(String email, int page, int size) { MessageCollectionResponse message = graphClient() .users() .byUserId(email) .messages() .get(requestConfiguration -> { requestConfiguration.queryParameters.select = new String[]{"id","conversationId", "from","toRecipients", "isRead", "receivedDateTime", "subject"}; requestConfiguration.queryParameters.skip = page * size; requestConfiguration.queryParameters.top = size; requestConfiguration.queryParameters.orderby = new String[]{"receivedDateTime DESC"}; }); return message.getValue(); } @Override public Message getMailById(String email, String messageId) { Message message = graphClient() .users() .byUserId(email) .messages() .byMessageId(messageId) .get(requestConfiguration -> { requestConfiguration.queryParameters.select = new String[]{"id","conversationId", "from","toRecipients", "isRead", "receivedDateTime", "subject"}; }); return message; } /** * 根据messageId获取邮件 * * @param email 邮箱 * @param messageIds 邮件ids * @return */ @Override public List<Message> getMailsByIds(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 email 邮箱 * @param messageId 邮件id * @return */ @Override public Message getMailInfoById(String email, String messageId) { Message message = graphClient() .users() .byUserId(email) .messages() .byMessageId(messageId) .get(requestConfiguration -> { requestConfiguration.queryParameters.select = new String[]{"id","conversationId", "from","toRecipients", "isRead", "receivedDateTime", "subject","body","hasAttachments"}; requestConfiguration.queryParameters.expand = new String []{"attachments"}; }); //转换邮件中的图片 message = getMailByIdWithAttachment(message); return message; } @Override public List<Message> getMailInfoByIds(String email, List<String> messageIds) { List<Message> messages = new ArrayList<>(); if (!CollectionUtils.isEmpty(messageIds)) { for (String messageId : messageIds) { Message message = getMailInfoById(email, messageId); messages.add(message); } } return messages; } /** * 根据单值属性获取邮件组 * @param email * @param singlePropertiesKey * @param singlePropertiesVal * @return */ @Override public List<Message> getMailBySingleProperties(String email, String singlePropertiesKey,String singlePropertiesVal) { // singleValueExtendedProperties : 47A7EF28-8843-11EF-8D6B-C81F66E74322 String filter = "ep:ep/Id eq 'String {47A7EF28-8843-11EF-8D6B-C81F66E74322} Name "+singlePropertiesKey+"' and contains(ep/Value, '"+singlePropertiesVal+"')"; List<Message> messages = graphClient() .users() .byUserId(email) .messages() .get(requestConfiguration -> { requestConfiguration.queryParameters.select = new String[]{"id","conversationId", "from","toRecipients", "isRead", "receivedDateTime", "subject"}; requestConfiguration.queryParameters.filter = filter; }) .getValue(); return messages; } /** * 根据会话ID获取邮件组 * @param email * @param conversationId * @return */ @Override public List<Message> getMailByConversationId(String email, String conversationId) { List<Message> messages = graphClient() .users() .byUserId(email) .messages() .get(requestConfiguration -> { requestConfiguration.queryParameters.select = new String[]{"id","conversationId", "from","toRecipients", "isRead", "receivedDateTime", "subject"}; requestConfiguration.queryParameters.filter="conversationId eq '"+conversationId+"'"; }) .getValue(); return messages; } /** * 获取带有图片的邮件 * * @param message 邮件 * @return */ @Override public 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,String singlePropertiesKey,String singlePropertiesVal) throws Exception { List<String> recipients = List.of(recipient); return sendMail(sender, recipients, subject, body,singlePropertiesKey,singlePropertiesVal, null); } /** * 发送邮件(多个收件人) * * @param sender 发件人 * @param recipients 多收件人 * @param subject 主题 * @param body 内容 * @throws Exception */ public Message sendMail(String sender, List<String> recipients, String subject, String body,String singlePropertiesKey,String singlePropertiesVal) throws Exception { return sendMail(sender, recipients, subject, body,singlePropertiesKey,singlePropertiesVal, null); } @Override public Message sendMail(String sender, List<String> recipients, String subject, String body,String singlePropertiesKey,String singlePropertiesVal, List<FileAttachment> files) throws Exception { // Ensure client isn't null if (graphClient() == null) { throw new Exception("Graph has not been initialized for user auth"); } // Create a new message SendMailPostRequestBody 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); //设置单值属性 handleSingleProperty(message,singlePropertiesKey,singlePropertiesVal); // Send the message sendMailPostRequestBody.setMessage(message); graphClient() .users() .byUserId(sender) .sendMail() .post(sendMailPostRequestBody); return message; } private void handleSingleProperty(Message message,String singlePropertiesKey,String singlePropertiesVal) { // singleValueExtendedProperties : 47A7EF28-8843-11EF-8D6B-C81F66E74322 if(StringUtils.hasText(singlePropertiesKey) && StringUtils.hasText(singlePropertiesVal)) { LinkedList<SingleValueLegacyExtendedProperty> singleValueExtendedProperties = new LinkedList<SingleValueLegacyExtendedProperty>(); SingleValueLegacyExtendedProperty singleValueLegacyExtendedProperty = new SingleValueLegacyExtendedProperty(); singleValueLegacyExtendedProperty.setId("String {47A7EF28-8843-11EF-8D6B-C81F66E74322} Name "+singlePropertiesKey); singleValueLegacyExtendedProperty.setValue(singlePropertiesVal); singleValueExtendedProperties.add(singleValueLegacyExtendedProperty); message.setSingleValueExtendedProperties(singleValueExtendedProperties); } } public Message replyMail(String messageId, String sender, String recipient, String body,String singlePropertiesKey,String singlePropertiesVal) throws Exception { List<String> recipients = List.of(recipient); return replyMail(messageId, sender, recipients, body,singlePropertiesKey,singlePropertiesVal, null); } public Message replyMail(String messageId, String sender, List<String> recipients, String body,String singlePropertiesKey,String singlePropertiesVal) throws Exception { return replyMail(messageId, sender, recipients, body,singlePropertiesKey,singlePropertiesVal, null); } @Override public Message replyMail(String messageId, String sender, List<String> recipients, String body,String singlePropertiesKey,String singlePropertiesVal, List<FileAttachment> files) throws Exception { ReplyPostRequestBody replyPostRequestBody=new ReplyPostRequestBody(); Message message = new Message(); //附件 message = addAttarchment(message, files); //设置单值属性 handleSingleProperty(message,singlePropertiesKey,singlePropertiesVal); //收件人 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; } @Override public 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; } @Override public 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 xxxxx.controller; import com.xxxx.common.core.domain.R; import com.xxxx.common.core.utils.StringUtils; import com.xxxx.common.satoken.utils.LoginHelper; import com.xxxx.common.web.core.BaseController; import com.xxxx.mail.api.dto.RemoteMailOffice365Dto; import com.xxxx.mail.domain.BoJobMailRes; import com.xxxx.mail.domain.MessageVo; import com.xxxx.mail.domain.conver.MessageDtoMapper; import com.xxxx.mail.service.IMailOffice365Service; import com.microsoft.graph.models.*; import io.seata.common.util.CollectionUtils; 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.ArrayList; import java.util.List; @Validated @RequiredArgsConstructor @RestController @RequestMapping("/mail365") public class MailController extends BaseController { @Autowired IMailOffice365Service mailOffice365Service; @GetMapping("/getUser") public R<User> getUser() { String account = LoginHelper.getLoginUser().getEmail(); if(StringUtils.isEmpty(account)){ return R.ok(); } User user = mailOffice365Service.getUser(account); return R.ok(user); } /** * 获取邮件文件夹 * @return */ @GetMapping("/getMailFolders") public R<List<MailFolder>> getMailFolders() { String account = LoginHelper.getLoginUser().getEmail(); if(StringUtils.isEmpty(account)){ return R.ok(); } MailFolderCollectionResponse folder = mailOffice365Service.getMailFolders(account); return R.ok(folder.getValue()); } /** * 获取邮件文件夹中的邮件列表(分页) * @param folderId * @param pageIndex * @return */ @GetMapping("/getFolderMails") public R<List<RemoteMailOffice365Dto>> getFolderMails(String folderId, int pageIndex) { String account = LoginHelper.getLoginUser().getEmail(); if(StringUtils.isEmpty(account)){ return R.ok(); } MessageCollectionResponse mails = mailOffice365Service.getFolderMails(account, folderId, pageIndex, 10); //返回dto List<RemoteMailOffice365Dto> mails_res=new ArrayList<>(); if(!CollectionUtils.isEmpty(mails.getValue())){ mails_res=MessageDtoMapper.INSTANCE.convertList(mails.getValue()); } return R.ok(mails_res); } /** * 获取邮件列表,分页 * @param pageIndex * @return */ @GetMapping("/getMails") public R<List<RemoteMailOffice365Dto>> getMails(int pageIndex) { String account = LoginHelper.getLoginUser().getEmail(); if(StringUtils.isEmpty(account)){ return R.ok(); } List<Message> mails = mailOffice365Service.getMails(account, pageIndex, 10); //返回dto List<RemoteMailOffice365Dto> mails_res=new ArrayList<>(); if(!CollectionUtils.isEmpty(mails)){ mails_res=MessageDtoMapper.INSTANCE.convertList(mails); } return R.ok(mails_res); } /** * 根据ids获取邮件列表 * @param messageIds * @return */ @PostMapping("/getMailsByIds") public R<List<RemoteMailOffice365Dto>> getMailsByIds(@RequestBody List<String> messageIds) { String account = LoginHelper.getLoginUser().getEmail(); if(StringUtils.isEmpty(account)){ return R.ok(); } List<Message> mails = mailOffice365Service.getMailsByIds(account,messageIds); //返回dto List<RemoteMailOffice365Dto> mails_res=new ArrayList<>(); if(!CollectionUtils.isEmpty(mails)){ mails_res=MessageDtoMapper.INSTANCE.convertList(mails); } return R.ok(mails_res); } /** * 获取邮件详情 * @param messageId * @return */ @GetMapping("/getMailInfoById") public R<RemoteMailOffice365Dto> getMailInfoById(String messageId) { String account = LoginHelper.getLoginUser().getEmail(); if(StringUtils.isEmpty(account)){ return R.ok(); } Message mail = mailOffice365Service.getMailInfoById(account, messageId); //设置已读 mailOffice365Service.setRead(account,mail); //返回Dto RemoteMailOffice365Dto mail_res = MessageDtoMapper.INSTANCE.convert(mail); return R.ok(mail_res); } /** * 根据单值属性获取邮件组 * @param singlePropertiesKey * @param singlePropertiesVal * @return */ @GetMapping("/getMailBySingleProperties") public R<List<RemoteMailOffice365Dto>> getMailBySingleProperties(String singlePropertiesKey,String singlePropertiesVal) { String account = LoginHelper.getLoginUser().getEmail(); if(StringUtils.isEmpty(account)){ return R.ok(); } List<Message> mails = mailOffice365Service.getMailBySingleProperties(account, singlePropertiesKey,singlePropertiesVal); //返回dto List<RemoteMailOffice365Dto> mails_res=new ArrayList<>(); if(!CollectionUtils.isEmpty(mails)){ mails_res=MessageDtoMapper.INSTANCE.convertList(mails); } return R.ok(mails_res); } /** * 根据会话ID获取邮件组 * @param conversationId * @return */ @GetMapping("/getMailByConversationId") public R<List<RemoteMailOffice365Dto>> getMailByConversationId(String conversationId) { String account = LoginHelper.getLoginUser().getEmail(); if(StringUtils.isEmpty(account)){ return R.ok(); } List<Message> mails = mailOffice365Service.getMailByConversationId(account, conversationId); //返回dto List<RemoteMailOffice365Dto> mails_res=new ArrayList<>(); if(!CollectionUtils.isEmpty(mails)){ mails_res=MessageDtoMapper.INSTANCE.convertList(mails); } return R.ok(mails_res); } /** * 根据ids获取邮件详情 * @param messageIds * @return */ @PostMapping("/getMailInfoByIds") public R<List<RemoteMailOffice365Dto>> getMailInfoByIds(@RequestBody List<String> messageIds){ String account = LoginHelper.getLoginUser().getEmail(); if(StringUtils.isEmpty(account)){ return R.ok(); } List<Message> mails = mailOffice365Service.getMailInfoByIds(account, messageIds); for(Message mail : mails){ //设置已读 mailOffice365Service.setRead(account,mail); } //返回dto List<RemoteMailOffice365Dto> mails_res=new ArrayList<>(); if(!CollectionUtils.isEmpty(mails)){ mails_res=MessageDtoMapper.INSTANCE.convertList(mails); } return R.ok(mails_res); } @PostMapping("/sendMail") public R<RemoteMailOffice365Dto> sendMail(@RequestBody MessageVo req) throws Exception { String account = LoginHelper.getLoginUser().getEmail(); if(StringUtils.isEmpty(account)){ return R.ok(); } Message mail = mailOffice365Service.sendMail( account ,req.getRecipients() ,req.getSubject()==null?"No subject":req.getSubject() ,req.getBody() ,req.getSinglePropertiesKey() ,req.getSinglePropertiesVal() ,req.getAttachments() ); //返回Dto RemoteMailOffice365Dto mail_res = MessageDtoMapper.INSTANCE.convert(mail); return R.ok(mail_res); } @PostMapping("/replyMail") public R<RemoteMailOffice365Dto> replyMail(@RequestBody MessageVo req) throws Exception { String account = LoginHelper.getLoginUser().getEmail(); if(StringUtils.isEmpty(account)){ return R.ok(); } Message mail = mailOffice365Service.replyMail(req.getMessageId() , account , req.getRecipients() , req.getBody() ,req.getSinglePropertiesKey() ,req.getSinglePropertiesVal() , req.getAttachments() ); //返回Dto RemoteMailOffice365Dto mail_res = MessageDtoMapper.INSTANCE.convert(mail); return R.ok(mail_res); } }
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 String singlePropertiesKey; private String singlePropertiesVal; private List<FileAttachment> attachments=new ArrayList<>(); }