From e6731fe4d855604ec8e7c93c45777f0d08e5f0e9 Mon Sep 17 00:00:00 2001 From: "zhenghaiyang@ele-cloud.com" Date: Wed, 22 Mar 2023 16:31:06 +0800 Subject: [PATCH] =?UTF-8?q?feature=201.=E6=96=B0=E5=A2=9E=E9=82=AE?= =?UTF-8?q?=E7=AE=B1=E9=87=87=E9=9B=86=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- dxhy-core/pom.xml | 10 + .../com/dxhy/core/task/SnEmailGatherTask.java | 120 +++++++ .../com/dxhy/core/util/EmailParseUtils.java | 313 ++++++++++++++++++ 3 files changed, 443 insertions(+) create mode 100644 dxhy-core/src/main/java/com/dxhy/core/task/SnEmailGatherTask.java create mode 100644 dxhy-core/src/main/java/com/dxhy/core/util/EmailParseUtils.java diff --git a/dxhy-core/pom.xml b/dxhy-core/pom.xml index 82b7580a..2562a47a 100644 --- a/dxhy-core/pom.xml +++ b/dxhy-core/pom.xml @@ -13,6 +13,16 @@ ${jxpt.version} jar + + javax.mail + javax.mail-api + 1.6.2 + + + com.sun.mail + javax.mail + 1.6.2 + com.dxhy.jxpt dxhy-common diff --git a/dxhy-core/src/main/java/com/dxhy/core/task/SnEmailGatherTask.java b/dxhy-core/src/main/java/com/dxhy/core/task/SnEmailGatherTask.java new file mode 100644 index 00000000..78653b5f --- /dev/null +++ b/dxhy-core/src/main/java/com/dxhy/core/task/SnEmailGatherTask.java @@ -0,0 +1,120 @@ +package com.dxhy.core.task; + + +import com.dxhy.core.job.service.ScheduleJobService; +import com.dxhy.core.util.EmailParseUtils; +import com.sun.mail.pop3.POP3Folder; +import lombok.SneakyThrows; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +import javax.annotation.Resource; +import javax.mail.*; +import javax.mail.internet.MimeMessage; +import java.util.Date; +import java.util.Properties; + + +@Component("snEmailGatherTask") +@Slf4j +public class SnEmailGatherTask { + + @Resource + private ScheduleJobService scheduleJobService; + + + public void mailGatherTask(){ + //进行邮件采集 + + + } + + + + @SneakyThrows + public static void main(String[] args) { + + //邮件接收协议 + String mail_protocol = "mail.store.protocol"; + //邮件接收协议类型 + String mail_protocol_type2 = "pop3"; + String mail_protocol_type = "pop"; + + //邮件接收服务器端口 + String mail_port = "mail.pop3.port"; + //邮件接收服务器端口 + String port = "110"; + //邮件接收服务器地址 + String mail_host = "mail.pop3.host"; + String emailName = "1149953701@qq.com"; + String password = "pmdzleyabmlzgdhc"; + + String mailSuffix = emailName.split("@")[1]; + //邮箱类型 + String mailType = mailSuffix.split("\\.")[0]; + Properties props = new Properties(); + if(mailType.equalsIgnoreCase("qq")){ + //qq邮箱 + props.setProperty(mail_protocol, mail_protocol_type2); // 协议 + props.setProperty(mail_host, mail_protocol_type+"."+mailSuffix); // pop3服务器 + props.setProperty(mail_port, port); // 端口 + }else { + props.setProperty(mail_protocol, mail_protocol_type2); // 协议 + props.setProperty(mail_host, mail_protocol_type2+"."+mailSuffix); // pop3服务器 + props.setProperty(mail_port, port); // 端口 + } + Session session = Session.getInstance(props); + Store store = session.getStore("pop3"); + + //连接邮箱服务器 + store.connect(emailName, password); + //获取当前时间 + Date currentTime = new Date(); + // 获得收件箱 pop3协议只有一个有效的文件夹就是INBOX + Folder folder = store.getFolder("INBOX"); + //获取邮件列表 + folder.open(Folder.READ_WRITE); + + // 由于POP3协议无法获知邮件的状态,所以getUnreadMessageCount得到的是收件箱的邮件总数 + System.out.println("未读邮件数: " + folder.getUnreadMessageCount()); + + // 由于POP3协议无法获知邮件的状态,所以下面得到的结果始终都是为0 + System.out.println("删除邮件数: " + folder.getDeletedMessageCount()); + System.out.println("新邮件: " + folder.getNewMessageCount()); + + // 获得收件箱中的邮件总数 + System.out.println("邮件总数: " + folder.getMessageCount()); + + Message[] messages = folder.getMessages(); + for (int i = 0, count = messages.length; i < count; i++) { + MimeMessage msg = (MimeMessage) messages[i]; + System.out.println("------------------解析第" + msg.getMessageNumber() + "封邮件-------------------- "); + System.out.println("主题: " + EmailParseUtils.getSubject(msg)); + System.out.println("发件人: " + EmailParseUtils.getFrom(msg)); + System.out.println("收件人:" + EmailParseUtils.getReceiveAddress(msg, null)); + System.out.println("发送时间:" + EmailParseUtils.getSentDate(msg, null)); + System.out.println("是否已读:" + EmailParseUtils.isSeen(msg)); + System.out.println("邮件优先级:" + EmailParseUtils.getPriority(msg)); + System.out.println("是否需要回执:" + EmailParseUtils.isReplySign(msg)); + System.out.println("邮件大小:" + msg.getSize() * 1024 + "kb"); + boolean isContainerAttachment = EmailParseUtils.isContainAttachment(msg); + POP3Folder inbox = (POP3Folder) folder; + String uid = inbox.getUID(msg); + System.out.println("uid: ------------------" + uid); + Flags flags = msg.getFlags(); + if (!flags.contains(Flags.Flag.SEEN)) { + //设置为已读 + msg.setFlag(Flags.Flag.SEEN, true); + } + System.out.println(""); + } + System.out.println(""); + + Date endTime = new Date(); + //计算耗时时间 +// double elapsedTime = CalendarUtil.arithDateTime(endTime, currentTime); + // 释放资源 + folder.close(false); // false为不更新邮件,true为更新,一般在删除邮件后使用 + store.close(); + } +} diff --git a/dxhy-core/src/main/java/com/dxhy/core/util/EmailParseUtils.java b/dxhy-core/src/main/java/com/dxhy/core/util/EmailParseUtils.java new file mode 100644 index 00000000..2028594c --- /dev/null +++ b/dxhy-core/src/main/java/com/dxhy/core/util/EmailParseUtils.java @@ -0,0 +1,313 @@ +package com.dxhy.core.util; + +import javax.mail.*; +import javax.mail.internet.InternetAddress; +import javax.mail.internet.MimeMessage; +import javax.mail.internet.MimeMultipart; +import javax.mail.internet.MimeUtility; +import java.io.*; +import java.text.SimpleDateFormat; +import java.util.Date; + +public class EmailParseUtils { + + /** + * 解析邮件 + * + * @param messages 要解析的邮件列表 + */ + public static void deleteMessage(Message... messages) throws MessagingException, IOException { + if (messages == null || messages.length < 1) + throw new MessagingException("未找到要解析的邮件!"); + + // 解析所有邮件 + for (int i = 0, count = messages.length; i < count; i++) { + + /** + * 邮件删除 + */ + Message message = messages[i]; + String subject = message.getSubject(); + // set the DELETE flag to true + message.setFlag(Flags.Flag.DELETED, true); + System.out.println("Marked DELETE for message: " + subject); + + + } + } + + /** + * 获得邮件主题 + * + * @param msg 邮件内容 + * @return 解码后的邮件主题 + */ + public static String getSubject(MimeMessage msg) throws UnsupportedEncodingException, MessagingException { + return MimeUtility.decodeText(msg.getSubject()); + } + + /** + * 获得邮件发件人 + * + * @param msg 邮件内容 + * @return 姓名 + * @throws MessagingException + * @throws UnsupportedEncodingException + */ + public static String getFrom(MimeMessage msg) throws MessagingException, UnsupportedEncodingException { + String from = ""; + Address[] froms = msg.getFrom(); + if (froms.length < 1) + throw new MessagingException("没有发件人!"); + + InternetAddress address = (InternetAddress) froms[0]; + String person = address.getPersonal(); + if (person != null) { + person = MimeUtility.decodeText(person) + " "; + } else { + person = ""; + } + from = person + "<" + address.getAddress() + ">"; + + return from; + } + + /** + * 根据收件人类型,获取邮件收件人、抄送和密送地址。如果收件人类型为空,则获得所有的收件人 + *

Message.RecipientType.TO 收件人

+ *

Message.RecipientType.CC 抄送

+ *

Message.RecipientType.BCC 密送

+ * + * @param msg 邮件内容 + * @param type 收件人类型 + * @return 收件人1 <邮件地址1>, 收件人2 <邮件地址2>, ... + * @throws MessagingException + */ + public static String getReceiveAddress(MimeMessage msg, Message.RecipientType type) throws MessagingException { + StringBuffer receiveAddress = new StringBuffer(); + Address[] addresss = null; + if (type == null) { + addresss = msg.getAllRecipients(); + } else { + addresss = msg.getRecipients(type); + } + + if (addresss == null || addresss.length < 1) + throw new MessagingException("没有收件人!"); + for (Address address : addresss) { + InternetAddress internetAddress = (InternetAddress) address; + receiveAddress.append(internetAddress.toUnicodeString()).append(","); + } + + receiveAddress.deleteCharAt(receiveAddress.length() - 1); //删除最后一个逗号 + + return receiveAddress.toString(); + } + + /** + * 获得邮件发送时间 + * + * @param msg 邮件内容 + * @return yyyy年mm月dd日 星期X HH:mm + * @throws MessagingException + */ + public static String getSentDate(MimeMessage msg, String pattern) throws MessagingException { + Date receivedDate = msg.getSentDate(); + if (receivedDate == null) + return ""; + + if (pattern == null || "".equals(pattern)) + pattern = "yyyy年MM月dd日 E HH:mm "; + + return new SimpleDateFormat(pattern).format(receivedDate); + } + + /** + * 判断邮件中是否包含附件 + *

+ * //* @param msg 邮件内容 + * + * @return 邮件中存在附件返回true,不存在返回false + * @throws MessagingException + * @throws IOException + */ + public static boolean isContainAttachment(Part part) throws MessagingException, IOException { + boolean flag = false; + if (part.isMimeType("multipart/*")) { + MimeMultipart multipart = (MimeMultipart) part.getContent(); + int partCount = multipart.getCount(); + for (int i = 0; i < partCount; i++) { + BodyPart bodyPart = multipart.getBodyPart(i); + String disp = bodyPart.getDisposition(); + if (disp != null && (disp.equalsIgnoreCase(Part.ATTACHMENT) || disp.equalsIgnoreCase(Part.INLINE))) { + flag = true; + } else if (bodyPart.isMimeType("multipart/*")) { + flag = isContainAttachment(bodyPart); + } else { + String contentType = bodyPart.getContentType(); + if (contentType.indexOf("application") != -1) { + flag = true; + } + + if (contentType.indexOf("name") != -1) { + flag = true; + } + } + + if (flag) break; + } + } else if (part.isMimeType("message/rfc822")) { + flag = isContainAttachment((Part) part.getContent()); + } + return flag; + } + + /** + * 判断邮件是否已读 + * + * @param msg 邮件内容 + * @return 如果邮件已读返回true, 否则返回false + * @throws MessagingException + */ + public static boolean isSeen(MimeMessage msg) throws MessagingException { + return msg.getFlags().contains(Flags.Flag.SEEN); + } + + /** + * 判断邮件是否需要阅读回执 + * + * @param msg 邮件内容 + * @return 需要回执返回true, 否则返回false + * @throws MessagingException + */ + public static boolean isReplySign(MimeMessage msg) throws MessagingException { + boolean replySign = false; + String[] headers = msg.getHeader("Disposition-Notification-To"); + if (headers != null) + replySign = true; + return replySign; + } + + /** + * 获得邮件的优先级 + * + * @param msg 邮件内容 + * @return 1(High):紧急 3:普通(Normal) 5:低(Low) + * @throws MessagingException + */ + public static String getPriority(MimeMessage msg) throws MessagingException { + String priority = "普通"; + String[] headers = msg.getHeader("X-Priority"); + if (headers != null) { + String headerPriority = headers[0]; + if (headerPriority.indexOf("1") != -1 || headerPriority.indexOf("High") != -1) + priority = "紧急"; + else if (headerPriority.indexOf("5") != -1 || headerPriority.indexOf("Low") != -1) + priority = "低"; + else + priority = "普通"; + } + return priority; + } + + /** + * 获得邮件文本内容 + * + * @param part 邮件体 + * @param content 存储邮件文本内容的字符串 + * @throws MessagingException + * @throws IOException + */ + public static void getMailTextContent(Part part, StringBuffer content) throws MessagingException, IOException { + //如果是文本类型的附件,通过getContent方法可以取到文本内容,但这不是我们需要的结果,所以在这里要做判断 + boolean isContainTextAttach = part.getContentType().indexOf("name") > 0; + if (part.isMimeType("text/*") && !isContainTextAttach) { + content.append(part.getContent().toString()); + } else if (part.isMimeType("message/rfc822")) { + getMailTextContent((Part) part.getContent(), content); + } 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); + getMailTextContent(bodyPart, content); + } + } + } + + /** + * 保存附件 + * + * @param part 邮件中多个组合体中的其中一个组合体 + * @param destDir 附件保存目录 + * @throws UnsupportedEncodingException + * @throws MessagingException + * @throws FileNotFoundException + * @throws IOException + */ + public static void saveAttachment(Part part, String destDir) throws UnsupportedEncodingException, MessagingException, + FileNotFoundException, IOException { + 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 disp = bodyPart.getDisposition(); + if (disp != null && (disp.equalsIgnoreCase(Part.ATTACHMENT) || disp.equalsIgnoreCase(Part.INLINE))) { + InputStream is = bodyPart.getInputStream(); + saveFile(is, destDir, decodeText(bodyPart.getFileName())); + } else if (bodyPart.isMimeType("multipart/*")) { + saveAttachment(bodyPart, destDir); + } else { + String contentType = bodyPart.getContentType(); + if (contentType.indexOf("name") != -1 || contentType.indexOf("application") != -1) { + saveFile(bodyPart.getInputStream(), destDir, decodeText(bodyPart.getFileName())); + } + } + } + } else if (part.isMimeType("message/rfc822")) { + saveAttachment((Part) part.getContent(), destDir); + } + } + + /** + * 读取输入流中的数据保存至指定目录 + * + * @param is 输入流 + * @param fileName 文件名 + * @param destDir 文件存储目录 + * @throws FileNotFoundException + * @throws IOException + */ + private static void saveFile(InputStream is, String destDir, String fileName) + throws FileNotFoundException, IOException { + BufferedInputStream bis = new BufferedInputStream(is); + BufferedOutputStream bos = new BufferedOutputStream( + new FileOutputStream(new File(destDir + fileName))); + int len = -1; + while ((len = bis.read()) != -1) { + bos.write(len); + bos.flush(); + } + bos.close(); + bis.close(); + } + + /** + * 文本解码 + * + * @param encodeText 解码MimeUtility.encodeText(String text)方法编码后的文本 + * @return 解码后的文本 + * @throws UnsupportedEncodingException + */ + public static String decodeText(String encodeText) throws UnsupportedEncodingException { + if (encodeText == null || "".equals(encodeText)) { + return ""; + } else { + return MimeUtility.decodeText(encodeText); + } + } +}