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