修改源码提高JavaMail比较新邮件效率
在JavaMail API 里还是一封封的去比较邮件,如果连接上服务器可以发一个命令就可以获得所有的邮件头列表是多么好的事情,可惜Javamail暂时没有提供这样的功能,我们只能自己丰衣足食了。把 POP 的UIDL 命令写在 JavaMail API 里进行调用。
你可以先看一下原先的方法最古老的方法,详见:《JavaMail议判断新邮件的思路》
其中
for (int i = 0; i < messages.length; i++,j–)
System.out.println(inbox.getUID(messages[i]));
}
这段代码我们就能看见需要一封一封的进行获得邮件UID,而我们下面提出的方法要比这样的效率高很多。
你可以下载JavaMail的源代码,修改JavaMail 源代码 com.sun.mail.pop3.Protocol 和 POP3Folder 2个程序,在代码中添加如下部分
================================Protocol.java===================================================
public ArrayList<String> extendCommand(String cmd) throws IOException {
log.info("extendCommand …………….");
ArrayList<String> msgID = new ArrayList<String>();
if (socket == null)
throw new IOException("Folder is closed"); //
if (cmd != null) {
if (debug)
out.println("C: " + cmd);
cmd += CRLF;
output.print(cmd); // do it in one write
output.flush();
}
String line = input.readLine(); // XXX – readLine is deprecated
if (line.startsWith("+OK")){
while (line != null) {
line = input.readLine();
if (line != null && line.trim().equals(".")) {
break;
}
msgID.add(line);
}
}else{
throw new IOException("Unexpected response: " + line);
}
return msgID;
}
// uidl方法 extendCommand方法执行UIDL命令,这回的有序的TreeMap属性
synchronized TreeMap<String,String> uidl() throws IOException {
log.info(" get uidl………"); // 打印日志
ArrayList<String> msgID = extendCommand("UIDL"); // 执行 UIDL命令
TreeMap<String,String> treeMap = new TreeMap<String,String>();
String[] temp = null;
for(String ID:msgID){
temp = ID.split("\\s+");
treeMap.put(temp[1], temp[0]);
}
return treeMap;
}
================================POP3Folder.java===================================================
public synchronized TreeMap<String,String> getAllUID() throws MessagingException {
checkOpen();
TreeMap<String,String> haspMap = null;
try {
haspMap = port.uidl();
} catch (EOFException eex) {
close(false);
throw new FolderClosedException(this, eex.toString());
} catch (IOException ex) {
throw new MessagingException("error getting all UIDL", ex);
}
return haspMap;
}
上述方式 是向 邮件服务器 发送一个UIDL命令,邮件服务器立刻返回给你邮件服务器上所有邮件的ID编号,如果需要比较新邮件,将上一次的结果保存下来,再用Hash 的方法比较2次的结果,比较后的结果就是新邮件,这样的效率将会比原来至少提高很多倍的效率,当处理一个邮箱内有大量邮件需要进行比较的时候,这样的方法非常有效。
细看了Sun 的JavaMail 源代码,说白了 Sun的JavaMail也是通过pop/smtp命令对邮件服务器进行操作,所以这样修改一点也不违背JavaMail本身的设计思想,我画了一个图来表达了自己的想法,如图所示:

修改后的 JavaMail 源代码 下载
测试代码如下
public static void main(String[] args) throws Exception {
Store store=null;
POP3Folder inbox=null;
Properties props = System.getProperties();
Session session = Session.getDefaultInstance(props, null);
store = session.getStore("pop3");
store.connect("pop.163.com", "test@163.com", "123456");
inbox = (POP3Folder) store.getFolder("INBOX");
inbox.open(Folder.READ_ONLY);
TreeMap<String, String> UIDTable = inbox.getAllUID();
System.out.println(UIDTable);
}
–end—

本文由J2ee企业顾问-黄毅创作,并已采用创作共用署名2.5中国大陆版许可证授权。
评论
Comment from air max 90 black
Time 2010年07月26日 at 10:02 上午
不要随意的做选择,免得将来后悔
Comment from 益阳
Time 2010年07月26日 at 2:14 下午
不错 顶一个!






Comment from levisjeans
Time 2010年07月15日 at 9:50 上午
是篇好文章,收藏者