MailMessageInfo 邮件对象

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.StrUtil;
import lombok.Data;

import javax.mail.*;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeMessage;
import javax.mail.internet.MimeUtility;
import java.io.File;
import java.io.InputStream;
import java.nio.file.Paths;
import java.util.Date;
import java.util.Objects;
import java.util.Optional;

@Data
public class MailMessageInfo {

private MimeMessage mimeMessage;

/**
* 附件下载后的存放目录
*/
private String saveAttachPath;

/**
* 主题
*/
private String subject;

/**
* 获得邮件发送日期
*/
private Date sendDate;

/**
* 发件人
*/
private String fromPerson;

/**
* 收件人
*/
private String toPerson;

/**
* 抄送人
*/
private String ccPerson;

/**
* 密送人
*/
private String bccPerson;

/**
* Message-ID
*/
private String messageID;

/**
* 是否已读
*/
private Boolean hasRead;

/**
* 是否需要回执
*/
private Boolean needReplay;

/**
* 存放邮件内容
*/
private final StringBuffer bodyText = new StringBuffer();

public MailMessageInfo(MimeMessage mimeMessage) throws Exception {
this.mimeMessage = mimeMessage;
this.subject = Optional.ofNullable(MimeUtility.decodeText(mimeMessage.getSubject())).orElse("");
this.sendDate = mimeMessage.getSentDate();
this.fromPerson = getFrom();
this.toPerson = getMailAddress("to");
this.ccPerson = getMailAddress("cc");
this.bccPerson = getMailAddress("bcc");
this.needReplay = mimeMessage.getHeader("Disposition-Notification-To") != null;
this.messageID = mimeMessage.getMessageID();
this.hasRead = checkHasRead();
parseMailContent(mimeMessage);
}

/**
* 获得发件人的地址和姓名
*/
private String getFrom() throws Exception {
InternetAddress[] address = (InternetAddress[]) mimeMessage.getFrom();
String from = Optional.ofNullable(address[0].getAddress()).orElse("");
String personal = Optional.ofNullable(address[0].getPersonal()).orElse("");
return personal + "<" + from + ">";
}

/**
* 获得邮件的收件人,抄送,和密送的地址和姓名,根据所传递的参数的不同 "to"----收件人 "cc"---抄送人地址 "bcc"---密送人地址
*/
private String getMailAddress(String type) throws Exception {
String addtype = type.toUpperCase();
InternetAddress[] address = null;
if (Objects.equals(addtype, "TO")) {
address = (InternetAddress[]) mimeMessage.getRecipients(Message.RecipientType.TO);
} else if (Objects.equals(addtype, "CC")) {
address = (InternetAddress[]) mimeMessage.getRecipients(Message.RecipientType.CC);
} else if (Objects.equals(addtype, "BCC")) {
address = (InternetAddress[]) mimeMessage.getRecipients(Message.RecipientType.BCC);
}

StringBuilder mailaddr = new StringBuilder();
if (address != null) {
for (InternetAddress internetAddress : address) {
String email = MimeUtility.decodeText(Optional.ofNullable(internetAddress.getAddress()).orElse(""));
String personal = MimeUtility.decodeText(Optional.ofNullable(internetAddress.getPersonal()).orElse(""));
mailaddr.append(",").append(personal).append("<").append(email).append(">");
}
mailaddr = new StringBuilder(mailaddr.substring(1));
}

return mailaddr.toString();
}

/**
* 解析邮件,把得到的邮件内容保存到一个StringBuffer对象中,解析邮件 主要是根据MimeType类型的不同执行不同的操作,一步一步的解析
*/
public void parseMailContent(Part part) throws Exception {
String contentType = part.getContentType();
int nameIndex = contentType.indexOf("name");
boolean hasNameKeyword = nameIndex != -1;
if (!hasNameKeyword && (part.isMimeType("text/plain") || part.isMimeType("text/html"))) {
bodyText.append((String) part.getContent());
} else if (part.isMimeType("multipart/*")) {
Multipart multipart = (Multipart) part.getContent();
int counts = multipart.getCount();
for (int i = 0; i < counts; i++) {
parseMailContent(multipart.getBodyPart(i));
}
} else if (part.isMimeType("message/rfc822")) {
parseMailContent((Part) part.getContent());
}
}

/**
* 判断此邮件是否已读,如果未读返回返回false,反之返回true
*/
public boolean checkHasRead() throws MessagingException {
Flags flags = mimeMessage.getFlags();
Flags.Flag[] flag = flags.getSystemFlags();
for (Flags.Flag value : flag) {
if (value == Flags.Flag.SEEN) {
return true;
}
}
return false;
}

/**
* 判断此邮件是否包含附件
*/
public boolean isContainAttach(Part part) throws Exception {
boolean attachflag = false;
if (part.isMimeType("multipart/*")) {
Multipart mp = (Multipart) part.getContent();
for (int i = 0; i < mp.getCount(); i++) {
BodyPart mpart = mp.getBodyPart(i);
String disposition = mpart.getDisposition();
if (Part.ATTACHMENT.equals(disposition) || Part.INLINE.equals(disposition)) {
attachflag = true;
} else if (mpart.isMimeType("multipart/*")) {
attachflag = isContainAttach(mpart);
} else {
String contentType = part.getContentType().toLowerCase();
attachflag = StrUtil.containsAny(contentType, "application", "name");
}
}
} else if (part.isMimeType("message/rfc822")) {
attachflag = isContainAttach((Part) part.getContent());
}
return attachflag;
}

/**
* 保存附件
*/
public File saveAttachment(Part part) throws Exception {
String fileName;
if (part.isMimeType("multipart/*")) {
Multipart mp = (Multipart) part.getContent();
for (int i = 0; i < mp.getCount(); i++) {
BodyPart bodyPart = mp.getBodyPart(i);
String disposition = bodyPart.getDisposition();
if (Part.ATTACHMENT.equals(disposition) || Part.INLINE.equals(disposition)) {
fileName = MimeUtility.decodeText(bodyPart.getFileName()).replaceAll("/", "_");
return saveFile(fileName, bodyPart.getInputStream());
} else if (bodyPart.isMimeType("multipart/*")) {
return saveAttachment(bodyPart);
} else {
String bodyPartFileName = bodyPart.getFileName();
if (bodyPartFileName != null) {
bodyPartFileName = MimeUtility.decodeText(bodyPartFileName);
return saveFile(bodyPartFileName, bodyPart.getInputStream());
}
}
}
} else if (part.isMimeType("message/rfc822")) {
return saveAttachment((Part) part.getContent());
}

return null;
}

/**
* 真正的保存附件到指定目录里
*/
private File saveFile(String fileName, InputStream in) {
if (StrUtil.isBlankIfStr(fileName)) {
return null;
}
String storedir = getSaveAttachPath();
if (!FileUtil.exist(storedir)) {
storedir = System.getProperty("java.io.tmpdir");
}
File storefile = Paths.get(storedir, fileName).toFile();
try {
FileUtil.writeFromStream(in, storefile);
return storefile;
} catch (Exception e) {
throw new RuntimeException("文件保存失败!", e);
}
}

}