最近在做邮件提醒抄送企业微信消息系统,就目前而言,无论是pop3还是imap都没有一个好的方法只接收新邮件,基本只能依靠收件箱列表message自行判断,下面给出几种思路并作对比。
//收件箱
folder = store.getFolder("INBOX");
//权限
folder.open(Folder.READ_ONLY);
1 缓存(redis)计数方案
这是最为直观的一种方式,基本思想是,在redis中对处理过新邮件的数目作原子加标记cacheTotal,定时扫描收件箱中所有邮件数目total, total与cacheTotal的差值即为新邮件数目,当然也很容易获取到新邮件的数组下标。
- 优点:直观,简单
- 缺点:粗暴,可能因为邮件归档,redis异常等原因,造成误读,风险较大
2 采用flag判断是否是新邮件
flag是邮件对象message的一种标识,需要设置:
- 需要使用imap协议,Store store = session.getStore("imap");
- 设置folder需要读写权限, folder.open(Folder.READ_WRITE);
但获取flag注意一点:在第一行,如果你调用了getMessages(),在第二次运行程序时就不会出现新邮件!因为调用了getMessages(),它就把新邮件读成了旧邮件。 运行结果:第一次运行,输出的flag:javax.mail.Flags@10,再次运行就全是0了。
- 优点:flag在能获取有效值的情况下,可精确判定是新邮件唯一标识
- 缺点:(1)限定是imap协议,pop3不可行(2)flag不能稳定获取,对于需要分批次拉取新邮件的需求不能满足
3 采用【邮箱名+UID】方式接收新邮件
UID是账户的每一封邮件的标识,不同于MessageID,MessageID是发送邮件的时候生成的唯一ID,也有可能发送没有你的接收邮箱自己生成,或者是javamail生成的,取messageid需要下载邮件的头造成效率缓慢,所以只需要存储uid;以POP3为例:
UID唯一性的前提是在同一个账户里,也就是说在不同账户下UID还是可能又相同的,这在数据库持久化时得注意,故采用【邮箱名+UID】得方式存储。还有就是session如果不带有用户和服务器信息, 就这样生成一个公用的就可以了 :
- 优点:(1)能精准识别新邮件(2)pop3,imap均可支持
- 缺点:(1)还行吧