-->

Why iterating over all java mail user's folder

2019-07-26 08:55发布

问题:

   Properties props = System.getProperties();
   props.put("mail.imap.connectiontimeout",5000);
   Session session = Session.getInstance(props);
   Store store = session.getStore("imap");
   for(50K users){

        //login,password changed in loop  
        String[] folders = {"inbox", "f1", "f2", "f3", "spam"};
        store.connect(serverAddress, login + emailSuffix, password);
        for (int i = 0; i < folders.length; i++) {
                    Folder x = store.getFolder(folders[i]);
                    x.open(Folder.READ_ONLY);
                    System.out.println("folder " + folders[i] + " of " + login);
                    x.getUnreadMessageCount();
                    x.close(false);
        }
        store.close();
    }

I'm using same store for all connections, changed service_count in dovecot according to this answer in order to improve imap-dovecot performance but I see only first iteration and after that code hangs or does next system.out after long time.

Actually, I need to grab all old messages of all users + count all unread messages as I want to migrate from pure Java Mail to some custom format. I didn;t manage even to just iterate over all users and folders for each user because even simple store.connect hangs after 1-st iteration!

I personally think that bottleneck is my dovecot config, but it uses default limits (1000 connections) which looks good.

My I somehow improve my dovecot or connect my store only once for all users or somehow fetch all messages of all users and unreadMessagesCount of all users in other way?

PS. The only alternative to programmatic way is some bash script in maildir which whill read each message from file system and pass it to some rest which converts to my custom format) but it much more harder than Java it's too difficult to parse smptp, parse seen flags from file name and so on.

UPDATE

I found apache commons net imapclient which works very fast.

<dependency>
    <groupId>commons-net</groupId>
    <artifactId>commons-net</artifactId>
    <version>3.3</version>
</dependency>

My code is the following

IMAPClient client = new IMAPClient();
client.connect("localhost");
for(50K users){
    client.login(login + emailSuffix, password);
    for (int i = 0; i < folders.length; i++) {
        System.out.println(client.select("INBOX"); //prints true, it's ok
    }
}
  1. Looks like it connects faster than java mailapi because it may connect once to host and after that login for each user. May I somehow repeat such behavior in JavaMail API?
  2. How may I grab messages with apache commons client? All methods return boolean or void, so it's looks like just server checking library am I right? Is it possible to somehow get useful info from imapclient?

回答1:

Finally solved my problem by simple iterating over file system (I have maildir format).

I guess Java Mail API makes new dovecot auth for each user in store.connect while it should just connect once (consume dovecot auth) and after that login for each user (consume dovecot imap-login). That's why I waited 1 minute for each iteration - it's std idle for auth process in dovecot config. I'm not sure but looks so.

Apache lib works fast but it's just testing library for pinging server, checking connection and other imap operations. It returns boolean result about operations but not useful information(