package com.fjhx.email.service.impl; import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.util.ObjectUtil; import com.baomidou.mybatisplus.core.toolkit.StringPool; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.fjhx.email.config.exception.ServiceException; import com.fjhx.email.entity.*; import com.fjhx.email.entity.dto.GetMessagePageDto; import com.fjhx.email.entity.dto.MailSyncInfo; import com.fjhx.email.entity.dto.MailboxInfo; import com.fjhx.email.entity.vo.MessageDetailVo; import com.fjhx.email.entity.vo.MessageVo; import com.fjhx.email.mapper.MailMapper; import com.fjhx.email.service.*; import com.fjhx.email.utils.EmailUtil; import com.fjhx.email.utils.ObsFileUtil; import com.fjhx.email.utils.PageWrapper; import com.sun.mail.imap.IMAPFolder; import com.sun.mail.imap.IMAPMessage; import com.sun.mail.imap.IMAPStore; import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import javax.mail.*; import javax.mail.internet.MimeUtility; import java.io.IOException; import java.io.InputStream; import java.io.UnsupportedEncodingException; import java.util.ArrayList; import java.util.List; @Slf4j @Service public class MailServiceImpl implements IMailService { @Autowired private MailMapper mailMapper; @Autowired private IPersonalMessageService personalMessageService; @Autowired private IEnterpriseMessageService enterpriseMessageService; @Autowired private IEnterpriseMessageAddressService enterpriseMessageAddressService; @Autowired private IEnterpriseMessageAttachmentService enterpriseMessageAttachmentService; @Autowired private IEnterpriseMessageContentService enterpriseMessageContentService; @Autowired private IPersonalMessageAddressService personalMessageAddressService; @Autowired private IPersonalMessageAttachmentService personalMessageAttachmentService; @Autowired private IPersonalMessageContentService personalMessageContentService; @Autowired private IPersonalMailboxService personalMailboxService; @Autowired private IEnterpriseMailboxService enterpriseMailboxService; @Autowired private IEnterpriseDomainService enterpriseDomainService; @Override public List getMailboxInfoListByUserId(List userIdList) { return mailMapper.getMailboxInfoListByUserId(userIdList, MailSyncInfo.mailType); } @Override public PageWrapper getMessagePage(GetMessagePageDto dto) { if (dto.getType().equals(1)) { Page page = personalMessageService.page(dto, q -> q .eq(PersonalMessage::getFolderId, dto.getFolderId()) .orderByDesc(PersonalMessage::getSendDate) ); return new PageWrapper<>(page, MessageVo.class); } Page page = enterpriseMessageService.page(dto, q -> q .eq(EnterpriseMessage::getFolderId, dto.getFolderId()) .orderByDesc(EnterpriseMessage::getSendDate) ); return new PageWrapper<>(page, MessageVo.class); } @SneakyThrows @Override public MessageDetailVo getMessageDetail(GetMessagePageDto dto) { Long messageId = dto.getMessageId(); Integer contentSync; Integer addressSync; Integer attachmentSync; Integer messageNumber; String folderName; Long mailboxId; if (dto.getType().equals(1)) { PersonalMessage personalMessage = personalMessageService.getById(messageId); if (personalMessage == null) { throw new ServiceException("没有找到邮箱"); } messageNumber = personalMessage.getMessageNumber(); contentSync = personalMessage.getContentSync(); addressSync = personalMessage.getAddressSync(); attachmentSync = personalMessage.getAttachmentSync(); folderName = personalMessage.getFolderName(); mailboxId = personalMessage.getMailboxId(); } else { EnterpriseMessage enterpriseMessage = enterpriseMessageService.getById(messageId); if (enterpriseMessage == null) { throw new ServiceException("没有找到邮箱"); } messageNumber = enterpriseMessage.getMessageNumber(); contentSync = enterpriseMessage.getContentSync(); addressSync = enterpriseMessage.getAddressSync(); attachmentSync = enterpriseMessage.getAttachmentSync(); folderName = enterpriseMessage.getFolderName(); mailboxId = enterpriseMessage.getMailboxId(); } MessageDetailVo messageDetailVo = new MessageDetailVo(); // 正文附件已同步 if (contentSync == 1 && addressSync == 1 && attachmentSync == 1) { if (dto.getType().equals(1)) { setPersonalMessageDetailVo(messageDetailVo, messageId); } else { setEnterpriseMessageDetailVo(messageDetailVo, messageId); } } // 未同步 else { MailboxInfo mailboxInfo = getMailboxInfo(dto.getType(), mailboxId); IMAPStore imapStore = EmailUtil.getIMAPStore(mailboxInfo); IMAPFolder folder = (IMAPFolder) imapStore.getFolder(folderName); folder.open(Folder.READ_ONLY); IMAPMessage message = (IMAPMessage) folder.getMessage(messageNumber); messageDetailVo.setMessageAttachmentList(new ArrayList<>()); getMessageAndAttachment(messageDetailVo, message, messageId); messageDetailVo.setMessageAddressList(EmailUtil.mailAddressList(message)); } for (MessageDetailVo.MessageAttachment messageAttachment : messageDetailVo.getMessageAttachmentList()) { messageAttachment.setUrl(ObsFileUtil.getCompleteUrl(messageAttachment.getUrl())); } return messageDetailVo; } private MailboxInfo getMailboxInfo(Integer type, Long mailboxId) { MailboxInfo mailboxInfo = new MailboxInfo(); if (type.equals(1)) { PersonalMailbox personalMailbox = personalMailboxService.getById(mailboxId); mailboxInfo.setReceiveHost(personalMailbox.getReceiveHost()); mailboxInfo.setReceivePort(personalMailbox.getReceivePort()); mailboxInfo.setMailUser(personalMailbox.getMailUser()); mailboxInfo.setMailPassword(personalMailbox.getMailPassword()); return mailboxInfo; } EnterpriseMailbox enterpriseMailbox = enterpriseMailboxService.getById(mailboxId); EnterpriseDomain enterpriseDomain = enterpriseDomainService.getById(enterpriseMailbox.getDomainId()); mailboxInfo.setReceiveHost(enterpriseDomain.getReceiveHost()); mailboxInfo.setReceivePort(enterpriseDomain.getReceivePort()); mailboxInfo.setMailUser(enterpriseMailbox.getMailUserPrefix() + "@" + enterpriseDomain.getDomanName()); mailboxInfo.setMailPassword(enterpriseMailbox.getMailPassword()); return mailboxInfo; } private void setPersonalMessageDetailVo(MessageDetailVo vo, Long messageId) { List addressList = personalMessageAddressService.list( q -> q.eq(PersonalMessageAddress::getMessageId, messageId)); vo.setMessageAddressList(BeanUtil.copyToList(addressList, MessageDetailVo.MessageAddress.class)); List attachmentList = personalMessageAttachmentService.list( q -> q.eq(PersonalMessageAttachment::getMessageId, messageId)); vo.setMessageAttachmentList(BeanUtil.copyToList(attachmentList, MessageDetailVo.MessageAttachment.class)); PersonalMessageContent content = personalMessageContentService.getOne( q -> q.eq(PersonalMessageContent::getMessageId, messageId)); vo.setContent(content.getContent()); } private void setEnterpriseMessageDetailVo(MessageDetailVo vo, Long messageId) { List addressList = enterpriseMessageAddressService.list( q -> q.eq(EnterpriseMessageAddress::getMessageId, messageId)); vo.setMessageAddressList(BeanUtil.copyToList(addressList, MessageDetailVo.MessageAddress.class)); List attachmentList = enterpriseMessageAttachmentService.list( q -> q.eq(EnterpriseMessageAttachment::getMessageId, messageId)); vo.setMessageAttachmentList(BeanUtil.copyToList(attachmentList, MessageDetailVo.MessageAttachment.class)); EnterpriseMessageContent content = enterpriseMessageContentService.getOne( q -> q.eq(EnterpriseMessageContent::getMessageId, messageId)); vo.setContent(content.getContent()); } /** * 保存附件和正文 */ private void getMessageAndAttachment(MessageDetailVo messageDetailVo, Part part, Long messageId) throws MessagingException, IOException { // 正文:文本格式 if (part.isMimeType("text/plain")) { addPlain(part, messageDetailVo); } // 正文:html格式 else if (part.isMimeType("text/html")) { addHtml(part, messageDetailVo); } // 正文:html格式 else if (part.isMimeType("text/html; charset=UTF-8")) { addHtmlUtf8(part, messageDetailVo); } // 大对象 else if (part.isMimeType("multipart/*")) { // 复杂体邮件 Multipart multipart = (Multipart) part.getContent(); // 复杂体邮件包含多个邮件体 int partCount = multipart.getCount(); for (int i = 0; i < partCount; i++) { // 获得复杂体邮件中其中一个邮件体 BodyPart bodyPart = multipart.getBodyPart(i); // 某一个邮件体也有可能是由多个邮件体组成的复杂体 String disposition = bodyPart.getDisposition(); // 正文:html格式 if (bodyPart.isMimeType("text/html")) { addHtml(bodyPart, messageDetailVo); } // 正文:文本格式 if (bodyPart.isMimeType("text/plain")) { addPlain(bodyPart, messageDetailVo); } // 正文:html格式 else if (part.isMimeType("text/html; charset=UTF-8")) { addHtmlUtf8(part, messageDetailVo); } // 附件 else if (disposition != null && (disposition.equalsIgnoreCase(Part.ATTACHMENT) || disposition.equalsIgnoreCase(Part.INLINE))) { MessageDetailVo.MessageAttachment messageAttachment = getMessageAttachment(bodyPart); messageDetailVo.getMessageAttachmentList().add(messageAttachment); } // 大对象 else if (bodyPart.isMimeType("multipart/*")) { getMessageAndAttachment(messageDetailVo, bodyPart, messageId); } // 其他类型 else { String contentType = bodyPart.getContentType(); if (contentType.contains("name") || contentType.contains("application")) { MessageDetailVo.MessageAttachment messageAttachment = getMessageAttachment(bodyPart); messageDetailVo.getMessageAttachmentList().add(messageAttachment); } else { if (!contentType.equals("text/html; charset=UTF-8")) log.error("未知文件格式:{} ,邮件id:{},待解析", contentType, messageId); } } } } // rfc822 else if (part.isMimeType("message/rfc822")) { getMessageAndAttachment(messageDetailVo, (Part) part.getContent(), messageId); } // 未知格式 else { log.error("未知文件格式:{} ,邮件id:{},待解析", part.getContentType(), messageId); } } private MessageDetailVo.MessageAttachment getMessageAttachment(Part part) throws MessagingException, IOException { InputStream is = part.getInputStream(); String fileName = decodeText(part.getFileName()); String url = ObsFileUtil.uploadFile(fileName, is); MessageDetailVo.MessageAttachment messageAttachment = new MessageDetailVo.MessageAttachment(); messageAttachment.setUrl(url); messageAttachment.setName(fileName); return messageAttachment; } private void addHtml(Part part, MessageDetailVo messageDetailVo) throws MessagingException, IOException { Object content = part.getContent(); if (content != null) { messageDetailVo.setContent(content.toString()); } else { messageDetailVo.setContent(StringPool.EMPTY); } messageDetailVo.setMimeType("text/html"); } private void addHtmlUtf8(Part part, MessageDetailVo messageDetailVo) throws MessagingException, IOException { Object content = part.getContent(); if (content != null) { messageDetailVo.setContent(content.toString()); } else { messageDetailVo.setContent(StringPool.EMPTY); } messageDetailVo.setMimeType("text/html; charset=UTF-8"); } private void addPlain(Part part, MessageDetailVo messageDetailVo) throws MessagingException, IOException { Object content = part.getContent(); if (content != null) { if (ObjectUtil.notEqual(messageDetailVo.getMimeType(), "text/html")) { messageDetailVo.setContent(content.toString()); messageDetailVo.setMimeType("text/plain"); } } } /** * 文本解码 */ private String decodeText(String encodeText) throws UnsupportedEncodingException { if (encodeText == null || StringPool.EMPTY.equals(encodeText)) { return StringPool.EMPTY; } else { return MimeUtility.decodeText(encodeText); } } // /** // * 上传文件 // */ // private String uploadFile(InputStream is, String fileName) { // // BufferedInputStream bis = new BufferedInputStream(is); // ByteArrayOutputStream baos = new ByteArrayOutputStream(); // BufferedOutputStream bos = new BufferedOutputStream(baos); // // try { // int len; // // while ((len = bis.read()) != -1) { // bos.write(len); // bos.flush(); // } // // bos.write(is.read()); // // // 上次附件至华为云 // ObsUpload obsUpload = new ObsUpload(); // obsUpload.setFileName(fileName); // obsUpload.setBytes(baos.toByteArray()); // R jsonObjectR = obsClient.uploadHuaWei(obsUpload); // if (jsonObjectR.isSuccess()) { // JSONObject data = jsonObjectR.getData(); // return data.getString("path"); // } // } catch (Exception e) { // log.error("上传文件出错", e); // throw new ServiceException("获取附件出现错误"); // } finally { // IoUtil.close(bos); // IoUtil.close(baos); // IoUtil.close(bis); // IoUtil.close(is); // } // return null; // } }