package com.smppw.modaq.application.util; import cn.hutool.core.exceptions.ExceptionUtil; import cn.hutool.core.map.MapUtil; import cn.hutool.core.util.StrUtil; import cn.hutool.extra.mail.JakartaUserPassAuthenticator; import com.smppw.modaq.common.conts.EmailTypeConst; import com.smppw.modaq.domain.dto.MailboxInfoDTO; import com.sun.mail.imap.IMAPStore; import jakarta.mail.Session; import jakarta.mail.Store; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Properties; /** * @author mozuwen * @date 2024-09-04 * @description 邮件解析工具 */ public class EmailUtil { private static final Logger logger = LoggerFactory.getLogger(EmailUtil.class); private static final String POP3 = "pop3"; private static final String IMAP = "imap"; // /** // * 采集邮件(多消息体)信息 // * // * @param message 邮件 // * @param emailAddress 邮箱地址 // * @param path 存储路径 // * @return 从邮箱采集到的信息 // * @throws Exception 异常信息 // */ // public static List collectMimeMultipart(Message message, String emailAddress, String path) throws Exception { // List emailContentInfoDTOList = CollUtil.newArrayList(); // String emailTitle = message.getSubject(); // String emailDate = DateUtil.format(message.getSentDate(), DateConst.YYYYMMDDHHMMSS24); // String emailDateStr = DateUtil.format(message.getSentDate(), DateConst.YYYYMMDD); // String filePath = path + File.separator + emailAddress + File.separator + emailDateStr + File.separator; // // MimeMultipart mimeMultipart = (MimeMultipart) message.getContent(); // int length = mimeMultipart.getCount(); // // 遍历邮件消息体 (我这里不要html正文) // for (int i = 0; i < length; i++) { // EmailContentInfoDTO emailContentInfoDTO = new EmailContentInfoDTO(); // MimeBodyPart part = (MimeBodyPart) mimeMultipart.getBodyPart(i); // Object partContent = part.getContent(); // String contentClass = part.getContent().getClass().getSimpleName(); // // 1.邮件正文 // switch (contentClass) { // case "String" -> { // // 文件名 = 邮件主题 + 邮件日期 // String fileName = emailTitle + "_" + emailDate + ".html"; // String content = partContent.toString(); // emailContentInfoDTO = collectTextPart(part, content, filePath, fileName); // } // case "BASE64DecoderStream" -> { // if (StrUtil.isNotBlank(part.getFileName())) { // String fileName = MimeUtility.decodeText(part.getFileName()); // if (isSupportedFileType(fileName)) { // continue; // } // emailContentInfoDTO.setFileName(fileName); // // String realPath = filePath + emailDate + fileName; // // File saveFile = cn.hutool.core.io.FileUtil.file(realPath); // if (!saveFile.exists()) { // if (!saveFile.getParentFile().exists()) { // saveFile.getParentFile().mkdirs(); // } // FileUtil.saveFile(saveFile, part); // } else { // cn.hutool.core.io.FileUtil.del(saveFile); // FileUtil.saveFile(saveFile, part); // } // emailContentInfoDTO.setFilePath(realPath); // } // } // case "MimeMultipart" -> { // MimeMultipart contentPart = (MimeMultipart) partContent; // int length2 = contentPart.getCount(); // for (int i2 = 0; i2 < length2; i2++) { // part = (MimeBodyPart) contentPart.getBodyPart(i2); // partContent = part.getContent(); // contentClass = partContent.getClass().getSimpleName(); // if ("String".equals(contentClass)) { // // 文件名 = 邮件主题 + 邮件日期 // String fileName = emailTitle + "_" + emailDate + ".html"; // String content = partContent.toString(); // emailContentInfoDTO = collectTextPart(part, content, filePath, fileName); // } // } // } // } // String filepath = emailContentInfoDTO.getFilePath(); // if (emailContentInfoDTO.getEmailContent() == null && filepath == null) { // continue; // } // emailContentInfoDTO.setEmailAddress(emailAddress); // emailContentInfoDTO.setEmailTitle(emailTitle); // emailContentInfoDTO.setEmailDate(DateUtil.format(message.getSentDate(), DateConst.YYYY_MM_DD_HH_MM_SS)); // emailContentInfoDTOList.add(emailContentInfoDTO); // } // // return emailContentInfoDTOList; // } // private static List zipFile(String filepath) { // return null; // } // private static boolean isSupportedFileType(String fileName) { // if (StrUtil.isBlank(fileName)) { // return true; // } // return !ExcelUtil.isZip(fileName) && !ExcelUtil.isExcel(fileName) && !ExcelUtil.isPdf(fileName) && !ExcelUtil.isHTML(fileName) && !ExcelUtil.isRAR(fileName); // } // /** // * 根据日期过滤邮件 // * // * @param messages 采集到的邮件 // * @param startDate 邮件起始日期 // * @param endDate 邮件截止日期 // * @return 符合日期的邮件 // */ // public static List filterMessage(Message[] messages, Date startDate, Date endDate) { // long startTime = System.currentTimeMillis(); // List messageList = CollUtil.newArrayList(); // if (messages == null) { // return messageList; // } // for (Message message : messages) { // try { // if (message.getSentDate().compareTo(startDate) >= 0 && message.getSentDate().compareTo(endDate) <= 0) { // messageList.add(message); // } // } catch (MessagingException e) { // throw new RuntimeException(e); // } // } // logger.info("根据日期过滤邮件耗时 -> {}ms", (System.currentTimeMillis() - startTime)); // return messageList; // } // /** // * 采集邮件正文 // * // * @param part 邮件消息体 // * @param partContent 邮件消息内筒 // * @param filePath 文件路径 // * @param fileName 文件名 // * @return 采集到邮件正文(html格式包含table标签) // */ // public static EmailContentInfoDTO collectTextPart(MimeBodyPart part, String partContent, String filePath, String fileName) { // EmailContentInfoDTO emailContentInfoDTO = new EmailContentInfoDTO(); // try { // if ((part.getContentType().contains("text/html") || part.getContentType().contains("TEXT/HTML"))) { // emailContentInfoDTO.setEmailContent(partContent); // String savePath = filePath + fileName; // File saveFile = new File(savePath); // if (!saveFile.exists()) { // if (!saveFile.getParentFile().exists()) { // saveFile.getParentFile().mkdirs(); // saveFile.getParentFile().setExecutable(true); // } // } // //获取邮件编码 // String contentType = part.getContentType(); // String html = partContent.toString(); // try { // if (contentType.contains("charset=")) { // contentType = contentType.substring(contentType.indexOf("charset=") + 8).replaceAll("\"", ""); // html = html.replace("charset=" + contentType.toLowerCase(), "charset=UTF-8"); // html = html.replace("charset=" + contentType.toUpperCase(), "charset=UTF-8"); // } // if (savePath.contains(":")) { // savePath = savePath.replaceAll(":", ""); // } // cn.hutool.core.io.FileUtil.writeUtf8String(html, new File(savePath)); // } catch (Exception e) { // logger.error(e.getMessage(), e); // } // emailContentInfoDTO.setFileName(fileName); // emailContentInfoDTO.setFilePath(savePath); // } else { // try { // if (part.getFileName() == null) { // return emailContentInfoDTO; // } // String fileName1 = MimeUtility.decodeText(part.getFileName()); // if (isSupportedFileType(fileName1)) { // return emailContentInfoDTO; // } // emailContentInfoDTO.setFileName(fileName1); // String realPath = filePath + fileName1; // File saveFile = new File(realPath); // if (!saveFile.exists()) { // if (!saveFile.getParentFile().exists()) { // saveFile.getParentFile().mkdirs(); // } // FileUtil.saveFile(saveFile, part); // } else { // cn.hutool.core.io.FileUtil.del(saveFile); // FileUtil.saveFile(saveFile, part); // } // emailContentInfoDTO.setFilePath(realPath); // } catch (Exception e) { // return emailContentInfoDTO; // } // } // } catch (MessagingException e) { // logger.info("邮件正文采集失败 -> 文件名:{}, 报错堆栈:{}", fileName, ExceptionUtil.stacktraceToString(e)); // return emailContentInfoDTO; // } // return emailContentInfoDTO; // } /** * 判断邮件是否符合解析条件 * * @param subject 邮件主题 * @param emailTypeMap 邮件类型识别规则映射表 * @return 邮件类型:1-净值,2-估值表,3-定期报告 -> 兜底为净值类型 */ public static Integer getEmailTypeBySubject(String subject, Map> emailTypeMap) { if (MapUtil.isEmpty(emailTypeMap) || StrUtil.isBlank(subject)) { return EmailTypeConst.NAV_EMAIL_TYPE; } for (Map.Entry> emailTypeEntry : emailTypeMap.entrySet()) { for (String field : emailTypeEntry.getValue()) { if (subject.contains(field)) { return emailTypeEntry.getKey(); } } } return EmailTypeConst.NAV_EMAIL_TYPE; } public static Store getStoreNew(MailboxInfoDTO mailboxInfoDTO) { // 配置连接邮件服务器参数 Properties props = getMailProps(mailboxInfoDTO); // 创建Session实例对象 Session session = Session.getInstance(props, new JakartaUserPassAuthenticator(mailboxInfoDTO.getAccount(), mailboxInfoDTO.getPassword())); Store store; try { String protocol = mailboxInfoDTO.getProtocol().equals(IMAP) ? "imaps" : "pop3"; if (mailboxInfoDTO.getProtocol().contains(IMAP)) { IMAPStore imapStore = (IMAPStore) session.getStore(protocol); imapStore.connect(mailboxInfoDTO.getHost(), mailboxInfoDTO.getAccount(), mailboxInfoDTO.getPassword()); // 网易邮箱需要带上身份标识,详情请看:https://www.hmail163.com/content/?404.html Map clientParams = new HashMap<>(2); clientParams.put("name", "my-imap"); clientParams.put("version", "1.0"); imapStore.id(clientParams); return imapStore; } else { store = session.getStore(protocol); store.connect(mailboxInfoDTO.getHost(), mailboxInfoDTO.getAccount(), mailboxInfoDTO.getPassword()); return store; } } catch (Exception e) { logger.error("邮箱信息:{},服务器参数:{}", mailboxInfoDTO, props); logger.error("连接邮箱报错堆栈信息:{}", ExceptionUtil.stacktraceToString(e)); return null; } } public static Properties getMailProps(MailboxInfoDTO mailboxInfoDTO) { Properties props = new Properties(); if (mailboxInfoDTO.getProtocol().equalsIgnoreCase(POP3)) { props.put("mail.pop3.host", mailboxInfoDTO.getHost()); props.put("mail.pop3.user", mailboxInfoDTO.getAccount()); props.put("mail.pop3.socketFactory", mailboxInfoDTO.getPort()); props.put("mail.pop3.socketFactory.class", "javax.net.ssl.SSLSocketFactory"); props.put("mail.pop3.port", mailboxInfoDTO.getPort()); props.put("mail.store.protocol", mailboxInfoDTO.getProtocol()); } if (mailboxInfoDTO.getProtocol().equalsIgnoreCase(IMAP)) { props.put("mail.store.protocol", "imaps"); props.put("mail.imap.host", mailboxInfoDTO.getHost()); props.put("mail.imap.port", mailboxInfoDTO.getPort()); props.put("mail.imaps.ssl.enable", "true"); props.put("mail.imaps.ssl.trust", "*"); props.put("mail.imap.auth", "true"); props.put("mail.imap.starttls.enable", "true"); props.put("mail.imap.socketFactory.class", "javax.net.ssl.SSLSocketFactory"); props.put("mail.imap.socketFactory.fallback", "false"); // 关闭读取附件时分批获取 BASE64 输入流的配置 props.put("mail.imap.partialfetch", false); props.put("mail.imaps.partialfetch", false); } return props; } // public static void senEmail(MailboxInfoDTO mailboxInfoDTO, String emails, File file, String htmlText, String host, String emailTitle) throws Exception { // logger.info("send email begin ........."); // // 根据Session 构建邮件信息 // MimeMessage message = new MimeMessage(getSession(mailboxInfoDTO)); // // 创建邮件发送者地址 // Address from = new InternetAddress(mailboxInfoDTO.getAccount() + host); // String[] emailArr = emails.split(";"); // Address[] toArr = new Address[emailArr.length]; // for (int idx = 0; idx < emailArr.length; idx++) { // if (StrUtil.isNotBlank(emailArr[idx])) { // Address to = new InternetAddress(emailArr[idx]); // toArr[idx] = to; // } // } // message.setFrom(from); // message.setRecipients(Message.RecipientType.TO, toArr); // // 邮件主题 // message.setSubject(emailTitle); // // 邮件容器 // MimeMultipart mimeMultiPart = new MimeMultipart(); // // 设置HTML // BodyPart bodyPart = new MimeBodyPart(); // logger.info("组装 htmlText........."); // // 邮件内容 // bodyPart.setContent(htmlText, "text/html;charset=utf-8"); // //设置附件 // BodyPart filePart = new MimeBodyPart(); // filePart.setFileName(file.getName()); // filePart.setDataHandler( // new DataHandler( // new ByteArrayDataSource( // Files.readAllBytes(Paths.get(file.getAbsolutePath())), "application/octet-stream"))); // mimeMultiPart.addBodyPart(bodyPart); // mimeMultiPart.addBodyPart(filePart); // message.setContent(mimeMultiPart); // message.setSentDate(new Date()); // // 保存邮件 // message.saveChanges(); // // 发送邮件 // Transport.send(message); // } // public static Session getSession(MailboxInfoDTO mailboxInfoDTO) { // try { // Properties properties = new Properties(); // properties.put("mail.smtp.host", mailboxInfoDTO.getHost()); // properties.put("mail.smtp.auth", true); // properties.put("mail.smtp.port", mailboxInfoDTO.getPort()); // properties.put("mail.smtp.ssl.enable", true); // final String SSL_FACTORY = "javax.net.ssl.SSLSocketFactory"; // properties.setProperty("mail.smtp.socketFactory.class", SSL_FACTORY); // properties.setProperty("mail.smtp.socketFactory.fallback", "false"); // properties.setProperty("mail.smtp.socketFactory.port", mailboxInfoDTO.getPort()); // // 根据邮件的会话属性构造一个发送邮件的Session, // JakartaUserPassAuthenticator authenticator = new JakartaUserPassAuthenticator(mailboxInfoDTO.getAccount(), mailboxInfoDTO.getPassword()); // return Session.getInstance(properties, authenticator); // } catch (Exception e) { // logger.error("getSession : {}", e.getMessage()); // } // return null; // } }