javaMail收郵件主要有兩種協議,一種是pop3,一種是imap。這兩種協議均可以用來收郵件,可是在其中的處理上是有區別的。pop3是不支持判斷郵件是否爲已讀的,也就是說你不能直接從收件箱裏面取到未讀郵件,這須要本身進行判斷,然而imap就提供了這樣的功能,使用imap時能夠很輕鬆的判斷該郵件是否爲已讀或未讀或其餘。java
此外收件箱中的每一封郵件都對應着一個MessageNumber,因此能夠經過一個MessageNumber拿到對應的那封郵件。如:Message message = folder.getMessage(messageNumber);這樣定時任務每次讀郵箱郵件不用全量讀了。redis
1、imap協議模式下讀取數據庫
public static void readMail() { String protocol = "imap"; Properties props = new Properties(); props.setProperty("mail.transport.protocol", protocol); // 使用的協議(JavaMail規範要求) props.setProperty("mail.smtp.host", host); // 發件人的郵箱的 SMTP服務器地址 // 獲取鏈接 Session session = Session.getInstance(props); session.setDebug(false); // 獲取Store對象 Store store = session.getStore(protocol); store.connect(host, userName, password); IMAPFolder inbox = (IMAPFolder)store.getFolder("INBOX"); //若是須要在取得郵件數後將郵件置爲已讀則這裏須要使用READ_WRITE,不然READ_ONLY就能夠 inbox.open(Folder.READ_WRITE); // 所有郵件數 int messageCount = inbox.getMessageCount(); System.out.println(messageCount); //folder.getUnreadMessageCount() 未讀取郵件總數 Message[] messages = inbox.getMessages(folder.getMessageCount()-inbox.getUnreadMessageCount()+1,inbox.getMessageCount()); List<Message> mesList=new ArrayList<>(); for (int i = 0; i < messages.length; i++) { Message message = messages[i]; System.out.println(message.getSubject()); //保存我將要設置爲已讀的message列表 mesList.add(message); //解析郵件內容(網上不少我就不一一貼代碼了) ....... } //將剛纔我獲取的郵件設置爲已讀 if (mesList.size() > 0) { Message[] savedMailMessage = new Message[mesList.size()]; mesList.toArray(savedMailMessage); inbox.setFlags(savedMailMessage, new Flags(Flags.Flag.SEEN),true); } folder.close(true); store.close(); }
2、pop3協議模式下讀取
因爲pop3是不支持判斷郵件是否爲已讀的,不能直接從收件箱裏面取到未讀郵件因此沒法獲取未讀郵箱數量,可是支持inbox.getMessages(start,end)方式獲取郵件區間,所以我採用redis存儲已讀郵件位置和每批次讀取郵件數量來實現!服務器
public Integer readMail(Integer readNum,Integer size) { String protocol = "pop3"; Properties props = new Properties(); props.setProperty("mail.transport.protocol", protocol); props.setProperty("mail.smtp.host", host); // 獲取鏈接 Session session = Session.getInstance(props); session.setDebug(false); // 獲取Store對象 Store store = session.getStore(protocol); store.connect(host, userName, password); Folder folder = store.getFolder("INBOX"); folder.open(Folder.READ_WRITE); int mailTotalNum=folder.getMessageCount(); log.info("定時器讀取郵件總數: {}", mailTotalNum); Integer endNum; if(readNum<=mailTotalNum) { //我在讀取redis中的readNum+1了因此這裏要-1 endNum = readNum + size - 1 > mailTotalNum ? mailTotalNum : readNum + size - 1; log.info("讀取郵件區間:{}-{}", readNum, endNum); Message[] messages = folder.getMessages(readNum, endNum); //解析郵件內容(網上不少我就不一一貼代碼了) ........... }else { endNum=readNum-1; } folder.close(false); store.close(); //返回本次讀取位置 redis 存儲當前讀取到多少條 return endNum; }
3、如何判斷髮送失敗的郵件
因爲查詢了很久沒有方法能夠直接判斷郵件發送狀態因此我只能用我所遇到的退信格式來判斷了,以下圖(不一樣收件郵箱退信格式不一樣,渣浪的郵箱投遞不成功沒有退信)
session
根據上圖能夠發現退信的郵件主題和通常郵件不同因此我採用以下代碼判斷(很挫)spa
String subject = getSubject(msg); if (subject.startsWith("未送達")|| subject.startsWith("系統退 信")) { }
找到發送失敗的郵箱而後再提取郵件內容中的收件郵箱、發送時間等去更新數據庫中郵件的發送狀態。code
到此成功獲取郵件發送後狀態了!對象
Contactblog