2011-01-18 4 views
7

У меня есть приложение, которое используется для архивирования электронной почты с помощью imap. Также в этом приложении много учетных записей IMAP, которые необходимо архивировать.Как скачать только новые письма от imap?

В этот момент время от времени приложение подключается к учетным записям imap и загружает только новые письма. Моя проблема в том, что каждый раз, когда он подключается к учетной записи imap, он проверяет все электронные письма из всех папок и загружает только электронные письма, которые еще не загружены (я сохраняю Message-ID для всех электронных писем и загружаю только электронные письма с идентификатором сообщения, не сохраняется). Так что я хочу знать, есть ли альтернатива для этого, потому что для проверки всех писем требуется некоторое время (для 10-20K это занимает 2-5 минут).

Я использую API JavaMail для подключения к учетным записям imap.

ответ

6

javadoc помогает:

IMAPFolder предоставляет методы:

getMessagesByUID (длинный старт, длинный конец) и

getUID (сообщение Message)

С getUID() вы можете получить UID последнего сообщения, которое вы уже загрузили. С помощью getMessagesByUID вы можете определить это последнее сообщение, которое вы загрузили в качестве начального диапазона, и посмотрите с помощью метода getUIDNext(), чтобы найти последнее сообщение, которое будет концом диапазона.

+0

Это не решение для меня, потому что UID меняются со временем, поэтому я использую Message-ID для отслеживания загруженных писем. – telebog

+0

как я понимаю getUID (Message message) -method, вы можете получить фактический MessageUID для данного сообщения с сервера. Таким образом, можно было бы получить фактический UID последнего сообщения, которое у вас есть, а затем использовать методы getUIDNext() и getMessagesByUID(), чтобы найти последнее сообщение и загрузить заданный диапазон. – Erik

+2

UID сообщения будет изменяться, когда сообщение будет перемещено из одной папки (или «почтового ящика» в терминологии IMAP) в другую. [«Уникальные идентификаторы назначаются строго по возрастанию в почтовом ящике, так как каждое сообщение добавляется в почтовый ящик, ему назначается более высокий UID, чем сообщения, которые были добавлены ранее».] (Http: //tools.ietf .org/html/rfc3501 # section-2.3.1.1), похоже, что телешоп хочет загружать каждое сообщение ровно один раз, независимо от того, в какой папке он находится. – dkarp

3

проверка только заголовки и когда вы достигнете известного (последней известного), выручать:

, например (я чувствую дополнительным приятно сегодня), и это исключение из реального кода производства (некоторые детали были вырезаны, поэтому он не может скомпилировать, state.processed некоторого множество предпочтительна LinkedHashMap суррогатный [Keyset()] (и ж/некоторую максимальной граничной булевой removeEldestEntry())

try { 
     store = mailSession.getStore("imap"); 
     try { 
     store.connect(); 
     Folder folder = store.getFolder("INBOX"); 
     folder.open(Folder.READ_ONLY); 

     int count = folder.getMessageCount(); 
     for(int localProc=0, chunk=49;localProc<10 && count>0; count -=chunk+1){ 


      Message messages[] = folder.getMessages(Math.max(count-chunk, 1), count); 

      FetchProfile fp = new FetchProfile(); 
      fp.add(FetchProfile.Item.ENVELOPE); 
      fp.add("Message-ID"); 
//add more headers, if need be 
      folder.fetch(messages,fp); 

      for (int i=messages.length;--i>=0;) { 

      //can check abort request here 
      Message message = messages[i]; 


      String msgId = getHeader(message,"Message-ID"); 
      if (msgId!=null && !state.processed.add(msgId)){    
       if (++localProc>=10){ 
       break; 
       } 
       continue; 
      } 
///process here, catch exception, etc.. 
      } 
     } 

     folder.close(false);   
     } catch (MessagingException e) { 
     logger.log(Level.SEVERE, "Mail messaging exception", e); 
     } 
    } catch (NoSuchProviderException e) { 
     logger.log(Level.SEVERE, "No mail provider", e); 
    } 

    if(store != null) { 
     try { 
     store.close(); 
     } catch (MessagingException e) {} 
    } 
+0

Это немного рискованно, так как большой ход известных сообщений поверх множества новых сообщений заставит вас пропустить новые. – dkarp

+0

верно, что это хороший момент; код предназначен для чтения неудачных писем, поэтому я думаю, что это никогда не было проблемой, сама. Код должен содержать, по крайней мере, предыдущий счетчик и пытаться восстановить по крайней мере столько сообщений. – bestsss

1

фильтра на SEEN флага. Этот флаг предназначен для поиск новых сообщений. Одно из предостережений заключается в том, что если ваш пользователь использует несколько считывателей, возможно, это было видно с помощью другого читателя.

+1

Вы имеете в виду флаг "RECENT". И да, любое подключение другого клиента к этой папке отключит «ПОСЛЕДНИЕ» во всех сообщениях в папке. – dkarp

+0

Я видел, что это задокументировано как SEEN, но это может быть НЕДАВНО в вашей реализации. IMAP отслеживает сообщения, которые еще не были прочитаны клиентом. Для интерфейса считывателя я ожидал бы, что все, что я прочитал, с любым клиентом, который будет помечен как прочитанный в моем интерфейсе. Мой опыт в этом случае заключается в администрировании сервера, а не в программировании клиента. – BillThor

+0

Флаг Seen - стандартный флаг. Java автоматически укажет сообщение, как видно, когда оно будет восстановлено. Это поведение, которое я ожидаю от всех клиентов. Можно очистить флаг. – BillThor

0

message-Id, который приходит как часть заголовка, всегда уникален, даже если u задал его вручную. Я протестировал его с помощью gamil и racksoace.

+0

Но это не требуется и просто нет вообще отсутствующего. В Gmail тоже. – Hubbitus

Смежные вопросы