| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544 |
- package jnpf.base.util;
- import jnpf.base.model.MailAccount;
- import jnpf.base.model.MailFile;
- import jnpf.config.ConfigValueUtil;
- import jnpf.base.entity.EmailReceiveEntity;
- import jnpf.constant.FileTypeConstant;
- import jnpf.util.*;
- import lombok.Cleanup;
- import lombok.extern.slf4j.Slf4j;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.stereotype.Component;
- import jakarta.mail.*;
- import jakarta.mail.internet.InternetAddress;
- import jakarta.mail.internet.MimeMessage;
- import jakarta.mail.internet.MimeMultipart;
- import jakarta.mail.internet.MimeUtility;
- import java.io.*;
- import java.text.SimpleDateFormat;
- import java.util.*;
- /**
- *
- * @author JNPF开发平台组
- * @version V3.1.0
- * @copyright 引迈信息技术有限公司
- * @date 2021/3/12 15:31
- */
- @Slf4j
- @Component
- public class Pop3Util {
- @Autowired
- private ConfigValueUtil configValueUtil;
- /**
- * 邮箱验证
- *
- * @param mailAccount
- * @return
- */
- public String checkConnected(MailAccount mailAccount) {
- try {
- Properties props = getProperties(mailAccount.getSsl());
- Session session = getSession(props);
- @Cleanup Store store = getStore(session, mailAccount);
- return "true";
- } catch (Exception e) {
- log.error(e.getMessage());
- return e.getMessage();
- }
- }
- /**
- * 接收邮件
- */
- public Map<String, Object> popMail(MailAccount mailAccount) {
- List<EmailReceiveEntity> entity = new ArrayList<>();
- Map<String, Object> map = new HashMap<>(16);
- try {
- Properties props = getProperties(mailAccount.getSsl());
- Session session = getSession(props);
- @Cleanup Store store = getStore(session, mailAccount);
- @Cleanup Folder folder = getFolder(store);
- int receiveCount = folder.getMessageCount();
- Message[] messages = folder.getMessages();
- entity = parseMessage(messages);
- map.put("receiveCount", receiveCount);
- map.put("mailList", entity);
- return map;
- } catch (Exception e) {
- log.error(e.getMessage());
- }
- return map;
- }
- /**
- * 删除邮件
- *
- * @param mailAccount
- * @param mid
- */
- public void deleteMessage(MailAccount mailAccount, String mid) {
- try {
- Properties props = getProperties(false);
- Session session = getSession(props);
- @Cleanup Store store = getStore(session, mailAccount);
- @Cleanup Folder folder = getFolder(store);
- Message[] messages = folder.getMessages();
- deleteMessage(messages, mid);
- } catch (Exception e) {
- log.error(e.getMessage());
- }
- }
- /**
- * 获取Properties
- *
- * @param ssl
- */
- private Properties getProperties(boolean ssl) {
- Properties props = new Properties();
- props.setProperty("mail.store.protocol", "pop3");
- props.setProperty("mail.pop3.auth", "true");
- // 设置连接超时时间
- props.put("mail.pop3.connectiontimeout", "35000");
- // 设置读取超时时间
- props.put("mail.pop3.timeout", "10000");
- // 设置写入超时时间
- props.put("mail.pop3.writetimeout", "10000");
- if (ssl) {
- props.put("mail.pop3.ssl.enable", "true");
- props.put("mail.pop3.socketFactory.fallback", "false");
- props.setProperty( "mail.pop3.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
- }
- return props;
- }
- /**
- * 获取Session
- *
- * @param props
- */
- private Session getSession(Properties props) {
- Session session = Session.getInstance(props);
- session.setDebug(true);
- return session;
- }
- /**
- * 获取Store
- */
- private Store getStore(Session session, MailAccount mailAccount) throws Exception {
- Store store = session.getStore();
- store.connect(mailAccount.getPop3Host(), mailAccount.getPop3Port(), mailAccount.getAccount(), mailAccount.getPassword());
- return store;
- }
- /**
- * 获取Folder
- */
- private Folder getFolder(Store store) throws Exception {
- Folder folder = store.getFolder("INBOX");
- folder.open(Folder.READ_ONLY);
- return folder;
- }
- /**
- * 解析邮件
- *
- * @param messages 要解析的邮件列表
- */
- private List<EmailReceiveEntity> parseMessage(Message... messages) throws MessagingException {
- List<EmailReceiveEntity> receiveEntity = new ArrayList<>();
- if (messages == null || messages.length < 1) {
- throw new MessagingException("未找到要解析的邮件!");
- }
- List<MailFile> mailFiles = new ArrayList<>();
- String mailfiles = "";
- for (int i = 0, count = messages.length; i < count; i++) {
- try {
- MimeMessage msg = (MimeMessage) messages[i];
- mailfiles = null;
- boolean isContainerAttachment = isContainAttachment(msg);
- if (isContainerAttachment) {
- //保存附件
- mailFiles = saveAttachment(msg, FileUploadUtils.getLocalBasePath() + FilePathUtil.getFilePath(FileTypeConstant.MAIL));
- mailfiles = JsonUtil.getObjectToString(mailFiles);
- }else {
- mailfiles="[]";
- }
- StringBuilder content = new StringBuilder(30);
- getMailTextContent(msg, content);
- EmailReceiveEntity entity = new EmailReceiveEntity();
- entity.setId(RandomUtil.uuId());
- entity.setMAccount(getReceiveAddress(msg, null));
- entity.setMID(getMessageId(msg));
- if(getFrom(msg)==null){
- entity.setSender("00000");
- entity.setSenderName("匿名");
- }else {
- entity.setSender(getFrom(msg).split("_")[0]);
- entity.setSenderName(getFrom(msg).split("_")[1]);
- }
- entity.setSubject(getSubject(msg));
- entity.setBodyText(content.toString());
- entity.setAttachment(mailfiles);
- entity.setFdate(msg.getSentDate());
- entity.setIsRead(0);
- receiveEntity.add(entity);
- }catch (Exception e){
- log.error(e.getMessage());
- }
- }
- return receiveEntity;
- }
- /**
- * 解析邮件
- *
- * @param messages 要解析的邮件列表
- */
- private void deleteMessage(Message[] messages, String mid) throws MessagingException {
- if (messages == null || messages.length < 1) {
- throw new MessagingException("未找到要解析的邮件!");
- }
- for (int i = 0; i < messages.length; i++) {
- Message message = messages[i];
- MimeMessage msg = (MimeMessage) messages[i];
- if (deleteMessageId(msg, mid)) {
- message.setFlag(Flags.Flag.DELETED, true);
- }
- }
- }
- /**
- * 判断mid是否一致
- *
- * @param msg
- * @param mid
- * @return
- * @throws MessagingException
- */
- private boolean deleteMessageId(MimeMessage msg, String mid) throws MessagingException {
- String messageId = msg.getMessageID();
- messageId = messageId.replace("<", "");
- messageId = messageId.replace(">", "");
- if (messageId.equals(mid)) {
- return true;
- }
- return false;
- }
- /**
- * 获得邮件主题
- *
- * @param msg 邮件内容
- * @return 解码后的邮件主题
- */
- private String getSubject(MimeMessage msg) throws UnsupportedEncodingException, MessagingException {
- return MimeUtility.decodeText(msg.getSubject());
- }
- /**
- * 获得邮件发件人
- *
- * @param msg 邮件内容
- * @return 姓名 <Email地址>
- * @throws MessagingException
- * @throws UnsupportedEncodingException
- */
- private String getFrom(MimeMessage msg) throws MessagingException, UnsupportedEncodingException {
- String from = "";
- Address[] froms = msg.getFrom();
- InternetAddress address = (InternetAddress) froms[0];
- String person = address.getPersonal();
- if (person != null) {
- person = MimeUtility.decodeText(person) + " ";
- } else {
- person = "";
- }
- from = person + "_" + address.getAddress();
- return from;
- }
- /**
- * 获取邮件的id
- */
- private String getMessageId(MimeMessage msg) throws MessagingException {
- String messageId = msg.getMessageID();
- if (messageId == null) {
- return "";
- }
- messageId = messageId.replace("<", "");
- messageId = messageId.replace(">", "");
- return messageId;
- }
- /**
- * 根据收件人类型,获取邮件收件人、抄送和密送地址。如果收件人类型为空,则获得所有的收件人
- * <p>Message.RecipientType.TO 收件人</p>
- * <p>Message.RecipientType.CC 抄送</p>
- * <p>Message.RecipientType.BCC 密送</p>
- *
- * @param msg 邮件内容
- * @param type 收件人类型
- * @return 收件人1 <邮件地址1>, 收件人2 <邮件地址2>, ...
- * @throws MessagingException
- */
- private String getReceiveAddress(MimeMessage msg, Message.RecipientType type) throws MessagingException {
- StringBuilder receiveAddress = new StringBuilder();
- Address[] addresss = null;
- if (type == null) {
- addresss = msg.getAllRecipients();
- } else {
- addresss = msg.getRecipients(type);
- }
- if (addresss == null || addresss.length < 1) {
- return null;
- }
- 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
- */
- private 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);
- }
- /**
- * 判断邮件中是否包含附件
- *
- * @return 邮件中存在附件返回true,不存在返回false
- * @throws MessagingException
- * @throws IOException
- */
- private boolean isContainAttachment(Part part) {
- boolean flag = false;
- try {
- 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.contains("application")) {
- flag = true;
- }
- if (contentType.contains("name")) {
- flag = true;
- }
- }
- if (flag) {
- break;
- }
- }
- } else if (part.isMimeType("message/rfc822")) {
- flag = isContainAttachment((Part) part.getContent());
- }
- }catch (Exception e){
- log.error(e.getMessage());
- }
- return flag;
- }
- /**
- * 判断邮件是否已读
- *
- * @param msg 邮件内容
- * @return 如果邮件已读返回true, 否则返回false
- * @throws MessagingException
- */
- private boolean isSeen(MimeMessage msg) throws MessagingException {
- return msg.getFlags().contains(Flags.Flag.SEEN);
- }
- /**
- * 判断邮件是否需要阅读回执
- *
- * @param msg 邮件内容
- * @return 需要回执返回true, 否则返回false
- * @throws MessagingException
- */
- private 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
- */
- private 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
- */
- private void getMailTextContent(Part part, StringBuilder content) {
- try {
- boolean isContainTextAttach = part.getContentType().indexOf("name") > 0;
- if (part.isMimeType("text/html") && !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);
- }
- }
- }catch (Exception e){
- e.printStackTrace();
- }
- }
- /**
- * 保存附件
- *
- * @param part 邮件中多个组合体中的其中一个组合体
- * @param destDir 附件保存目录
- * @throws UnsupportedEncodingException
- * @throws MessagingException
- * @throws FileNotFoundException
- * @throws IOException
- */
- private List<MailFile> saveAttachment(Part part, String destDir) {
- List<MailFile> mailFiles = new ArrayList<>();
- try {
- 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))) {
- MailFile mailFile = new MailFile();
- @Cleanup InputStream is = bodyPart.getInputStream();
- //解决附件中文乱码
- String fileName=MimeUtility.decodeText(bodyPart.getFileName());
- String fileType=fileName.split("\\.")[1];
- mailFile.setFileId(RandomUtil.uuId()+"."+fileType);
- saveFile(is, destDir, decodeText(mailFile.getFileId()));
- File file = new File(destDir + decodeText(fileName));
- mailFile.setFileName(fileName);
- mailFile.setFileSize(String.valueOf(file.length()));
- mailFile.setFileState("-1");
- mailFile.setFileTime(DateUtil.getNow());
- mailFiles.add(mailFile);
- } 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()));
- File file = new File(destDir + decodeText(bodyPart.getFileName()));
- MailFile mailFile = new MailFile();
- mailFile.setFileId(RandomUtil.uuId());
- mailFile.setFileName(file.getName());
- mailFile.setFileSize(String.valueOf(file.length()));
- mailFile.setFileState("-1");
- mailFile.setFileTime(DateUtil.getNow());
- mailFiles.add(mailFile);
- }
- }
- }
- } else if (part.isMimeType("message/rfc822")) {
- saveAttachment((Part) part.getContent(), destDir);
- }
- }catch (Exception e){
- e.printStackTrace();
- }
- return mailFiles;
- }
- /**
- * 读取输入流中的数据保存至指定目录
- *
- * @param is 输入流
- * @param fileName 文件名
- * @param destDir 文件存储目录
- * @throws FileNotFoundException
- * @throws IOException
- */
- private void saveFile(InputStream is, String destDir, String fileName)
- throws FileNotFoundException, IOException {
- @Cleanup BufferedInputStream bis = new BufferedInputStream(is);
- @Cleanup FileOutputStream fileOutputStream = new FileOutputStream(new File(destDir + fileName));
- @Cleanup BufferedOutputStream bos = new BufferedOutputStream(fileOutputStream);
- int len = -1;
- while ((len = bis.read()) != -1) {
- bos.write(len);
- bos.flush();
- }
- }
- /**
- * 文本解码
- *
- * @param encodeText 解码MimeUtility.encodeText(String text)方法编码后的文本
- * @return 解码后的文本
- * @throws UnsupportedEncodingException
- */
- private String decodeText(String encodeText) throws UnsupportedEncodingException {
- if (encodeText == null || "".equals(encodeText)) {
- return "";
- } else {
- return MimeUtility.decodeText(encodeText);
- }
- }
- }
|