java 通过 microsoft graph 调用outlook(二)
这次提供一些基础调用方式API
下一篇文章,我会使用6.10.0版本,这个版本不像之前的6.x.x非常慢。
里面会带有 reply回复接口
PS:
getMailFolders 接口返回的属性中,包含了未读邮件数量unreadItemCount
一 POM文件
<!-- office 365 --> <dependency> <groupId>com.google.guava</groupId> <artifactId>guava</artifactId> <version>32.1.3-jre</version> </dependency> <dependency> <groupId>com.azure</groupId> <artifactId>azure-identity</artifactId> <version>1.11.1</version> <scope>compile</scope> </dependency> <dependency> <groupId>com.microsoft.graph</groupId> <artifactId>microsoft-graph</artifactId> <version>5.77.0</version> </dependency> <!-- office 365 -->
二 Domain
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<>(); }
三 Service / Impl
service
package com.xxx.mail.service; import com.microsoft.graph.models.*; import com.microsoft.graph.requests.MailFolderCollectionPage; import com.microsoft.graph.requests.MessageCollectionPage; import org.springframework.web.multipart.MultipartFile; import java.util.List; public interface IMailOffice365Service { /** * 用户信息 * * @param email * @return */ User getUser(String email); /** * 邮件文件夹 * 可显示未读邮件数量 * @param email 邮箱 * @return */ MailFolderCollectionPage getMailFolders(String email); /** * 邮件列表 * * @param email * @return */ MessageCollectionPage getFolderMails(String email, String folderId, int page, int size); MessageCollectionPage getMails(String email,int page,int size); /** * 邮件 * * @param email * @param messageId * @return */ Message getMailById(String email, String messageId); /** * 多个邮件 * * @param email * @param messageIds * @return */ List<Message> getMailByIds(String email, List<String> messageIds); /** * 带有图片的邮件 * * @param message * @return */ Message getMailByIdWithAttachment(Message message); /** * 发送邮件 * * @param sender * @param recipient * @param subject * @param body * @throws Exception */ Message sendMail(String sender , String recipient , String subject, String body) throws Exception; /** * 发送邮件和附件(多个收件人) * * @param sender * @param recipients * @param subject * @param body * @throws Exception */ Message sendMail(String sender , List<String> recipients , String subject, String body) throws Exception; /** * * @param sender * @param recipients * @param subject * @param body * @param files * @return * @throws Exception */ Message sendMail(String sender , List<String> recipients , String subject, String body, List<FileAttachment> files) throws Exception; /** * * 回复 * * @param messageId * @param sender * @param recipient * @param subject * @param body * @throws Exception */ Message replyMail(String messageId, String sender, String recipient, String subject, String body) throws Exception; /** * * 回复 * * @param messageId * @param sender * @param recipients * @param subject * @param body * @throws Exception */ Message replyMail(String messageId, String sender, List<String> recipients, String subject, String body) throws Exception; /** * * 回复带附件 * * @param messageId * @param sender * @param recipients * @param subject * @param body * @throws Exception */ Message replyMail(String messageId, String sender, List<String> recipients, String subject, String body, List<FileAttachment> files) throws Exception; /** * 添加附件 * @param message * @param files * @return */ Message addAttarchment(Message message,List<FileAttachment> files); /** * 设置已读 * @param sender * @param message * @return */ Message setRead(String sender,Message message); }
impl
package com.xxx.mail.service.impl; import com.azure.identity.ClientSecretCredential; import com.azure.identity.ClientSecretCredentialBuilder; import com.helka.mail.service.IMailOffice365Service; import com.microsoft.graph.authentication.IAuthenticationProvider; import com.microsoft.graph.authentication.TokenCredentialAuthProvider; import com.microsoft.graph.models.*; import com.microsoft.graph.requests.*; import okhttp3.Request; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import org.springframework.util.CollectionUtils; import org.springframework.web.multipart.MultipartFile; import javax.annotation.PostConstruct; import java.io.IOException; 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.graphUserScopes}") private String graphUserScopes; private IAuthenticationProvider authProvider; private GraphServiceClient<Request> graphClient; @PostConstruct public void init() { auth(); graphClient = GraphServiceClient.builder().authenticationProvider(authProvider).buildClient(); } /** * auth 授权 */ private void auth() { ClientSecretCredential clientSecretCredential = new ClientSecretCredentialBuilder() .clientId(clientId) .tenantId(tenantId) .clientSecret(clientSecret) .build(); authProvider = new TokenCredentialAuthProvider( Arrays.asList("https://graph.microsoft.com/.default") , clientSecretCredential ); } /** * 获取用户信息 * * @param email 邮箱 * @return */ public User getUser(String email) { User user = graphClient.users(email) .buildRequest() .select("displayName,mail,userPrincipalName") .get(); return user; } /** * 邮件文件夹 * * @param email 邮箱 * @return */ @Override public MailFolderCollectionPage getMailFolders(String email) { MailFolderCollectionPage result = graphClient.users(email).mailFolders().buildRequest().get(); return result; } /** * 获取文件夹邮件 * * @param email 邮箱 * @return */ public MessageCollectionPage getFolderMails(String email, String folderId, int page, int size) { MessageCollectionPage message = graphClient.users(email) .mailFolders() .byId(folderId) .messages() .buildRequest() .select("id,from,isRead,receivedDateTime,subject") .skip(page * size) .top(size) .orderBy("receivedDateTime DESC") .get(); return message; } /** * 获取邮件 * * @param email 邮箱 * @return */ public MessageCollectionPage getMails(String email, int page, int size) { MessageCollectionPage message = graphClient.users(email) .messages() .buildRequest() .select("id,from,isRead,receivedDateTime,subject") .skip(page * size) .top(size) .orderBy("receivedDateTime DESC") .get(); return message; } /** * 邮件详情 * * @param email 邮箱 * @param messageId 邮件id * @return */ @Override public Message getMailById(String email, String messageId) { Message message = graphClient.users(email) // .mailFolders("inbox") .messages() .byId(messageId) .buildRequest() .select("id,from,isRead,receivedDateTime,subject,body,hasAttachments") .expand("attachments") .get(); //转换邮件中的图片 message = getMailByIdWithAttachment(message); return message; } @Override public 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 */ @Override public Message getMailByIdWithAttachment(Message message) { //邮件内图片展示 String emailBody = message.body.content; for (Attachment attachment : message.attachments.getCurrentPage()) { if (attachment.isInline.booleanValue()) { if ((attachment instanceof FileAttachment) && (attachment.contentType.contains("image"))) { FileAttachment fileAttachment = (FileAttachment) attachment; byte[] contentBytes = fileAttachment.contentBytes; String imageContentIDToReplace = "cid:" + fileAttachment.contentId; emailBody = emailBody.replace(imageContentIDToReplace, String.format("data:image;base64,%s", Base64.getEncoder().encodeToString(contentBytes ))); } } } message.body.content = 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); } @Override public Message sendMail(String sender, List<String> recipients, String subject, String body, 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 Message message = new Message(); message.subject = subject; message.body = new ItemBody(); message.body.content = body; message.body.contentType = BodyType.HTML; //收件人 if (recipients != null && recipients.size() > 0) { message.toRecipients = new ArrayList<>(); for (String item : recipients) { Recipient toRecipient = new Recipient(); toRecipient.emailAddress = new EmailAddress(); toRecipient.emailAddress.address = item; message.toRecipients.add(toRecipient); } } //附件 message = addAttarchment(message, files); // Send the message graphClient .users(sender) .sendMail(UserSendMailParameterSet.newBuilder() .withMessage(message) .build()) .buildRequest() .post(); return message; } public Message replyMail(String messageId, String sender, String recipient, String subject, String body) throws Exception { List<String> recipients = List.of(recipient); return replyMail(messageId, sender, recipients, subject, body, null); } public Message replyMail(String messageId, String sender, List<String> recipients, String subject, String body) throws Exception { return replyMail(messageId, sender, recipients, subject, body, null); } @Override public Message replyMail(String messageId, String sender, List<String> recipients, String subject, String body, List<FileAttachment> files) throws Exception { Message message = new Message(); message.subject = subject; message.body = new ItemBody(); message.body.content = body; message.body.contentType = BodyType.HTML; //附件 message = addAttarchment(message, files); graphClient.users(sender) .messages() .byId(messageId) .reply(MessageReplyParameterSet.newBuilder() .withMessage(message) // .withComment("helloasf") .build()) .buildRequest() .post(); 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.name = file.name; attachment.oDataType = "#microsoft.graph.fileAttachment"; attachment.contentType = file.contentType; attachment.contentBytes = file.contentBytes; attachment.isInline = file.isInline; attachment.contentId = file.contentId; attachment.size = file.size; attachmentList.add(attachment); } AttachmentCollectionResponse attachmentCollectionResponse = new AttachmentCollectionResponse(); attachmentCollectionResponse.value = attachmentList; AttachmentCollectionPage attachmentCollectionPage = new AttachmentCollectionPage(attachmentCollectionResponse, null); message.attachments = attachmentCollectionPage; } return message; } @Override public Message setRead(String sender, Message message) { if (!message.isRead) { Message newMessage = new Message(); newMessage.isRead = true; graphClient.users(sender) .messages() .byId(message.id) .buildRequest() .patch(newMessage); } return message; } }
四 调用
读取邮箱的权限,在第一篇中有说,不赘述了。
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 com.microsoft.graph.requests.MailFolderCollectionPage; import com.microsoft.graph.requests.MessageCollectionPage; import lombok.RequiredArgsConstructor; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; import javax.annotation.Nullable; 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(); User user = mailOffice365Service.getUser(account); return R.ok(user); } @GetMapping("/getMailFolders") public R<List<MailFolder>> getMailFolders() { String account = LoginHelper.getLoginUser().getEmail(); MailFolderCollectionPage folder = mailOffice365Service.getMailFolders(account); return R.ok(folder.getCurrentPage()); } @GetMapping("/getFolderMails") public R<List<Message>> getFolderMails(String folderId, int pageIndex) { String account = LoginHelper.getLoginUser().getEmail(); MessageCollectionPage mails = mailOffice365Service.getFolderMails(account, folderId, pageIndex, 10); return R.ok(mails.getCurrentPage()); } @GetMapping("/getMails") public R<List<Message>> getMails(int pageIndex) { String account = LoginHelper.getLoginUser().getEmail(); MessageCollectionPage mails = mailOffice365Service.getMails(account, pageIndex, 10); return R.ok(mails.getCurrentPage()); } @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.getSubject() , req.getBody() , req.getAttachments()); return R.ok(message); } }