修改源码提高JavaMail比较新邮件效率

9 七月, 2010 (16:10) | J2EE框架, 性能 繁体 English    DeliciOus    分享到新浪微博
作者: H.E. | 您可以转载, 但必须以超链接形式标明文章原始出处和作者信息及版权声明
网址: http://www.javabloger.com/article/javamail-compare-new-email.html
豆瓣读书 向你推荐有关 J2EE框架性能、 类别的图书。

在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本身的设计思想,我画了一个图来表达了自己的想法,如图所示:
http://www.javabloger.com/images/2010-07/javamail.png

修改后的 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框架 性能、 类别的图书。



Creative Commons License
本文由J2ee企业顾问-黄毅创作,并已采用创作共用署名2.5中国大陆版许可证授权。

评论

Comment from levisjeans
Time 2010年07月15日 at 9:50 上午

是篇好文章,收藏者

Comment from air max 90 black
Time 2010年07月26日 at 10:02 上午

不要随意的做选择,免得将来后悔

Comment from 益阳
Time 2010年07月26日 at 2:14 下午

不错 顶一个!

评论

评论也是有版权的!




4434