上一篇讲到了构建接口和各种需要用到的实体类,这一篇会讲到业务实现类和邮件解析工具类的实现。我会在每一个类前面或注释写上一些需要注意的地方。本地存储路径会保存一份邮件源码eml,还有解析出来的各种附件。
1.POP邮件拉取
POP3协议只能获取到收件箱(INBOX)文件夹里的邮件
/** * pop3协议邮箱收件类 * * @author zeemoo * @date 2019/01/18 */
public class Pop3Service implements IMailService {
/** * Session properties的键名 */
private static final String PROPS_HOST = "mail.pop3.host";
private static final String PROPS_PORT = "mail.pop3.port";
private static final String PROPS_SSL = "mail.pop3.ssl.enable";
private static final String PROPS_AUTH = "mail.pop3.auth";
private static final String PROPS_SOCKS_PROXY_HOST = "mail.pop3.socks.host";
private static final String PROPS_SOCKS_PROXY_PORT = "mail.pop3.socks.port";
private static final String PROPS_HTTP_PROXY_HOST = "mail.pop3.proxy.host";
private static final String PROPS_HTTP_PROXY_PORT = "mail.pop3.proxy.port";
private static final String PROPS_HTTP_PROXY_USER = "mail.pop3.proxy.user";
private static final String PROPS_HTTP_PROXY_PASSWORD = "mail.pop3.proxy.password";
/** * POP3只能打开INBOX文件夹,也就是收件箱 */
private static final String FOLDER_INBOX = "INBOX";
/** * 一次性最多能同步的数量 */
private static final int MAX_SYNCHRO_SIZE = 80;
/** * 解析邮件 * * @param mailItem 需要解析的邮件列表项 * @param localSavePath 本地存储路径 * @return * @throws MailPlusException */
@Override
public UniversalMail parseEmail(MailItem mailItem, String localSavePath) throws MailPlusException {
//使用通用的邮件解析工具类解析邮件
return MailItemParser.parseMail(mailItem, localSavePath);
}
/** * 列举需要被同步的邮件 * * @param mailConn 邮箱连接,也可以做成字段 * @param existUids 已存在的邮件uid * @return * @throws MailPlusException */
@Override
public List<MailItem> listAll(MailConn mailConn, List<String> existUids) throws MailPlusException {
POP3Store pop3Store = mailConn.getPop3Store();
try {
//获取文件夹,POP3只能获取收件箱的邮件
POP3Folder folder = (POP3Folder) pop3Store.getFolder(FOLDER_INBOX);
//文件夹必须打开才可以获取邮件
folder.open(Folder.READ_ONLY);
Message[] messages = folder.getMessages();
List<MailItem> mailItems = new ArrayList<>();
//进行去重筛选需要同步的邮件
for (int i = messages.length - 1; i >= 0; i--) {
String uid = folder.getUID(messages[i]);
if (!existUids.contains(uid)) {
POP3Message pop3Message = (POP3Message) messages[i];
mailItems.add(MailItem.builder().pop3Message(pop3Message).build());
}
//到一定数量停止
if (mailItems.size() == MAX_SYNCHRO_SIZE) {
break;
}
}
return mailItems;
} catch (MessagingException e) {
e.printStackTrace();
throw new MailPlusException(String.format("【POP3服务】打开文件夹/获取邮件列表失败,错误信息【{}】"));
}
}
/** * 连接服务器 * * @param mailConnCfg 连接配置 * @param proxy 是否设置代理 * @return 返回连接 */
@Override
public MailConn createConn(MailConnCfg mailConnCfg, boolean proxy) throws MailPlusException {
//构建Session Properties
Properties properties = new Properties();
properties.put(PROPS_HOST, mailConnCfg.getHost());
properties.put(PROPS_PORT, mailConnCfg.getPort());
properties.put(PROPS_SSL, mailConnCfg.isSsl());
properties.put(PROPS_AUTH, true);
//设置代理
if (proxy && mailConnCfg.getProxyType() != null) {
ProxyTypeEnum proxyType = mailConnCfg.getProxyType();
if (proxyType.equals(ProxyTypeEnum.HTTP)) {
properties.put(PROPS_HTTP_PROXY_HOST, mailConnCfg.getProxyHost());
properties.put(PROPS_HTTP_PROXY_PORT, mailConnCfg.getProxyPort());
properties.put(PROPS_HTTP_PROXY_USER, mailConnCfg.getProxyUsername());
properties.put(PROPS_HTTP_PROXY_PASSWORD, mailConnCfg.getProxyPassword());
} else if (proxyType.equals(ProxyTypeEnum.SOCKS)) {
//java mail里socks代理是不支持用户名密码验证的
properties.put(PROPS_SOCKS_PROXY_HOST, mailConnCfg.getSocksProxyHost());
properties.put(PROPS_SOCKS_PROXY_PORT, mailConnCfg.getSocksProxyPort());
}
}
//构建session
Session session = Session.getInstance(properties);
try {
//连接
Store store = session.getStore("pop3");
store.connect(mailConnCfg.getEmail(), mailConnCfg.getPassword());
return MailConn.builder().pop3Store((POP3Store) store).build();
} catch (NoSuchProviderException e) {
e.printStackTrace();
throw new MailPlusException(e.getMessage());
} catch (MessagingException e) {
e.printStackTrace();
throw new MailPlusException(e.getMessage());
}
}
}
2.IMAP邮件拉取
IMAP和POP3差不多,但是IMAP能获取到更多的文件夹。值得注意的是IMAP的邮件uid是数字,针对帐号和文件夹唯一,建议自己重装一下uid,我采用【文件夹+uid】的格式返回,如果你是多用户的一个项目,可以【用户ID+邮箱+文件夹+uid】的格式,或者在这个基础上再md5一下。
/** * IMAP4协议邮箱收取类 * * @author zeemoo * @date 2018/12/8 */
public class ImapService implements IMailService {
/** * Session properties的键名 */
private static final String PROPS_HOST = "mail.imap.host";
private static final String PROPS_PORT = "mail.imap.port";
private static final String PROPS_SSL = "mail.imap.ssl.enable";
private static final String PROPS_AUTH = "mail.imap.auth";
private static final String PROPS_SOCKS_PROXY_HOST = "mail.imap.socks.host";
private static final String PROPS_SOCKS_PROXY_PORT = "mail.imap.socks.port";
private static final String PROPS_HTTP_PROXY_HOST = "mail.imap.proxy.host";
private static final String PROPS_HTTP_PROXY_PORT = "mail.imap.proxy.port";
private static final String PROPS_HTTP_PROXY_USER = "mail.imap.proxy.user";
private static final String PROPS_HTTP_PROXY_PASSWORD = "mail.imap.proxy.password";
private static final String PROPS_PARTIALFETCH = "mail.imap.partialfetch";
private static final String PROPS_STARTTLS = "mail.imap.starttls.enable";
/** * 一次性最多同步的邮件数量 */
private static final int MAX_SYNCHRO_SIZE = 100;
/** * 解析邮件 * * @param mailItem 邮箱列表项 * @param localSavePath 本地存储路径 * @return * @throws MailPlusException */
@Override
public UniversalMail parseEmail(MailItem mailItem, String localSavePath) throws MailPlusException {
return MailItemParser.parseMail(mailItem, localSavePath);
}
/** * 列举需要被同步的邮件 * * @param mailConn 邮箱连接,可以做成这个类的字段 * @param existUids 已同步的邮件uid * @return * @throws MailPlusException */
@Override
public List<MailItem> listAll(MailConn mailConn, List<String> existUids) throws MailPlusException {
IMAPStore imapStore = mailConn.getImapStore();
try {
Folder defaultFolder = imapStore.getDefaultFolder();
List<MailItem> mailItems = new ArrayList<>();
Folder[] list = defaultFolder.list();
//判断是否达到一定数量的标志(使用双层循环)
boolean flag = false;
for (int i = 0; i < list.length; i++) {
IMAPFolder imapFolder = (IMAPFolder) list[i];
//Gmail额外分层
if (imapFolder.getName().equalsIgnoreCase("[gmail]")) {
flag = listGmailMessageFolder(mailItems, existUids, imapFolder);
} else {
flag = listFolderMessage(mailItems, existUids, imapFolder);
}
//已达到数目,直接退出循环
if (flag) {
break;
}
}
return mailItems;
} catch (MessagingException e) {
e.printStackTrace();
throw new MailPlusException(String.format("【IMAP服务】打开文件夹/获取邮件列表失败,错误信息【{}】"));
}
}
/** * Gmail邮箱有额外的一层文件夹,需要被再打开一次 * * @param target 存储需要被同步的邮件列表项 * @param existUids 已同步下来的邮件uid * @param imapFolder 有邮件的文件夹 * @return * @throws MessagingException */
private boolean listGmailMessageFolder(List<MailItem> target, List<String> existUids, IMAPFolder imapFolder) throws MessagingException {
Folder[] list = imapFolder.list();
boolean flag = false;
for (Folder folder :
list) {
flag = listFolderMessage(target, existUids, (IMAPFolder) folder);
if (flag) {
break;
}
}
return flag;
}
/** * 通用的获取文件夹下邮件代码 * * @param target 存储需要被同步的邮件列表项 * @param existUids 已同步下来的邮件uid * @param imapFolder 有邮件的文件夹 * @return * @throws MessagingException */
private boolean listFolderMessage(List<MailItem> target, List<String> existUids, IMAPFolder imapFolder) throws MessagingException {
boolean flag = false;
imapFolder.open(Folder.READ_ONLY);
Message[] messages = imapFolder.getMessages();
for (int j = messages.length - 1; j >= 0; j--) {
if (!existUids.contains(String.valueOf(imapFolder.getFullName() + imapFolder.getUID(messages[j])))) {
target.add(MailItem.builder().imapMessage((IMAPMessage) messages[j]).build());
}
flag = target.size() == MAX_SYNCHRO_SIZE;
if (flag) {
break;
}
}
return flag;
}
/** * 连接服务器 * * @param mailConnCfg 连接配置 * @param proxy 是否代理 * @return 返回连接 */
@Override
public MailConn createConn(MailConnCfg mailConnCfg, boolean proxy) throws MailPlusException {
//构建Session Properties
Properties properties = new Properties();
properties.put(PROPS_HOST, mailConnCfg.getHost());
properties.put(PROPS_PORT, mailConnCfg.getPort());
properties.put(PROPS_SSL, mailConnCfg.isSsl());
properties.put(PROPS_PARTIALFETCH, false);
properties.put(PROPS_STARTTLS, false);
properties.put(PROPS_AUTH, true);
//设置代理
if (proxy && mailConnCfg.getProxyType() != null) {
ProxyTypeEnum proxyType = mailConnCfg.getProxyType();
if (proxyType.equals(ProxyTypeEnum.SOCKS)) {
properties.put(PROPS_SOCKS_PROXY_HOST, mailConnCfg.getSocksProxyHost());
properties.put(PROPS_SOCKS_PROXY_PORT, mailConnCfg.getSocksProxyPort());
} else if (proxyType.equals(ProxyTypeEnum.HTTP)) {
properties.put(PROPS_HTTP_PROXY_HOST, mailConnCfg.getProxyHost());
properties.put(PROPS_HTTP_PROXY_PORT, mailConnCfg.getProxyPort());
properties.put(PROPS_HTTP_PROXY_USER, mailConnCfg.getProxyUsername());
properties.put(PROPS_HTTP_PROXY_PASSWORD, mailConnCfg.getProxyPassword());
}
}
//构建session
Session session = Session.getInstance(properties);
try {
//连接
Store store = session.getStore("imap");
store.connect(mailConnCfg.getEmail(), mailConnCfg.getPassword());
return MailConn.builder().imapStore((IMAPStore) store).build();
} catch (NoSuchProviderException e) {
e.printStackTrace();
throw new MailPlusException(e.getMessage());
} catch (MessagingException e) {
e.printStackTrace();
throw new MailPlusException(e.getMessage());
}
}
}
3.Exchange邮件收取
Exchange跟前面的都不一样,使用的是HTTP登录的方式。而且ews的方式和java mail的方式也是很不一样,多是用静态方法的方式去构建。关于服务器地址,Exchange是不需要自己填入服务器地址和端口的,它有一个自动发现的方法。还有就是Exchange的邮件,不管附件是不是在邮件正文里,都会带有cid的值。
/** * Exchange服务 * * @author zeemoo * @date 2019/01/18 */
public class MyExchangeService implements IMailService {
/** * 最大同步数量 */
private static final int MAX_SYNCHRO_SIZE = 80;
/** * 解析邮件 * * @param mailItem * @param localSavePath * @return * @throws MailPlusException */
@Override
public UniversalMail parseEmail(MailItem mailItem, String localSavePath) throws MailPlusException {
return MailItemParser.parseMail(mailItem, localSavePath);
}
/** * 列举需要被同步的邮件 * * @param mailConn * @param existUids * @return * @throws MailPlusException */
@Override
public List<MailItem> listAll(MailConn mailConn, List<String> existUids) throws MailPlusException {
ExchangeService exchangeService = mailConn.getExchangeService();
try {
Folder msgFolderRoot = Folder.bind(exchangeService, WellKnownFolderName.MsgFolderRoot);
int childFolderCount = msgFolderRoot.getChildFolderCount();
FolderView folderView = new FolderView(childFolderCount);
FindFoldersResults folders = msgFolderRoot.findFolders(folderView);
ArrayList<Folder> folderList = folders.getFolders();
List<MailItem> mailItems = new ArrayList<>();
//判断是否达到一定数量的标志(使用双层循环)
boolean flag = false;
for (int i = 0; i < folderList.size(); i++) {
Folder folder = folderList.get(i);
String displayName = folder.getDisplayName();
//排除已知的非邮件格式的文件夹(是EmailMessage类型但是不是标准邮件)
if (
displayName.equals("Files")
|| displayName.equals("文件")
|| displayName.equals("檔案")
|| displayName.equals("記事")
) {
continue;
}
if (folder.getTotalCount() > 0) {
ItemView itemView = new ItemView(folder.getTotalCount());
itemView.getOrderBy().add(ItemSchema.DateTimeReceived, SortDirection.Descending);
FindItemsResults<Item> items = exchangeService.findItems(folder.getId(), itemView);
ArrayList<Item> itemList = items.getItems();
for (Item item :
itemList) {
if (item instanceof EmailMessage && !existUids.contains(item.getId().getUniqueId())) {
EmailMessage message = (EmailMessage) item;
mailItems.add(MailItem.builder().exchangeMessage(message).build());
}
flag = mailItems.size() >= MAX_SYNCHRO_SIZE;
if (flag) {
break;
}
}
if (flag) {
break;
}
}
}
return mailItems;
} catch (Exception e) {
e.printStackTrace();
throw new MailPlusException(e.getMessage());
}
}
/** * 连接服务器 * * @param mailConnCfg 连接配置 * @param proxy 是否代理 * @return 返回连接 */
@Override
public MailConn createConn(MailConnCfg mailConnCfg, boolean proxy) throws MailPlusException {
ExchangeService service = new ExchangeService();
//配置代理
if (proxy) {
WebProxy webProxy = new WebProxy(
mailConnCfg.getHost()
, mailConnCfg.getProxyPort()
, new WebProxyCredentials(
mailConnCfg.getProxyUsername()
, mailConnCfg.getProxyPassword()
, ""
)
);
service.setWebProxy(webProxy);
}
service.setCredentials(
new WebCredentials(
mailConnCfg.getEmail()
, mailConnCfg.getPassword()
)
);
//设置超时时间,在拉取邮件的时候保证不中断
service.setTimeout(600000);
try {
if (mailConnCfg.isSsl()) {
//我怀疑exchange的都是https方式
service.autodiscoverUrl(mailConnCfg.getEmail(), redirectionUrl -> {
return redirectionUrl.toLowerCase().startsWith("https://");
});
} else {
service.autodiscoverUrl(mailConnCfg.getEmail());
}
return MailConn.builder().exchangeService(service).build();
} catch (Exception e) {
e.printStackTrace();
throw new MailPlusException(e.getMessage());
}
}
}
4.通用邮件解析工具类
直接上代码吧
/** * 通用邮件解析工具 * * @author zeemoo * @date 2019/01/18 */
public class MailItemParser {
public static final String IMPORT_FOLDER = "手动导入";
/** * eml文件后缀 */
private static final String EML_SUFFIX = ".eml";
/** * 解析通用邮件内容 * * @param mailItem * @param targetDir * @return */
public static UniversalMail parseMail(MailItem mailItem, String targetDir) throws MailPlusException {
UniversalMail universalMail = null;
if (mailItem.getPop3Message() != null) {
POP3Message pop3Message = mailItem.getPop3Message();
universalMail = parseMimeMessage(pop3Message, targetDir);
if (universalMail.getHasAttachment()) {
List<UniversalAttachment> universalAttachments = parseAttachment(pop3Message, targetDir + "/" + universalMail.getUid());
universalMail.setAttachments(universalAttachments);
}
String emlPath = saveMimiMessageAsLocalEml(pop3Message, targetDir + "/" + universalMail.getUid());
universalMail.setEmlPath(emlPath);
} else if (mailItem.getImapMessage() != null) {
IMAPMessage imapMessage = mailItem.getImapMessage();
universalMail = parseMimeMessage(imapMessage, targetDir);
if (universalMail.getHasAttachment()) {
List<UniversalAttachment> universalAttachments = parseAttachment(imapMessage, targetDir + "/" + universalMail.getUid());
universalMail.setAttachments(universalAttachments);
}
String emlPath = saveMimiMessageAsLocalEml(imapMessage, targetDir + "/" + universalMail.getUid());
universalMail.setEmlPath(emlPath);
} else if (mailItem.getExchangeMessage() != null) {
universalMail = parseExchangeMail(mailItem.getExchangeMessage());
//解析附件
if (universalMail.getHasAttachment()) {
try {
EmailMessage exchangeMessage = mailItem.getExchangeMessage();
exchangeMessage.load(new PropertySet(EmailMessageSchema.MimeContent, EmailMessageSchema.AllowedResponseActions, EmailMessageSchema.Attachments));
List<UniversalAttachment> attachments = parseAttachment(exchangeMessage.getAttachments(), targetDir + "/" + universalMail.getUid());
universalMail.setAttachments(attachments);
} catch (Exception e) {
e.printStackTrace();
throw new MailPlusException(e.getMessage());
}
}
//保存到本地
String emlPath = saveExchangeMailAsLocalEml(mailItem.getExchangeMessage(), targetDir + "/" + universalMail.getUid());
universalMail.setEmlPath(emlPath);
}
return universalMail;
}
/** * 保存邮件到本地的eml中 * * @param mimeMessage * @param targetDir * @return */
public static String saveMimiMessageAsLocalEml(MimeMessage mimeMessage, String targetDir) throws MailPlusException {
try {
String subject = mimeMessage.getSubject();
subject = StringUtils.isEmpty(subject) ? "无主题" + System.currentTimeMillis() : subject;
File file = new File(targetDir.concat("/")
.concat(mimeMessage.getSession() == null ? RandomStringUtils.random(40, true, true) : DigestUtils.md5Hex(subject))
.concat(EML_SUFFIX));
if (!file.getParentFile().exists()) {
file.getParentFile().mkdirs();
}
if (!file.exists()) {
file.createNewFile();
mimeMessage.writeTo(new FileOutputStream(file));
}
return file.getAbsolutePath();
} catch (MessagingException e) {
e.printStackTrace();
throw new MailPlusException(e.getMessage());
} catch (IOException e) {
e.printStackTrace();
throw new MailPlusException(e.getMessage());
}
}
/** * 解析邮件附件 * * @param mimeMessage * @param targetDir * @return */
public static List<UniversalAttachment> parseAttachment(MimeMessage mimeMessage, String targetDir) throws MailPlusException {
try {
MimeMessageParser parser = new MimeMessageParser(mimeMessage).parse();
List<UniversalAttachment> list = new ArrayList<>();
File dir = new File(targetDir);
if (!dir.exists()) {
dir.mkdirs();
}
List<DataSource> attachmentList = parser.getAttachmentList();
Collection<String> contentIds = parser.getContentIds();
Set<String> cidFile = new HashSet<>();
for (String cid : contentIds) {
DataSource attachmentByCid = parser.findAttachmentByCid(cid);
File file = new File(targetDir + "/" + attachmentByCid.getName());
if (!file.exists()) {
file.createNewFile();
FileUtils.copyInputStreamToFile(attachmentByCid.getInputStream(), file);
}
UniversalAttachment universalAttachment = UniversalAttachment.builder()
.cid(cid)
.path(file.getAbsolutePath())
.name(attachmentByCid.getName())
.contentType(attachmentByCid.getContentType())
.build();
list.add(universalAttachment);
cidFile.add(attachmentByCid.getName());
}
for (DataSource dataSource :
attachmentList) {
if (cidFile.contains(dataSource.getName())) {
continue;
}
File file = new File(targetDir + "/" + dataSource.getName());
if (!file.exists()) {
file.createNewFile();
FileUtils.copyInputStreamToFile(dataSource.getInputStream(), file);
}
UniversalAttachment universalAttachment = UniversalAttachment.builder()
.cid(null)
.path(file.getAbsolutePath())
.name(dataSource.getName())
.contentType(dataSource.getContentType())
.build();
list.add(universalAttachment);
}
return list;
} catch (Exception e) {
e.printStackTrace();
throw new MailPlusException(e.getMessage());
}
}
/** * 解析mime邮件 * * @param mimeMessage * @param targetDir * @return * @throws MailPlusException */
public static UniversalMail parseMimeMessage(MimeMessage mimeMessage, String targetDir) throws MailPlusException {
try {
MimeMessageParser parser = new MimeMessageParser(mimeMessage).parse();
javax.mail.Folder folder = mimeMessage.getFolder();
String uid = "";
//组装uid
if (mimeMessage instanceof IMAPMessage) {
uid = folder.getName() + ((IMAPFolder) folder).getUID(mimeMessage);
} else if (mimeMessage instanceof POP3Message) {
uid = ((POP3Folder) folder).getUID(mimeMessage);
} else {
uid = UUID.randomUUID().toString();
}
if (StringUtils.isEmpty(uid)) {
throw new MailPlusException("【MIME邮件解析】解析uid失败");
}
String subject = parser.getSubject();
String body = parser.hasHtmlContent() ? parser.getHtmlContent() : parser.getPlainContent();
UniversalMail universalMail = UniversalMail.builder()
.content(StringUtils.isEmpty(body) ? "" : EmojiParser.parseToAliases(body))
.uid(uid)
.receiver(getMimeMessageAddressJson(parser.getTo()))
.title(StringUtils.isEmpty(subject) ? "<无主题>" : EmojiParser.parseToAliases(subject))
.sendDate(mimeMessage.getSentDate())
.hasRead(mimeMessage.getFlags().equals(Flags.Flag.SEEN))
.hasAttachment(parser.hasAttachments())
.fromer(parser.getFrom())
.folder(folder != null ? folder.getName() : IMPORT_FOLDER)
.cc(getMimeMessageAddressJson(parser.getCc()))
.bcc(getMimeMessageAddressJson(parser.getBcc()))
.build();
return universalMail;
} catch (Exception e) {
e.printStackTrace();
throw new MailPlusException(e.getMessage());
}
}
/** * 获取JSON格式的邮件地址 * * @param address * @return */
public static String getMimeMessageAddressJson(List<Address> address) {
List<UniversalRecipient> recipients = new ArrayList<>();
for (int i = 0; i < address.size(); i++) {
InternetAddress internetAddress = (InternetAddress) address.get(i);
UniversalRecipient build = UniversalRecipient.builder()
.name(StringUtils.isNotEmpty(internetAddress.getPersonal()) ? EmojiParser.parseToAliases(internetAddress.getPersonal()) : internetAddress.getAddress())
.email(internetAddress.getAddress())
.build();
recipients.add(build);
}
return JSON.toJSONString(recipients);
}
/** * 保存到本地,必须在解析完邮件之后再保存,不然会报错,加载的头不一样了 * * @param exchangeMessage * @param targetDir * @return * @throws MailPlusException */
public static String saveExchangeMailAsLocalEml(EmailMessage exchangeMessage, String targetDir) throws MailPlusException {
try {
File dir = new File(targetDir);
if (dir.exists()) {
dir.mkdirs();
}
exchangeMessage.load();
String subject = exchangeMessage.getSubject();
subject = StringUtils.isEmpty(subject) ? "<无主题>" + System.currentTimeMillis() : subject;
File eml = new File(targetDir.concat("/").concat(DigestUtils.md5Hex(subject).concat(EML_SUFFIX)));
exchangeMessage.load(
new PropertySet(
EmailMessageSchema.MimeContent
, EmailMessageSchema.AllowedResponseActions
)
);
if (!eml.exists()) {
File parentFile = eml.getParentFile();
if (!parentFile.exists()) {
parentFile.mkdirs();
}
eml.createNewFile();
byte[] content = exchangeMessage.getMimeContent().getContent();
FileUtils.writeByteArrayToFile(eml, content);
}
return eml.getAbsolutePath();
} catch (Exception e) {
e.printStackTrace();
throw new MailPlusException(e.getMessage());
}
}
/** * 解析Exchange附件 * * @param attachments * @param targetDir * @return */
public static List<UniversalAttachment> parseAttachment(AttachmentCollection attachments, String targetDir) {
List<UniversalAttachment> universalAttachments = new ArrayList<>();
List<Attachment> items = attachments.getItems();
File dir = new File(targetDir);
if (!dir.exists()) {
dir.mkdirs();
}
for (Attachment attachment :
items) {
try {
String path = targetDir + "/" + attachment.getName();
File file = new File(path);
if (!file.exists()) {
file.createNewFile();
if (attachment instanceof FileAttachment) {
((FileAttachment) attachment).load(file.getAbsolutePath());
} else if (attachment instanceof ItemAttachment) {
ItemAttachment itemAttachment = (ItemAttachment) attachment;
itemAttachment.load(ItemSchema.MimeContent);
Item item = itemAttachment.getItem();
FileUtils.writeByteArrayToFile(file, item.getMimeContent().getContent());
}
}
universalAttachments.add(
UniversalAttachment.builder()
.cid(attachment.getContentId())
.contentType(attachment.getContentType())
.name(attachment.getName())
.path(path)
.build()
);
} catch (Exception e) {
e.printStackTrace();
}
}
return universalAttachments;
}
/** * 解析exchange邮件 * * @param message * @return */
public static UniversalMail parseExchangeMail(EmailMessage message) throws MailPlusException {
try {
message.load();
String subject = message.getSubject();
EmailAddress from = message.getFrom();
String body = message.getBody().toString();
Date dateTimeSent = null;
try {
dateTimeSent = message.getDateTimeSent();
} catch (ServiceLocalException e) {
e.printStackTrace();
}
UniversalMail.UniversalMailBuilder builder = UniversalMail.builder()
.bcc(getExchangeAddressJson(message.getBccRecipients()))
.cc(getExchangeAddressJson(message.getCcRecipients()))
.folder(Folder.bind(message.getService(), message.getParentFolderId()).getDisplayName())
.fromer(from == null ? "<无发件人>" : from.getAddress())
.hasAttachment(message.getHasAttachments())
.hasRead(message.getIsRead())
.sendDate(dateTimeSent)
//处理emoji
.title(StringUtils.isAnyEmpty(message.getSubject()) ? "<无主题>" : EmojiParser.parseToAliases(subject))
.receiver(getExchangeAddressJson(message.getToRecipients())).uid(message.getId().getUniqueId())
.content(StringUtils.isEmpty(body) ? "" : EmojiParser.parseToAliases(body));
UniversalMail universalMail = builder.build();
return universalMail;
} catch (ServiceLocalException e) {
e.printStackTrace();
throw new MailPlusException(e.getMessage());
} catch (Exception e) {
e.printStackTrace();
throw new MailPlusException(e.getMessage());
}
}
/** * 解析exchange地址为键值对并转换成JSON字符串 * * @param recipients * @return */
public static String getExchangeAddressJson(EmailAddressCollection recipients) {
List<EmailAddress> items = recipients.getItems();
List<UniversalRecipient> list = new ArrayList<>();
for (EmailAddress emailAddress :
items) {
list.add(
UniversalRecipient.builder()
.email(emailAddress.getAddress())
.name(StringUtils.isNotEmpty(emailAddress.getName()) ? EmojiParser.parseToAliases(emailAddress.getName()) : emailAddress.getAddress())
.build()
);
}
return JSON.toJSONString(list);
}
}