MailServiceImpl.java 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411
  1. package com.fjhx.email.service.impl;
  2. import cn.hutool.core.bean.BeanUtil;
  3. import cn.hutool.core.util.ObjectUtil;
  4. import com.baomidou.mybatisplus.core.toolkit.StringPool;
  5. import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
  6. import com.fjhx.email.config.exception.ServiceException;
  7. import com.fjhx.email.entity.*;
  8. import com.fjhx.email.entity.dto.GetMessagePageDto;
  9. import com.fjhx.email.entity.dto.MailSyncInfo;
  10. import com.fjhx.email.entity.dto.MailboxInfo;
  11. import com.fjhx.email.entity.vo.MessageDetailVo;
  12. import com.fjhx.email.entity.vo.MessageVo;
  13. import com.fjhx.email.mapper.MailMapper;
  14. import com.fjhx.email.service.*;
  15. import com.fjhx.email.utils.EmailUtil;
  16. import com.fjhx.email.utils.ObsFileUtil;
  17. import com.fjhx.email.utils.PageWrapper;
  18. import com.sun.mail.imap.IMAPFolder;
  19. import com.sun.mail.imap.IMAPMessage;
  20. import com.sun.mail.imap.IMAPStore;
  21. import lombok.SneakyThrows;
  22. import lombok.extern.slf4j.Slf4j;
  23. import org.springframework.beans.factory.annotation.Autowired;
  24. import org.springframework.stereotype.Service;
  25. import javax.mail.*;
  26. import javax.mail.internet.MimeUtility;
  27. import java.io.IOException;
  28. import java.io.InputStream;
  29. import java.io.UnsupportedEncodingException;
  30. import java.util.ArrayList;
  31. import java.util.List;
  32. @Slf4j
  33. @Service
  34. public class MailServiceImpl implements IMailService {
  35. @Autowired
  36. private MailMapper mailMapper;
  37. @Autowired
  38. private IPersonalMessageService personalMessageService;
  39. @Autowired
  40. private IEnterpriseMessageService enterpriseMessageService;
  41. @Autowired
  42. private IEnterpriseMessageAddressService enterpriseMessageAddressService;
  43. @Autowired
  44. private IEnterpriseMessageAttachmentService enterpriseMessageAttachmentService;
  45. @Autowired
  46. private IEnterpriseMessageContentService enterpriseMessageContentService;
  47. @Autowired
  48. private IPersonalMessageAddressService personalMessageAddressService;
  49. @Autowired
  50. private IPersonalMessageAttachmentService personalMessageAttachmentService;
  51. @Autowired
  52. private IPersonalMessageContentService personalMessageContentService;
  53. @Autowired
  54. private IPersonalMailboxService personalMailboxService;
  55. @Autowired
  56. private IEnterpriseMailboxService enterpriseMailboxService;
  57. @Autowired
  58. private IEnterpriseDomainService enterpriseDomainService;
  59. @Override
  60. public List<MailboxInfo> getMailboxInfoListByUserId(List<Long> userIdList) {
  61. return mailMapper.getMailboxInfoListByUserId(userIdList, MailSyncInfo.mailType);
  62. }
  63. @Override
  64. public PageWrapper<MessageVo> getMessagePage(GetMessagePageDto dto) {
  65. if (dto.getType().equals(1)) {
  66. Page<PersonalMessage> page = personalMessageService.page(dto, q -> q
  67. .eq(PersonalMessage::getFolderId, dto.getFolderId())
  68. .orderByDesc(PersonalMessage::getSendDate)
  69. );
  70. return new PageWrapper<>(page, MessageVo.class);
  71. }
  72. Page<EnterpriseMessage> page = enterpriseMessageService.page(dto, q -> q
  73. .eq(EnterpriseMessage::getFolderId, dto.getFolderId())
  74. .orderByDesc(EnterpriseMessage::getSendDate)
  75. );
  76. return new PageWrapper<>(page, MessageVo.class);
  77. }
  78. @SneakyThrows
  79. @Override
  80. public MessageDetailVo getMessageDetail(GetMessagePageDto dto) {
  81. Long messageId = dto.getMessageId();
  82. Integer contentSync;
  83. Integer addressSync;
  84. Integer attachmentSync;
  85. Integer messageNumber;
  86. String folderName;
  87. Long mailboxId;
  88. if (dto.getType().equals(1)) {
  89. PersonalMessage personalMessage = personalMessageService.getById(messageId);
  90. if (personalMessage == null) {
  91. throw new ServiceException("没有找到邮箱");
  92. }
  93. messageNumber = personalMessage.getMessageNumber();
  94. contentSync = personalMessage.getContentSync();
  95. addressSync = personalMessage.getAddressSync();
  96. attachmentSync = personalMessage.getAttachmentSync();
  97. folderName = personalMessage.getFolderName();
  98. mailboxId = personalMessage.getMailboxId();
  99. } else {
  100. EnterpriseMessage enterpriseMessage = enterpriseMessageService.getById(messageId);
  101. if (enterpriseMessage == null) {
  102. throw new ServiceException("没有找到邮箱");
  103. }
  104. messageNumber = enterpriseMessage.getMessageNumber();
  105. contentSync = enterpriseMessage.getContentSync();
  106. addressSync = enterpriseMessage.getAddressSync();
  107. attachmentSync = enterpriseMessage.getAttachmentSync();
  108. folderName = enterpriseMessage.getFolderName();
  109. mailboxId = enterpriseMessage.getMailboxId();
  110. }
  111. MessageDetailVo messageDetailVo = new MessageDetailVo();
  112. // 正文附件已同步
  113. if (contentSync == 1 && addressSync == 1 && attachmentSync == 1) {
  114. if (dto.getType().equals(1)) {
  115. setPersonalMessageDetailVo(messageDetailVo, messageId);
  116. } else {
  117. setEnterpriseMessageDetailVo(messageDetailVo, messageId);
  118. }
  119. }
  120. // 未同步
  121. else {
  122. MailboxInfo mailboxInfo = getMailboxInfo(dto.getType(), mailboxId);
  123. IMAPStore imapStore = EmailUtil.getIMAPStore(mailboxInfo);
  124. IMAPFolder folder = (IMAPFolder) imapStore.getFolder(folderName);
  125. folder.open(Folder.READ_ONLY);
  126. IMAPMessage message = (IMAPMessage) folder.getMessage(messageNumber);
  127. messageDetailVo.setMessageAttachmentList(new ArrayList<>());
  128. getMessageAndAttachment(messageDetailVo, message, messageId);
  129. messageDetailVo.setMessageAddressList(EmailUtil.mailAddressList(message));
  130. }
  131. for (MessageDetailVo.MessageAttachment messageAttachment : messageDetailVo.getMessageAttachmentList()) {
  132. messageAttachment.setUrl(ObsFileUtil.getCompleteUrl(messageAttachment.getUrl()));
  133. }
  134. return messageDetailVo;
  135. }
  136. private MailboxInfo getMailboxInfo(Integer type, Long mailboxId) {
  137. MailboxInfo mailboxInfo = new MailboxInfo();
  138. if (type.equals(1)) {
  139. PersonalMailbox personalMailbox = personalMailboxService.getById(mailboxId);
  140. mailboxInfo.setReceiveHost(personalMailbox.getReceiveHost());
  141. mailboxInfo.setReceivePort(personalMailbox.getReceivePort());
  142. mailboxInfo.setMailUser(personalMailbox.getMailUser());
  143. mailboxInfo.setMailPassword(personalMailbox.getMailPassword());
  144. return mailboxInfo;
  145. }
  146. EnterpriseMailbox enterpriseMailbox = enterpriseMailboxService.getById(mailboxId);
  147. EnterpriseDomain enterpriseDomain = enterpriseDomainService.getById(enterpriseMailbox.getDomainId());
  148. mailboxInfo.setReceiveHost(enterpriseDomain.getReceiveHost());
  149. mailboxInfo.setReceivePort(enterpriseDomain.getReceivePort());
  150. mailboxInfo.setMailUser(enterpriseMailbox.getMailUserPrefix() + "@" + enterpriseDomain.getDomanName());
  151. mailboxInfo.setMailPassword(enterpriseMailbox.getMailPassword());
  152. return mailboxInfo;
  153. }
  154. private void setPersonalMessageDetailVo(MessageDetailVo vo, Long messageId) {
  155. List<PersonalMessageAddress> addressList = personalMessageAddressService.list(
  156. q -> q.eq(PersonalMessageAddress::getMessageId, messageId));
  157. vo.setMessageAddressList(BeanUtil.copyToList(addressList, MessageDetailVo.MessageAddress.class));
  158. List<PersonalMessageAttachment> attachmentList = personalMessageAttachmentService.list(
  159. q -> q.eq(PersonalMessageAttachment::getMessageId, messageId));
  160. vo.setMessageAttachmentList(BeanUtil.copyToList(attachmentList, MessageDetailVo.MessageAttachment.class));
  161. PersonalMessageContent content = personalMessageContentService.getOne(
  162. q -> q.eq(PersonalMessageContent::getMessageId, messageId));
  163. vo.setContent(content.getContent());
  164. }
  165. private void setEnterpriseMessageDetailVo(MessageDetailVo vo, Long messageId) {
  166. List<EnterpriseMessageAddress> addressList = enterpriseMessageAddressService.list(
  167. q -> q.eq(EnterpriseMessageAddress::getMessageId, messageId));
  168. vo.setMessageAddressList(BeanUtil.copyToList(addressList, MessageDetailVo.MessageAddress.class));
  169. List<EnterpriseMessageAttachment> attachmentList = enterpriseMessageAttachmentService.list(
  170. q -> q.eq(EnterpriseMessageAttachment::getMessageId, messageId));
  171. vo.setMessageAttachmentList(BeanUtil.copyToList(attachmentList, MessageDetailVo.MessageAttachment.class));
  172. EnterpriseMessageContent content = enterpriseMessageContentService.getOne(
  173. q -> q.eq(EnterpriseMessageContent::getMessageId, messageId));
  174. vo.setContent(content.getContent());
  175. }
  176. /**
  177. * 保存附件和正文
  178. */
  179. private void getMessageAndAttachment(MessageDetailVo messageDetailVo, Part part, Long messageId)
  180. throws MessagingException, IOException {
  181. // 正文:文本格式
  182. if (part.isMimeType("text/plain")) {
  183. addPlain(part, messageDetailVo);
  184. }
  185. // 正文:html格式
  186. else if (part.isMimeType("text/html")) {
  187. addHtml(part, messageDetailVo);
  188. }
  189. // 正文:html格式
  190. else if (part.isMimeType("text/html; charset=UTF-8")) {
  191. addHtmlUtf8(part, messageDetailVo);
  192. }
  193. // 大对象
  194. else if (part.isMimeType("multipart/*")) {
  195. // 复杂体邮件
  196. Multipart multipart = (Multipart) part.getContent();
  197. // 复杂体邮件包含多个邮件体
  198. int partCount = multipart.getCount();
  199. for (int i = 0; i < partCount; i++) {
  200. // 获得复杂体邮件中其中一个邮件体
  201. BodyPart bodyPart = multipart.getBodyPart(i);
  202. // 某一个邮件体也有可能是由多个邮件体组成的复杂体
  203. String disposition = bodyPart.getDisposition();
  204. // 正文:html格式
  205. if (bodyPart.isMimeType("text/html")) {
  206. addHtml(bodyPart, messageDetailVo);
  207. }
  208. // 正文:文本格式
  209. if (bodyPart.isMimeType("text/plain")) {
  210. addPlain(bodyPart, messageDetailVo);
  211. }
  212. // 正文:html格式
  213. else if (part.isMimeType("text/html; charset=UTF-8")) {
  214. addHtmlUtf8(part, messageDetailVo);
  215. }
  216. // 附件
  217. else if (disposition != null
  218. && (disposition.equalsIgnoreCase(Part.ATTACHMENT) || disposition.equalsIgnoreCase(Part.INLINE))) {
  219. MessageDetailVo.MessageAttachment messageAttachment = getMessageAttachment(bodyPart);
  220. messageDetailVo.getMessageAttachmentList().add(messageAttachment);
  221. }
  222. // 大对象
  223. else if (bodyPart.isMimeType("multipart/*")) {
  224. getMessageAndAttachment(messageDetailVo, bodyPart, messageId);
  225. }
  226. // 其他类型
  227. else {
  228. String contentType = bodyPart.getContentType();
  229. if (contentType.contains("name") || contentType.contains("application")) {
  230. MessageDetailVo.MessageAttachment messageAttachment = getMessageAttachment(bodyPart);
  231. messageDetailVo.getMessageAttachmentList().add(messageAttachment);
  232. } else {
  233. if (!contentType.equals("text/html; charset=UTF-8"))
  234. log.error("未知文件格式:{} ,邮件id:{},待解析", contentType, messageId);
  235. }
  236. }
  237. }
  238. }
  239. // rfc822
  240. else if (part.isMimeType("message/rfc822")) {
  241. getMessageAndAttachment(messageDetailVo, (Part) part.getContent(), messageId);
  242. }
  243. // 未知格式
  244. else {
  245. log.error("未知文件格式:{} ,邮件id:{},待解析", part.getContentType(), messageId);
  246. }
  247. }
  248. private MessageDetailVo.MessageAttachment getMessageAttachment(Part part)
  249. throws MessagingException, IOException {
  250. InputStream is = part.getInputStream();
  251. String fileName = decodeText(part.getFileName());
  252. String url = ObsFileUtil.uploadFile(fileName, is);
  253. MessageDetailVo.MessageAttachment messageAttachment = new MessageDetailVo.MessageAttachment();
  254. messageAttachment.setUrl(url);
  255. messageAttachment.setName(fileName);
  256. return messageAttachment;
  257. }
  258. private void addHtml(Part part, MessageDetailVo messageDetailVo) throws MessagingException, IOException {
  259. Object content = part.getContent();
  260. if (content != null) {
  261. messageDetailVo.setContent(content.toString());
  262. } else {
  263. messageDetailVo.setContent(StringPool.EMPTY);
  264. }
  265. messageDetailVo.setMimeType("text/html");
  266. }
  267. private void addHtmlUtf8(Part part, MessageDetailVo messageDetailVo) throws MessagingException, IOException {
  268. Object content = part.getContent();
  269. if (content != null) {
  270. messageDetailVo.setContent(content.toString());
  271. } else {
  272. messageDetailVo.setContent(StringPool.EMPTY);
  273. }
  274. messageDetailVo.setMimeType("text/html; charset=UTF-8");
  275. }
  276. private void addPlain(Part part, MessageDetailVo messageDetailVo) throws MessagingException, IOException {
  277. Object content = part.getContent();
  278. if (content != null) {
  279. if (ObjectUtil.notEqual(messageDetailVo.getMimeType(), "text/html")) {
  280. messageDetailVo.setContent(content.toString());
  281. messageDetailVo.setMimeType("text/plain");
  282. }
  283. }
  284. }
  285. /**
  286. * 文本解码
  287. */
  288. private String decodeText(String encodeText) throws UnsupportedEncodingException {
  289. if (encodeText == null || StringPool.EMPTY.equals(encodeText)) {
  290. return StringPool.EMPTY;
  291. } else {
  292. return MimeUtility.decodeText(encodeText);
  293. }
  294. }
  295. // /**
  296. // * 上传文件
  297. // */
  298. // private String uploadFile(InputStream is, String fileName) {
  299. //
  300. // BufferedInputStream bis = new BufferedInputStream(is);
  301. // ByteArrayOutputStream baos = new ByteArrayOutputStream();
  302. // BufferedOutputStream bos = new BufferedOutputStream(baos);
  303. //
  304. // try {
  305. // int len;
  306. //
  307. // while ((len = bis.read()) != -1) {
  308. // bos.write(len);
  309. // bos.flush();
  310. // }
  311. //
  312. // bos.write(is.read());
  313. //
  314. // // 上次附件至华为云
  315. // ObsUpload obsUpload = new ObsUpload();
  316. // obsUpload.setFileName(fileName);
  317. // obsUpload.setBytes(baos.toByteArray());
  318. // R<JSONObject> jsonObjectR = obsClient.uploadHuaWei(obsUpload);
  319. // if (jsonObjectR.isSuccess()) {
  320. // JSONObject data = jsonObjectR.getData();
  321. // return data.getString("path");
  322. // }
  323. // } catch (Exception e) {
  324. // log.error("上传文件出错", e);
  325. // throw new ServiceException("获取附件出现错误");
  326. // } finally {
  327. // IoUtil.close(bos);
  328. // IoUtil.close(baos);
  329. // IoUtil.close(bis);
  330. // IoUtil.close(is);
  331. // }
  332. // return null;
  333. // }
  334. }