對這文章發表回應
發表限制: 非會員 可以發表
發表者: 冷日 發表時間: 2019/12/18 5:23:41
javaMail使用javax.mail自動讀取郵件,並下載解析附件,IMAP/POP3協議等
搜索網上各個案例,總結的一套比較全面且行之有效的方法。供大家參考使用!
使用javax.mail自動讀取郵件,並下載解析附件,IMAP/POP3協議等!
直接上代碼如下:
原文出處:javaMail使用javax.mail自動讀取郵件,並下載解析附件,IMAP/POP3協議等 - 台部落
搜索網上各個案例,總結的一套比較全面且行之有效的方法。供大家參考使用!
使用javax.mail自動讀取郵件,並下載解析附件,IMAP/POP3協議等!
直接上代碼如下:
package ***
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.mail.Address;
import javax.mail.Folder;
import javax.mail.Message;
import javax.mail.MessagingException;
import javax.mail.Multipart;
import javax.mail.NoSuchProviderException;
import javax.mail.Part;
import javax.mail.Session;
import javax.mail.Store;
import javax.mail.internet.InternetAddress;
import javax.mail.internet.MimeUtility;
import javax.mail.search.AndTerm;
import javax.mail.search.ComparisonTerm;
import javax.mail.search.FromStringTerm;
import javax.mail.search.SearchTerm;
import javax.mail.search.SentDateTerm;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Calendar;
import java.util.Date;
import java.util.Properties;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
*/
@Component
public class BlacklistCodeTask {
private static Logger logger = LoggerFactory.getLogger(BlacklistCodeTask.class);
@Autowired
private blacklistService blacklistService;
// 郵箱附件保存路徑
private static String FILE_SAVE_PATH = ConfigProperties.getProperties("blacklist.emailFilePath");
// 讀取的發件人
private static String fromEmail = ConfigProperties.getProperties("blacklist.fromEmail");
// 收件服務器
private static String hostServer = ConfigProperties.getProperties("blacklist.hostServer");
private static String protocol = ConfigProperties.getProperties("blacklist.protocol");
private static String port = ConfigProperties.getProperties("blacklist.port");
private static String username = ConfigProperties.getProperties("blacklist.username");
private static String password = ConfigProperties.getProperties("blacklist.password");
// 執行日期標識
String dateTimeFlag;
// 附件名稱關鍵詞
private static String FILE_NAME_FLAG1 = "加黑***明細";
private static String FILE_NAME_FLAG2 = "加黑";
// Runtime.getRuntime().availableProcessors()
public static ExecutorService threadPool = Executors.newFixedThreadPool(1);
/**
* 定時任務獲取前一天郵件,並解析保存黑端口號碼
*/
public void acquireXinAnEmails() {
try {
// 1. 設置連接信息, 生成一個 Session
// 獲取連接
Session session;
if ("pop3".equalsIgnoreCase(protocol)) {
session = Session.getInstance(getPOP3());
// session = Session.getDefaultInstance(getPOP3());
} else {
// session = Session.getDefaultInstance(getIMAP());
session = Session.getInstance(getIMAP());
}
session.setDebug(false);
// 2. 獲取Store, 並連接到服務器
Store store = session.getStore(protocol);
store.connect(hostServer, username, password); // POP3服務器的登陸認證
//
Folder defaultFolder = store.getDefaultFolder();// 默認父目錄
if (defaultFolder == null) {
logger.error("服務器不可用! hostServer:{}", hostServer);
return;
}
//
Folder folder = defaultFolder.getFolder("INBOX");// 獲取收件箱
folder.open(Folder.READ_WRITE);// 可讀郵件,可以刪郵件的模式打開目錄
// 取出來郵件數
logger.info("folder urlName: {}, 共有郵件: {}封, UnreadMessages: {}, NewMessages: {}...", folder.getURLName().toString(),
folder.getMessageCount(), folder.getUnreadMessageCount(), folder.getNewMessageCount());
//
dateTimeFlag = DateTimeUtil.formatDateTime(new Date(), DateTimeUtil.DATA_FORMAT_yyyyMMdd);
searchMails(folder);
// 7. 關閉 Folder 會真正刪除郵件, false 不刪除
folder.close(false);
// 8. 關閉 store, 斷開網絡連接
store.close();
} catch (NoSuchProviderException e) {
logger.error(e.getMessage(), e);
} catch (Exception e) {
logger.error(e.getMessage(), e);
}
// // 統一處理下載好的的Excel文件
// dealAndGetBlacklist();
}
/**
* 獲取POP3收信配置 995
*
* @return
*/
private Properties getPOP3() {
Properties props = new Properties();
props.setProperty("mail.transport.protocol", protocol);
props.setProperty("mail.pop3.host", hostServer); // 按需要更改
props.setProperty("mail.pop3.port", port);
// SSL安全連接參數
props.setProperty("mail.pop3.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
props.setProperty("mail.pop3.socketFactory.fallback", "false");
props.setProperty("mail.pop3.socketFactory.port", port);
// 解決DecodingException: BASE64Decoder: but only got 0 before padding character (=)
props.setProperty("mail.mime.base64.ignoreerrors", "true");
return props;
}
/**
* 獲取IMAP收信配置 993
*
* @return
*/
private Properties getIMAP() {
Properties props = new Properties();
props.setProperty("mail.transport.protocol", protocol);
props.setProperty("mail.imap.host", hostServer); // 按需要更改
props.setProperty("mail.imap.port", port);
// SSL安全連接參數
props.setProperty("mail.imap.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
props.setProperty("mail.imap.socketFactory.fallback", "false");
props.setProperty("mail.imap.socketFactory.port", port);
props.setProperty("mail.mime.base64.ignoreerrors", "true");
return props;
}
/**
* 創建搜索條件,並獲取郵件...第二天凌晨10分之後執行,查詢前一天零點到今天零點的數據
*
* @param folder
* @throws Exception
*/
private void searchMails(Folder folder) throws Exception {
//建立搜索條件繼承自SearchTerm,像根據發件人,主題搜索,郵件標記FlagTerm等,
// FlagTerm ft = new FlagTerm(new Flags(Flags.Flag.SEEN), false); //false代表未讀,true代表已讀
// 搜索昨天收到的的所有郵件
Calendar calendar = Calendar.getInstance();
calendar.add(Calendar.DAY_OF_MONTH, -1);
calendar.set(Calendar.HOUR_OF_DAY, 0);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
Date start = calendar.getTime();
calendar.setTime(new Date());
calendar.set(Calendar.HOUR_OF_DAY, 0);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
Date end = calendar.getTime();
SearchTerm comparisonTermGe = new SentDateTerm(ComparisonTerm.GE, start);
SearchTerm comparisonTermLe = new SentDateTerm(ComparisonTerm.LE, end);
FromStringTerm fromStringTerm = new FromStringTerm(fromEmail);
SearchTerm andTerm = new AndTerm(new SearchTerm[]{comparisonTermGe, comparisonTermLe, fromStringTerm});
logger.info("SearchTerm start: {}, end: {}, fromEmail: {}", DateTimeUtil.formatDateTime(start, DateTimeUtil.DATA_FORMAT_yyyy_MM_dd_HH_mm_ss),
DateTimeUtil.formatDateTime(end, DateTimeUtil.DATA_FORMAT_yyyy_MM_dd_HH_mm_ss), fromEmail);
//
Message[] messages = folder.search(andTerm); //根據設置好的條件獲取message
logger.info("search郵件: " + messages.length + "封, SearchTerm:" + andTerm.getClass());
// FetchProfile fProfile = new FetchProfile(); // 選擇郵件的下載模式,
// fProfile.add(FetchProfile.Item.ENVELOPE); // 根據網速選擇不同的模式
// folder.fetch(messages, fProfile);// 選擇性的下載郵件
// 5. 循環處理每個郵件並實現郵件轉爲新聞的功能
for (int i = 0; i < messages.length; i++) {
// 單個郵件
logger.info("---第" + i + "郵件開始------------");
mailReceiver(messages[i]);
logger.info("---第" + i + "郵件結束------------");
// 郵件讀取備份保存,用來校驗
// messages[i].writeTo(new FileOutputStream(FILE_SAVE_PATH + "pop3Mail_" + messages[i].getMessageNumber() + ".eml"));
}
}
/**
* 解析郵件
*
* @param msg 郵件對象
* @throws Exception
*/
private void mailReceiver(Message msg) {
try {
// 發件人信息
Address[] froms = msg.getFrom();
String mailSubject = transferChinese(msg.getSubject());
if (froms != null) {
InternetAddress addr = (InternetAddress) froms[0];
logger.info("發件人地址:" + addr.getAddress() + ", 發件人顯示名:" + transferChinese(addr.getPersonal()));
} else {
logger.error("msg.getFrom() is null... subject:" + mailSubject);
}
Date sentDate = msg.getSentDate();
logger.info("郵件主題: {}, sentDate: {}", mailSubject,
sentDate == null ? null : DateTimeUtil.formatDateTime(sentDate, DateTimeUtil.DATA_FORMAT_yyyy_MM_dd_HH_mm_ss));
// getContent() 是獲取包裹內容, Part相當於外包裝
Object content = msg.getContent();
if (content instanceof Multipart) {
Multipart multipart = (Multipart) content;
reMultipart(multipart);
} else if (content instanceof Part) {
Part part = (Part) content;
rePart(part);
} else {
String contentType = msg.getContentType();
if (contentType != null && contentType.startsWith("text/html")) {
logger.warn("---類型:" + contentType);
} else {
logger.warn("---類型:" + contentType);
logger.warn("---內容:" + msg.getContent());
}
}
} catch (Exception e) {
logger.error(e.getMessage(), e);
}
}
/**
* 把郵件主題轉換爲中文.
*
* @param strText the str text
* @return the string
*/
public String transferChinese(String strText) {
try {
if (StringUtils.isBlank(strText)) {
return null;
}
strText = MimeUtility.encodeText(new String(strText.getBytes(),
"UTF-8"), "UTF-8", "B");
strText = MimeUtility.decodeText(strText);
} catch (Exception e) {
logger.error(e.getMessage(), e);
}
return strText;
}
/**
* @param part 解析內容
* @throws Exception
*/
private void rePart(Part part) {
String tempFilePath = null;
try {
// 附件
if (part.getDisposition() != null) {
// 郵件附件
String strFileName = MimeUtility.decodeText(part.getFileName()); //MimeUtility.decodeText解決附件名亂碼問題
logger.info("發現附件: {}, 內容類型: {} ", strFileName, MimeUtility.decodeText(part.getContentType()));
// 讀取附件字節並存儲到文件中. xls/xlsx
String fileType = strFileName.substring(strFileName.lastIndexOf(".") + 1);
if ((fileType.equals("xlsx") || fileType.equals("xls")) &&
(strFileName.contains(FILE_NAME_FLAG1) || strFileName.contains(FILE_NAME_FLAG2))) {
InputStream in = part.getInputStream();// 打開附件的輸入流
tempFilePath = FILE_SAVE_PATH + dateTimeFlag + strFileName;
FileOutputStream out = new FileOutputStream(tempFilePath);
int data;
while ((data = in.read()) != -1) {
out.write(data);
}
in.close();
out.close();
} else {
logger.info("not what we need file, discard it: {}", strFileName);
}
} else {
// 郵件內容
if (part.getContentType().startsWith("text/plain") || part.getContentType().startsWith("Text/Plain")) {
logger.info("Content文本內容:" + part.getContent());
} else if (part.getContentType().startsWith("text/html")) {
// logger.info("HTML內容:" + part.getContent());
logger.debug("HTML內容,,不記錄日誌展示。。");
} else {
logger.debug("!其它ContentType:" + part.getContentType() + " ?內容:" + part.getContent());
}
}
} catch (MessagingException e) {
logger.error(e.getMessage(), e);
} catch (IOException e) {
logger.error(e.getMessage(), e);
} finally {
// 單個處理黑名單文件,放入線程池處理
String finalTempFilePath = tempFilePath;
threadPool.execute(() -> {
dealBlacklist(finalTempFilePath);
}
);
}
}
/**
* @param multipart // 接卸包裹(含所有郵件內容(包裹+正文+附件))
* @throws Exception
*/
private void reMultipart(Multipart multipart) throws Exception {
logger.debug("Multipart郵件共有" + multipart.getCount() + "部分組成");
// 依次處理各個部分
for (int j = 0, n = multipart.getCount(); j < n; j++) {
Part part = multipart.getBodyPart(j);
// 解包, 取出 MultiPart的各個部分, 每部分可能是郵件內容, 也可能是另一個小包裹(MultipPart)
if (part.getContent() instanceof Multipart) {
logger.debug("部分" + j + "的ContentType: " + part.getContentType() + ", to reMultipart() ");
Multipart p = (Multipart) part.getContent();// 轉成小包裹
//遞歸迭代
reMultipart(p);
} else {
logger.debug("部分" + j + "的ContentType: " + part.getContentType() + ", to rePart() ");
rePart(part);
}
}
}
/**
* 單個處理下載好的文件
*
* @param tempFilePath
*/
private void dealBlacklist(String tempFilePath) {
if (StringUtil.isBlank(tempFilePath)) {
return;
}
logger.info("to deal with blacklist Excel file: {}", tempFilePath);
blacklistService.dealBlacklist(tempFilePath);
}
}
原文出處:javaMail使用javax.mail自動讀取郵件,並下載解析附件,IMAP/POP3協議等 - 台部落