对象中不单纯有参数,还有执行的方法,偏向富血
使用该包有几个好处:
1. 简易获取邮箱Session
2. 只要获取到邮件,初始化 MailMessage 后,可通过调用单一方法从而获取 发件人、收件人、抄送人、主题、内容、内容中的图片、附件等
pom文件增加依赖:
<!-- lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.16</version>
<scope>provided</scope>
</dependency>
<!-- javamail -->
<dependency>
<groupId>com.sun.mail</groupId>
<artifactId>javax.mail</artifactId>
<version>1.6.1</version>
</dependency>
<!-- guava -->
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>25.1-jre</version>
</dependency>
<!-- html 解析 -->
<dependency>
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
<version>1.11.3</version>
</dependency>
<!-- log4j2 -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.11.0</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-slf4j-impl</artifactId>
<version>2.11.0</version>
</dependency>
日志文件log4j2.xml
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="INFO">
<Appenders>
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/>
</Console>
</Appenders>
<Loggers>
<Root level="INFO">
<AppenderRef ref="Console"/>
</Root>
</Loggers>
</Configuration>
包结构为:
---com
|---test
|---build
|---common
|---enums
|---domain
|---pojo
JavaMail 会话创建类:
package com.test.build;
import com.test.common.enums.MailProtocol;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.mail.Authenticator;
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import java.util.Properties;
/**
* 仿照 Camel MailConfiguration
* https://www.cnblogs.com/15ho/p/5907174.html
* https://javaee.github.io/javamail/docs/api/com/sun/mail/imap/package-summary.html
*
* IMAPBuilder.sessionBuilder(MailProtocol.IMAPS)
* .host("imap.exmail.qq.com")
* .username("xxx@qq.com")
* .password("你猜")
* .connectionTimeout(12345)
* .build();
*
* SearchTerm 试了 YoungerTerm OlderTerm SentDateTerm ,前两者服务器不支持,后者支持但其实查询无效
* @author chenyunan 2018/6/15 9:16
*/
public class IMAPBuilder {
private static final Logger logger = LoggerFactory.getLogger(IMAPBuilder.class);
public static SessionBuilder sessionBuilder() {
return new SessionBuilder();
}
public static SessionBuilder sessionBuilder(MailProtocol mailProtocol) {
return new SessionBuilder().mailProtocol(mailProtocol);
}
/**
* 邮件Session构造器
*/
public static class SessionBuilder {
private MailProtocol mailProtocol;
private int connectionTimeout = 0; //milliseconds default infinite
private String host;
private int port; // 默认0
private int fetchSize = 4; // 每次附件获取的Buffer大小,单位:mb
private String username;
private String password;
private boolean debugMode = false;
public SessionBuilder mailProtocol(MailProtocol mailProtocol) {
this.mailProtocol = mailProtocol;
return this;
}
public SessionBuilder host(String host) {
this.host = host;
return this;
}
/**
* 不填默认为0
* <p/>
* -1 使用系统默认
* 0 使用硬编码自动适配默认
*/
public SessionBuilder port(int port) {
this.port = port;
return this;
}
/**
* 每次附件获取的Buffer大小,单位:mb
*/
public SessionBuilder fetchSize(int fetchSize) {
this.fetchSize = fetchSize;
return this;
}
/**
* 获取连接的超时时间
*/
public SessionBuilder connectionTimeout(int connectionTimeout) {
this.connectionTimeout = connectionTimeout;
return this;
}
/**
* 邮箱
*/
public SessionBuilder username(String username) {
this.username = username;
return this;
}
/**
* 邮箱密码
*/
public SessionBuilder password(String password) {
this.password = password;
return this;
}
/**
* 创建会话
*/
public Session build() {
if(mailProtocol == null) {
throw new IllegalArgumentException("未传递MailProtocol");
}
Session session = Session.getDefaultInstance(createJavaMailProperties(), new DefaultAuthenticator(username, password));
session.setDebug(debugMode);
return session;
}
/**
* 无需写入ssl参数,只要把协议 imaps 写入即可
*/
private Properties createJavaMailProperties() {
// clone the system properties and set the java mail properties
Properties properties = (Properties)System.getProperties().clone();
if(connectionTimeout != 0) {
properties.put("mail." + mailProtocol.getProtocol() + ".connectiontimeout", connectionTimeout);
properties.put("mail." + mailProtocol.getProtocol() + ".timeout", connectionTimeout);
}
properties.put("mail." + mailProtocol.getProtocol() + ".host", host);
if(port == 0) {
port = mailProtocol.getPort();
}
properties.put("mail." + mailProtocol.getProtocol() + ".port", "" + port);
if (username != null) {
properties.put("mail." + mailProtocol.getProtocol() + ".user", username);
properties.put("mail.user", username);
properties.put("mail." + mailProtocol.getProtocol() + ".auth", "true");
} else {
properties.put("mail." + mailProtocol.getProtocol() + ".auth", "false");
}
properties.put("mail.transport.protocol", mailProtocol.getProtocol());
properties.put("mail.store.protocol", mailProtocol.getProtocol());
properties.put("mail.host", host);
properties.put("mail." + mailProtocol.getProtocol() + ".fetchsize", fetchSize * 1024 * 1000);
if (debugMode) {
// add more debug for the SSL communication as well
properties.put("javax.net.debug", "all");
}
return properties;
}
}
/**
* Mail {@link Authenticator} that supplies username and password
*/
public static class DefaultAuthenticator extends Authenticator {
private final String username;
private final String password;
public DefaultAuthenticator(String username, String password) {
this.password = password;
this.username = username;
}
/**
* Returns an authenticator object for use in sessions
*/
public PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(username, password);
}
}
}
实际邮件对象与处理类(领域模型):
package com.test.domain;
import com.google.common.collect.HashBasedTable;
import com.google.common.collect.Table;
import com.test.common.enums.FileType;
import com.test.pojo.FileFullPathType;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.mail.*;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeUtility;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
/**
* 参考:https://blog.csdn.net/caoyishuai/article/details/7870418
*
* 根据业务获取指定参数
* <p/>
* Multipart multipart = (Multipart) imapMessage.getContent();
* multipart.getBodyPart(index);
* <p/>
* part.isMimeType(MimeType)
* <p/>
* 内容,媒体类型分为下列几种:
* 1、text/plain:只包含文本,不包含图片等
* 2、text/html:包含完整html
* 3、multipart/*:关联类型,有子类型
* 4、message/rfc822:电子邮件标准格式,各种参数:https://baike.baidu.com/item/RFC%20822/1468155
* 5、其他:文件、流、图片等
* <p/>
* 附件,媒体类型分为下列几种:
* 1、multipart/*:关联类型,有子类型
* 2、APPLICATION/OCTET-STREAM:流,通常是附件
* 3、IMAGE/JPEG:图片,正常是与text/html内中通过Content-ID关联
* <p/>
* 关闭流不在本类
* @author chenyunan 2018/6/15 11:55
*/
public class MailMessage {
/**
* 初始化Mail对象
*/
public static MailMessage init(Message message) {
return new MailMessage().message(message);
}
private Message message;
private String subject;
private String from;
private String fromPersonal;
private String fromMail;
private String[] tos;
private Map<String, String[]> toPersonalMails = new HashMap<>();
private String[] ccs;
private Map<String, String[]> ccPersonalMails = new HashMap<>();
private String body;
/**
* 替换过src的body
*/
private String replaceBody;
private String[] attachments;
// MAIL-UUID fileName inputstream
private Table<String, String, InputStream> srcAttachmentStream;
// MAIL-UUID fileFullPath
private Map<String, String> contentIdFullPath;
private boolean have2Close = false;
private MailMessage message(Message message) {
this.message = message;
return this;
}
/**
* 执行完附件获取流,此时统一关闭或Folder关闭时统一关闭
*/
public boolean isHave2Close() {
return have2Close;
}
/**
* 做 content-type = text/html 格式的src替换 <br>
* 获取 邮件中的:
* <br>
* row:邮件的UUID ,默认填充 文件名 或 邮件的Content-ID
* <br>
* column:文件名
* <br>
* value:流,如果不使用需要需要关闭
*/
public Table<String, String, InputStream> srcAttachmentStream() throws IOException, MessagingException {
attachments();
return srcAttachmentStream;
}
/**
*
*/
@Deprecated
public Map<String, String> contentIdFullPath(String prefixFilePath) throws IOException, MessagingException {
if(contentIdFullPath == null) {
srcAttachmentStream();
contentIdFullPath = new HashMap<>();
// tODO
}
return contentIdFullPath;
}
/**
* 附件名称
*/
public String[] attachments() throws IOException, MessagingException {
if(attachments == null) {
have2Close = true;
srcAttachmentStream = HashBasedTable.create();
Object content = message.getContent();
if(content == null) {
attachments = new String[0];
} else if(content instanceof Multipart) {
multiPartAttachments((Multipart) content);
Set<String> fileNames = srcAttachmentStream.columnKeySet();
attachments = new String[fileNames.size()];
fileNames.toArray(attachments);
} else {
attachments = new String[0];
}
}
return attachments;
}
/**
* 嵌套类型
* MIMETYPE=multipart/* 的对象,为数组,内部有多个嵌套类型
*/
private void multiPartAttachments(Multipart multipart) throws MessagingException, IOException {
for(int i=0, count=multipart.getCount(); i < count; i++) {
relativeAttachments(multipart.getBodyPart(i));
}
}
/**
* 嵌套类型下的类型处理
* MIMETYPE=可能为multipart/*(嵌套类型), message/rfc822(邮件类型), application/*(应用,实际附件)
*/
private void relativeAttachments(Part part) throws MessagingException, IOException {
if(part.isMimeType(MULTIPART_ALL)) {
multiPartAttachments((Multipart) part.getContent());
} else if(part.isMimeType(MESSAGE_RFC822)) {
relativeAttachments((Part) part.getContent());
} else if(part.isMimeType(APPLICATION_ALL)) {
gatherAttachments(part);
} else {
logger.info("其他类型[{}]", part.getContentType());
gatherAttachments(part);
}
}
private static final Logger logger = LoggerFactory.getLogger(MailMessage.class);
/**
* 应用类型,附件实际可能保存的位置
* 提取附件,application/* 是附件,其他可能是插入文本的照片
*/
private void gatherAttachments(Part part) throws MessagingException, IOException {
String disposition = part.getDisposition();
if(disposition != null
&& (disposition.equals(Part.ATTACHMENT) || disposition.equals(Part.INLINE))) {
extractAttachment((BodyPart) part);
} else if(part.isMimeType(MULTIPART_ALL)) {
multiPartAttachments((Multipart) part.getContent());
} else {
logger.info("默认类型是啥{}", part.getContentType());
extractAttachment((BodyPart) part);
}
}
/**
* 提取附件
*/
private void extractAttachment(BodyPart mpart) throws IOException, MessagingException {
String fileName = mpart.getFileName();
if (checkFileName(fileName)) {
fileName = MimeUtility.decodeText(fileName);
String id;
if(mpart.getHeader(CONTENT_ID) != null && mpart.getHeader(CONTENT_ID).length > 0) {
id = mpart.getHeader(CONTENT_ID)[0]
.replace(LEFT_ANGLE_BUCKET, BLANK).replace(RIGHT_ANGLE_BUCKET, BLANK);
} else {
id = fileName;
}
srcAttachmentStream.put(id, fileName, mpart.getInputStream());
}
}
private static final String CONTENT_ID = "Content-ID";
private static final String LEFT_ANGLE_BUCKET = "<";
private static final String RIGHT_ANGLE_BUCKET = ">";
private static final String BLANK = "";
/**
* 是不是可以解析的文件名
*/
private static boolean checkFileName(String fileName) {
return fileName != null
&& (fileName.toLowerCase().indexOf("gb2312") != -1
|| fileName.toLowerCase().indexOf("gb18030") != -1
|| fileName.toLowerCase().indexOf("gbk") != -1
|| fileName.toLowerCase().indexOf("utf-8") != -1);
}
/**
* 内容,媒体类型=text/html,text/plain不获取
*/
public String body() throws MessagingException, IOException {
if(body == null) {
Object content = message.getContent();
if(content == null) {
body = "";
} else if(content instanceof Multipart) {
Multipart multipart = (Multipart) content;
StringBuilder htmlBuilder = new StringBuilder();
for(int i=0, count = multipart.getCount(); i < count; i++) {
multipartContent(multipart.getBodyPart(i), htmlBuilder);
}
body = htmlBuilder.toString().replaceAll("\\[\\r|\\r\\n|\\n\\]", "");
} else if(content instanceof String) {
body = ((String) content).replaceAll("\\[\\r|\\r\\n|\\n\\]", "");
}
// warning 这里是为了替换html文本中的编码方式,如果还是要保留GB2312把下边两段去掉
if(body != null) {
body.replace("GB2312", "UTF-8");
body.replace("gb2312", "UTF-8");
}
}
return body;
}
/**
* 将内容中的src替换
* <p/>
* 原始:src="cid:xxxxxxx"
* 替换:文件路径,如:src="/abc/abc.jpg"
*/
public String replaceBody(Map<String, FileFullPathType> contentIdFileFullPath) throws IOException, MessagingException {
if(replaceBody == null) {
replaceImgSrc(contentIdFileFullPath);
}
return replaceBody;
}
/**
* 替换照片中的文件地址
*/
private void replaceImgSrc(Map<String, FileFullPathType> contentIdFileFullPath) throws IOException, MessagingException {
body();
if(contentIdFileFullPath != null && !contentIdFileFullPath.isEmpty()) {
Document document = Jsoup.parse(body);
document.outputSettings().prettyPrint(false);
Elements elements = document.getElementsByTag("img");
if(elements != null && elements.size() != 0) {
int size = elements.size();
for (int i = 0; i < size; i++) {
Element element = elements.get(i);
String cid = element.attr("src").replace("cid:", "");
if (contentIdFileFullPath.containsKey(cid)) {
FileFullPathType fileFullPathType = contentIdFileFullPath.get(cid);
fileFullPathType.setFileType(FileType.BODY_IMAGE);
element.attr("src", fileFullPathType.getFileFullPath());
}
}
replaceBody = document.outerHtml();
} else {
replaceBody = body;
}
} else {
replaceBody = body;
}
}
private static final String TEXT_PLAIN = "text/plain";
private static final String TEXT_HTML = "text/html";
private static final String MULTIPART_ALL = "multipart/*";
private static final String MESSAGE_RFC822 = "message/rfc822";
private static final String APPLICATION_ALL = "application/*";
private void multipartContent(Part part, StringBuilder stringBuilder) throws MessagingException, IOException {
String contentType = part.getContentType();
int nameIndex = contentType.indexOf("name");
boolean containName = false;
if (nameIndex != -1) {
containName = true;
}
if (part.isMimeType(TEXT_PLAIN) && !containName) {
// stringBuilder.append((String) part.getContent());
// skip 根据业务,暂时只保存html
} else if (part.isMimeType(TEXT_HTML) && !containName) {
stringBuilder.append((String) part.getContent());
} else if (part.isMimeType(MULTIPART_ALL)) {
Multipart multipart = (Multipart) part.getContent();
for (int i = 0, counts = multipart.getCount() ; i < counts; i++) {
multipartContent(multipart.getBodyPart(i), stringBuilder);
}
} else if (part.isMimeType(MESSAGE_RFC822)) {
multipartContent((Part) part.getContent(), stringBuilder);
}
}
/**
* 抄送
*/
public String[] ccs() throws UnsupportedEncodingException, MessagingException {
if(ccs == null) {
ccs = assembleToOrCc(Message.RecipientType.CC, ccPersonalMails);
}
return ccs;
}
/**
* 接收人(to)或抄送人(cc)中的人或地址类型
* 原始:chenyunan<chenyunan@banggood.com>
* personal:chenyunan
* address:chenyunan@banggood.com
*/
public enum PersonalMail {
PERSONAL, ADDRESS;
}
/**
* 获取cc中的人或地址
*/
public String ccPersonalOrMail(String personalMail, PersonalMail type) {
switch (type) {
case PERSONAL:
return ccPersonalMails.containsKey(personalMail) ? ccPersonalMails.get(personalMail)[0] : null;
case ADDRESS:
return ccPersonalMails.containsKey(personalMail) ? ccPersonalMails.get(personalMail)[1] : null;
}
return null;
}
/**
* 获取to中的人或地址
*/
public String toPersonalOrMail(String personalMail, PersonalMail type) {
switch (type) {
case PERSONAL:
return toPersonalMails.containsKey(personalMail) ? toPersonalMails.get(personalMail)[0] : null;
case ADDRESS:
return toPersonalMails.containsKey(personalMail) ? toPersonalMails.get(personalMail)[1] : null;
}
return null;
}
/**
* 获取接收人
*/
public String[] tos() throws MessagingException, UnsupportedEncodingException {
if(tos == null) {
tos = assembleToOrCc(Message.RecipientType.TO, toPersonalMails);
}
return tos;
}
/**
* 获取相应类型(to或cc)数据
*/
private String[] assembleToOrCc(Message.RecipientType recipientType, Map<String, String[]> map) throws MessagingException, UnsupportedEncodingException {
InternetAddress address[] = (InternetAddress[]) message.getRecipients(recipientType);
if (address != null) {
StringBuilder personalMails = new StringBuilder();
String[] personalMailArgs;
for (int i = 0; i < address.length; i++) {
String personalMail = "";
String personal = address[i].getPersonal();
if(personal != null) {
personal = MimeUtility.decodeText(personal);
personalMail += personal;
}
personalMail += "<";
String email = address[i].getAddress();
if(email != null) {
email = MimeUtility.decodeText(email);
personalMail += email;
}
personalMail += ">";
if("<>".equals(personalMail)) {
continue;
} else {
personalMailArgs = new String[2];
personalMailArgs[0] = personal;
personalMailArgs[1] = email;
map.put(personalMail, personalMailArgs);
personalMails.append(personalMail);
personalMails.append(",");
}
}
return personalMails.length() == 0 ?
new String[0] : personalMails.substring(0, personalMails.length() - 1).split(",");// size - 1 - ",".length
} else {
return new String[0];
}
}
/**
* 主题,标题
*/
public String subject() throws MessagingException, UnsupportedEncodingException {
if(subject == null) {
subject = MimeUtility.decodeText(message.getSubject());
}
return subject;
}
/**
* 发件人
* 如:chenyunan<chenyunan@banggood.com>
*/
public String from() throws MessagingException {
if(from == null) {
assembleFrom();
}
return from;
}
/**
* 发件人,别名
* 如:chenyunan
*/
public String fromPersonal() throws MessagingException {
if(fromPersonal == null) {
assembleFrom();
}
return fromPersonal;
}
/**
* 发件人,邮箱
* 如:chenyunan@banggood.com
*/
public String fromMail() throws MessagingException {
if(fromMail == null) {
assembleFrom();
}
return fromMail;
}
private void assembleFrom() throws MessagingException {
InternetAddress address[] = (InternetAddress[]) message.getFrom();
fromMail = address[0].getAddress();
if(fromMail == null) {
fromMail = "";
}
this.fromPersonal = address[0].getPersonal();
if (fromPersonal == null) {
fromPersonal = "";
}
from = fromPersonal + "<" + fromMail + ">";
}
}
附件处理类:
package com.test.pojo;
import com.test.common.enums.FileType;
import lombok.Data;
/**
* @author chenyunan 2018/7/11 10:41
*/
@Data
public class FileFullPathType {
private String fileFullPath;
private FileType fileType;
}
邮箱连接协议端口枚举:
package com.test.common.enums;
import lombok.Getter;
/**
* 邮箱的协议 端口
* @author chenyunan 2018/6/15 10:22
*/
@Getter
public enum MailProtocol {
IMAP("imap", 143),
STMP("stmp", 25),
IMAPS("imaps", 993),
STMPS("stmps", 465);
private String protocol;
private int port;
MailProtocol(String protocol, int port) {
this.protocol = protocol;
this.port = port;
}
}
文件流类型(附件或文本图片):
package com.test.common.enums;
/**
* @author chenyunan 2018/7/11 10:42
*/
public enum FileType {
// 附件
ATTACHMENT,
// 邮件内容中的图片
BODY_IMAGE;
}
启动类,测试:
package com.test;
import com.sun.mail.imap.IMAPStore;
import com.test.build.IMAPBuilder;
import com.test.common.enums.FileType;
import com.test.common.enums.MailProtocol;
import com.test.domain.MailMessage;
import com.test.pojo.FileFullPathType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.mail.*;
import java.io.*;
import java.util.HashMap;
import java.util.Map;
/**
* @author chenyunan 2018/7/11 10:28
*/
public class App {
private static final Logger logger = LoggerFactory.getLogger(App.class);
private static final String PREFIX_PATH = "d:/tmp/";
public static void main(String[] args) throws MessagingException, IOException {
Session session = IMAPBuilder.sessionBuilder(MailProtocol.IMAPS)
.connectionTimeout(5000)
.host("imap.exmail.qq.com")
.username("xxx@qq.com")
.fetchSize(4)
.password("123123")
.build();
MailMessage mailMessage = null;
try (Store store = session.getStore()) {
if (store instanceof IMAPStore) {
IMAPStore imapStore = (IMAPStore) store;
imapStore.connect();
try (Folder folder = imapStore.getFolder("INBOX")){
if (folder.exists()) {
folder.open(Folder.READ_ONLY);
// 邮箱邮件总数
int count = folder.getMessageCount();
// 邮件指针从1开始
// 获取最新一封邮件
Message message = folder.getMessage(count);
logger.info("------邮件总数:{}", count);
logger.info("------邮件标题:{}", message.getSubject());
mailMessage = MailMessage.init(message);
String from = mailMessage.from();
String[] tos = mailMessage.tos();
String[] ccs = mailMessage.ccs();
logger.info("------发件人:{}", from);
logger.info("------发件人别名:{}", mailMessage.fromPersonal());
logger.info("------发件人邮箱地址:{}", mailMessage.fromMail());
logger.info("------标题:{}", mailMessage.subject());
if(tos != null && tos.length != 0) {
logger.info("------收件人:{}", tos);
logger.info("------第一个收件人别名:{}", mailMessage.toPersonalOrMail(tos[0], MailMessage.PersonalMail.PERSONAL));
logger.info("------第一个收件人邮箱地址:{}", mailMessage.toPersonalOrMail(tos[0], MailMessage.PersonalMail.ADDRESS));
}
if(ccs != null && ccs.length != 0) {
logger.info("------抄送人:{}", ccs);
logger.info("------第一个抄送人别名:{}", mailMessage.ccPersonalOrMail(ccs[0], MailMessage.PersonalMail.PERSONAL));
logger.info("------第一个抄送人邮箱地址:{}", mailMessage.ccPersonalOrMail(ccs[0], MailMessage.PersonalMail.ADDRESS));
}
logger.info("------类型为:text/html 的正文内容:{}", mailMessage.body());
logger.info("------附件:{}", mailMessage.attachments());
logger.info("------UUID-FILE-STREAM:{}", mailMessage.srcAttachmentStream());
if(mailMessage.srcAttachmentStream() != null) {
Map<String, FileFullPathType> contentIdFileFullPath = new HashMap<>();
for(String contentId : mailMessage.srcAttachmentStream().rowKeySet()) {
FileFullPathType fileFullPathType = new FileFullPathType();
mailMessage.srcAttachmentStream().row(contentId).forEach((key, value) -> fileFullPathType.setFileFullPath(PREFIX_PATH + key));
fileFullPathType.setFileType(FileType.ATTACHMENT);
contentIdFileFullPath.put(contentId, fileFullPathType);
// 保存文件
Map<String, InputStream> fileNameInputstream = mailMessage.srcAttachmentStream().row(contentId);
for(String fileName : fileNameInputstream.keySet()) {
try(InputStream inputStream = fileNameInputstream.get(fileName)) {
File file = new File(PREFIX_PATH + fileName);
if(!file.exists()) {
try {
file.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
}
byte []bytes = new byte[65536];
try (OutputStream outputStream = new FileOutputStream(file)){
int index;
while((index = inputStream.read(bytes)) != -1) {
outputStream.write(bytes, 0, index);
}
} catch (IOException e) {
logger.error("", e);
} finally {
logger.info("------文件保存,地址:{}", PREFIX_PATH + fileName);
}
}
}
}
// 原始:src="cid:078E8559@BCD85E73.8172455B.jpg"
// 替换后:src="d:/tmp/078E8559@BCD85E73.8172455B.jpg"
logger.info("------替换src标签内容之后的内容:{}", mailMessage.replaceBody(contentIdFileFullPath));
}
}
}
}
} catch (NoSuchProviderException e) {
e.printStackTrace();
} catch (MessagingException e) {
e.printStackTrace();
}
}
}
输出结果:
16:45:07.689 [main] INFO com.test.App - ------邮件总数:1431
16:45:08.048 [main] INFO com.test.App - ------邮件标题:这是一封测试邮件
16:45:08.050 [main] INFO com.test.App - ------发件人:chenyunan@banggood.com<chenyunan@banggood.com>
16:45:08.050 [main] INFO com.test.App - ------发件人别名:chenyunan@banggood.com
16:45:08.050 [main] INFO com.test.App - ------发件人邮箱地址:chenyunan@banggood.com
16:45:08.050 [main] INFO com.test.App - ------标题:这是一封测试邮件
16:45:08.050 [main] INFO com.test.App - ------收件人:chenyunan<chenyunan@banggood.com>
16:45:08.051 [main] INFO com.test.App - ------第一个收件人别名:chenyunan
16:45:08.051 [main] INFO com.test.App - ------第一个收件人邮箱地址:chenyunan@banggood.com
16:45:08.051 [main] INFO com.test.App - ------抄送人:chenyunan<chenyunan@banggood.com>
16:45:08.051 [main] INFO com.test.App - ------第一个抄送人别名:chenyunan
16:45:08.051 [main] INFO com.test.App - ------第一个抄送人邮箱地址:chenyunan@banggood.com
16:45:08.648 [main] INFO com.test.App - ------类型为:text/html 的正文内容:<html><head><meta http-equiv="content-type" content="text/html; charset=GB2312"><style>body { line-height: 1.5; }blockquote { margin-top: 0px; margin-bottom: 0px; margin-left: 0.5em; }div.foxdiv20180711160907014546 { }body { font-size: 10.5pt; font-family: 微软雅黑; color: rgb(0, 0, 0); line-height: 1.5; }</style></head><body>
<div><span></span><br></div><blockquote style="margin-top: 0px; margin-bottom: 0px; margin-left: 0.5em;"><div><div class="FoxDiv20180711160907014546"><blockquote style="margin-top: 0px; margin-bottom: 0px; margin-left: 0.5em;"><div><div class="FoxDiv20180711160207551816">
<div><span></span>里边的内容是这些<img src="cid:_Foxmail.1@c2779f19-e831-7609-db30-d579df91f1cb" border="0" style="font-size: 10.5pt; line-height: 1.5; background-color: window;"><img src="cid:_Foxmail.1@093484e4-2c8c-7869-d22c-323baeffcda2" border="0" style="font-size: 10.5pt; line-height: 1.5; background-color: window;"></div>
<div><br></div><hr style="width: 210px; height: 1px;" color="#b5c4df" size="1" align="left">
<div><span><div style="MARGIN: 10px; FONT-FAMILY: verdana; FONT-SIZE: 10pt"><div>chenyunan@banggood.com</div></div></span></div>
</div></div></blockquote>
</div></div></blockquote>
</body></html>
16:45:09.455 [main] INFO com.test.App - ------附件:InsertPic_(07-11(07-11-16-09-0
16:45:09.462 [main] INFO com.test.App - ------UUID-FILE-STREAM:{_Foxmail.1@c2779f19-e831-7609-db30-d579df91f1cb={InsertPic_(07-11(07-11-16-09-0=com.sun.mail.util.BASE64DecoderStream@3098cf3b}, _Foxmail.1@093484e4-2c8c-7869-d22c-323baeffcda2={Catch(07-11-16-0(07-11-16-09-0=com.sun.mail.util.BASE64DecoderStream@610f7aa}, xxx.xls={xxx.xls=com.sun.mail.util.BASE64DecoderStream@6a03bcb1}}
16:45:09.770 [main] INFO com.test.App - ------文件保存,地址:d:/tmp/InsertPic_(07-11(07-11-16-09-0
16:45:10.062 [main] INFO com.test.App - ------文件保存,地址:d:/tmp/Catch(07-11-16-0(07-11-16-09-0
16:45:10.342 [main] INFO com.test.App - ------文件保存,地址:d:/tmp/xxx.xls
16:45:10.392 [main] INFO com.test.App - ------替换src标签内容之后的内容:<html><head><meta http-equiv="content-type" content="text/html; charset=GB2312"><style>body { line-height: 1.5; }blockquote { margin-top: 0px; margin-bottom: 0px; margin-left: 0.5em; }div.foxdiv20180711160907014546 { }body { font-size: 10.5pt; font-family: 微软雅黑; color: rgb(0, 0, 0); line-height: 1.5; }</style></head><body>
<div><span></span><br></div><blockquote style="margin-top: 0px; margin-bottom: 0px; margin-left: 0.5em;"><div><div class="FoxDiv20180711160907014546"><blockquote style="margin-top: 0px; margin-bottom: 0px; margin-left: 0.5em;"><div><div class="FoxDiv20180711160207551816">
<div><span></span>里边的内容是这些<img src="d:/tmp/InsertPic_(07-11(07-11-16-09-0" border="0" style="font-size: 10.5pt; line-height: 1.5; background-color: window;"><img src="d:/tmp/Catch(07-11-16-0(07-11-16-09-0" border="0" style="font-size: 10.5pt; line-height: 1.5; background-color: window;"></div>
<div><br></div><hr style="width: 210px; height: 1px;" color="#b5c4df" size="1" align="left">
<div><span><div style="MARGIN: 10px; FONT-FAMILY: verdana; FONT-SIZE: 10pt"><div>chenyunan@banggood.com</div></div></span></div>
</div></div></blockquote>
</div></div></blockquote>
</body></html>