@Test public void fetch_withNullMessageListArgument_shouldDoNothing() throws Exception { ImapFolder folder = createFolder("Folder"); FetchProfile fetchProfile = createFetchProfile(); folder.fetch(null, fetchProfile, null); verifyNoMoreInteractions(imapConnection); }
@Override public void fetch(List<ImapMessage> messages, FetchProfile fetchProfile, MessageRetrievalListener<ImapMessage> listener) throws MessagingException { if (messages == null || messages.isEmpty()) { return; } checkOpen(); List<String> uids = new ArrayList<>(messages.size()); HashMap<String, Message> messageMap = new HashMap<>(); for (Message message : messages) { String uid = message.getUid(); uids.add(uid); messageMap.put(uid, message); } Set<String> fetchFields = new LinkedHashSet<>(); fetchFields.add("UID"); if (fetchProfile.contains(FetchProfile.Item.FLAGS)) { fetchFields.add("FLAGS"); } if (fetchProfile.contains(FetchProfile.Item.ENVELOPE)) { fetchFields.add("INTERNALDATE"); fetchFields.add("RFC822.SIZE"); fetchFields.add("BODY.PEEK[HEADER.FIELDS (date subject from content-type to cc " + "reply-to message-id references in-reply-to " + K9MailLib.IDENTITY_HEADER + ")]"); } if (fetchProfile.contains(FetchProfile.Item.STRUCTURE)) { fetchFields.add("BODYSTRUCTURE"); } if (fetchProfile.contains(FetchProfile.Item.BODY_SANE)) { int maximumAutoDownloadMessageSize = store.getStoreConfig().getMaximumAutoDownloadMessageSize(); if (maximumAutoDownloadMessageSize > 0) { fetchFields.add(String.format(Locale.US, "BODY.PEEK[]<0.%d>", maximumAutoDownloadMessageSize)); } else { fetchFields.add("BODY.PEEK[]"); } } if (fetchProfile.contains(FetchProfile.Item.BODY)) { fetchFields.add("BODY.PEEK[]"); } String spaceSeparatedFetchFields = combine(fetchFields.toArray(new String[fetchFields.size()]), ' '); for (int windowStart = 0; windowStart < messages.size(); windowStart += (FETCH_WINDOW_SIZE)) { int windowEnd = Math.min(windowStart + FETCH_WINDOW_SIZE, messages.size()); List<String> uidWindow = uids.subList(windowStart, windowEnd); try { String commaSeparatedUids = combine(uidWindow.toArray(new String[uidWindow.size()]), ','); String command = String.format("UID FETCH %s (%s)", commaSeparatedUids, spaceSeparatedFetchFields); connection.sendCommand(command, false); ImapResponse response; int messageNumber = 0; ImapResponseCallback callback = null; if (fetchProfile.contains(FetchProfile.Item.BODY) || fetchProfile.contains(FetchProfile.Item.BODY_SANE)) { callback = new FetchBodyCallback(messageMap); } do { response = connection.readResponse(callback); if (response.getTag() == null && ImapResponseParser.equalsIgnoreCase(response.get(1), "FETCH")) { ImapList fetchList = (ImapList) response.getKeyedValue("FETCH"); String uid = fetchList.getKeyedString("UID"); long msgSeq = response.getLong(0); if (uid != null) { try { msgSeqUidMap.put(msgSeq, uid); if (K9MailLib.isDebug()) { Timber.v("Stored uid '%s' for msgSeq %d into map", uid, msgSeq); } } catch (Exception e) { Timber.e("Unable to store uid '%s' for msgSeq %d", uid, msgSeq); } } Message message = messageMap.get(uid); if (message == null) { if (K9MailLib.isDebug()) { Timber.d("Do not have message in messageMap for UID %s for %s", uid, getLogId()); } handleUntaggedResponse(response); continue; } if (listener != null) { listener.messageStarted(uid, messageNumber++, messageMap.size()); } ImapMessage imapMessage = (ImapMessage) message; Object literal = handleFetchResponse(imapMessage, fetchList); if (literal != null) { if (literal instanceof String) { String bodyString = (String) literal; InputStream bodyStream = new ByteArrayInputStream(bodyString.getBytes()); imapMessage.parse(bodyStream); } else if (literal instanceof Integer) { } else { throw new MessagingException("Got FETCH response with bogus parameters"); } } if (listener != null) { listener.messageFinished(imapMessage, messageNumber, messageMap.size()); } } else { handleUntaggedResponse(response); } } while (response.getTag() == null); } catch (IOException ioe) { throw ioExceptionHandler(connection, ioe); } } }
ImapFolder extends Folder<ImapMessage> { @Override public void fetch(List<ImapMessage> messages, FetchProfile fetchProfile, MessageRetrievalListener<ImapMessage> listener) throws MessagingException { if (messages == null || messages.isEmpty()) { return; } checkOpen(); List<String> uids = new ArrayList<>(messages.size()); HashMap<String, Message> messageMap = new HashMap<>(); for (Message message : messages) { String uid = message.getUid(); uids.add(uid); messageMap.put(uid, message); } Set<String> fetchFields = new LinkedHashSet<>(); fetchFields.add("UID"); if (fetchProfile.contains(FetchProfile.Item.FLAGS)) { fetchFields.add("FLAGS"); } if (fetchProfile.contains(FetchProfile.Item.ENVELOPE)) { fetchFields.add("INTERNALDATE"); fetchFields.add("RFC822.SIZE"); fetchFields.add("BODY.PEEK[HEADER.FIELDS (date subject from content-type to cc " + "reply-to message-id references in-reply-to " + K9MailLib.IDENTITY_HEADER + ")]"); } if (fetchProfile.contains(FetchProfile.Item.STRUCTURE)) { fetchFields.add("BODYSTRUCTURE"); } if (fetchProfile.contains(FetchProfile.Item.BODY_SANE)) { int maximumAutoDownloadMessageSize = store.getStoreConfig().getMaximumAutoDownloadMessageSize(); if (maximumAutoDownloadMessageSize > 0) { fetchFields.add(String.format(Locale.US, "BODY.PEEK[]<0.%d>", maximumAutoDownloadMessageSize)); } else { fetchFields.add("BODY.PEEK[]"); } } if (fetchProfile.contains(FetchProfile.Item.BODY)) { fetchFields.add("BODY.PEEK[]"); } String spaceSeparatedFetchFields = combine(fetchFields.toArray(new String[fetchFields.size()]), ' '); for (int windowStart = 0; windowStart < messages.size(); windowStart += (FETCH_WINDOW_SIZE)) { int windowEnd = Math.min(windowStart + FETCH_WINDOW_SIZE, messages.size()); List<String> uidWindow = uids.subList(windowStart, windowEnd); try { String commaSeparatedUids = combine(uidWindow.toArray(new String[uidWindow.size()]), ','); String command = String.format("UID FETCH %s (%s)", commaSeparatedUids, spaceSeparatedFetchFields); connection.sendCommand(command, false); ImapResponse response; int messageNumber = 0; ImapResponseCallback callback = null; if (fetchProfile.contains(FetchProfile.Item.BODY) || fetchProfile.contains(FetchProfile.Item.BODY_SANE)) { callback = new FetchBodyCallback(messageMap); } do { response = connection.readResponse(callback); if (response.getTag() == null && ImapResponseParser.equalsIgnoreCase(response.get(1), "FETCH")) { ImapList fetchList = (ImapList) response.getKeyedValue("FETCH"); String uid = fetchList.getKeyedString("UID"); long msgSeq = response.getLong(0); if (uid != null) { try { msgSeqUidMap.put(msgSeq, uid); if (K9MailLib.isDebug()) { Timber.v("Stored uid '%s' for msgSeq %d into map", uid, msgSeq); } } catch (Exception e) { Timber.e("Unable to store uid '%s' for msgSeq %d", uid, msgSeq); } } Message message = messageMap.get(uid); if (message == null) { if (K9MailLib.isDebug()) { Timber.d("Do not have message in messageMap for UID %s for %s", uid, getLogId()); } handleUntaggedResponse(response); continue; } if (listener != null) { listener.messageStarted(uid, messageNumber++, messageMap.size()); } ImapMessage imapMessage = (ImapMessage) message; Object literal = handleFetchResponse(imapMessage, fetchList); if (literal != null) { if (literal instanceof String) { String bodyString = (String) literal; InputStream bodyStream = new ByteArrayInputStream(bodyString.getBytes()); imapMessage.parse(bodyStream); } else if (literal instanceof Integer) { } else { throw new MessagingException("Got FETCH response with bogus parameters"); } } if (listener != null) { listener.messageFinished(imapMessage, messageNumber, messageMap.size()); } } else { handleUntaggedResponse(response); } } while (response.getTag() == null); } catch (IOException ioe) { throw ioExceptionHandler(connection, ioe); } } } }
ImapFolder extends Folder<ImapMessage> { @Override public void fetch(List<ImapMessage> messages, FetchProfile fetchProfile, MessageRetrievalListener<ImapMessage> listener) throws MessagingException { if (messages == null || messages.isEmpty()) { return; } checkOpen(); List<String> uids = new ArrayList<>(messages.size()); HashMap<String, Message> messageMap = new HashMap<>(); for (Message message : messages) { String uid = message.getUid(); uids.add(uid); messageMap.put(uid, message); } Set<String> fetchFields = new LinkedHashSet<>(); fetchFields.add("UID"); if (fetchProfile.contains(FetchProfile.Item.FLAGS)) { fetchFields.add("FLAGS"); } if (fetchProfile.contains(FetchProfile.Item.ENVELOPE)) { fetchFields.add("INTERNALDATE"); fetchFields.add("RFC822.SIZE"); fetchFields.add("BODY.PEEK[HEADER.FIELDS (date subject from content-type to cc " + "reply-to message-id references in-reply-to " + K9MailLib.IDENTITY_HEADER + ")]"); } if (fetchProfile.contains(FetchProfile.Item.STRUCTURE)) { fetchFields.add("BODYSTRUCTURE"); } if (fetchProfile.contains(FetchProfile.Item.BODY_SANE)) { int maximumAutoDownloadMessageSize = store.getStoreConfig().getMaximumAutoDownloadMessageSize(); if (maximumAutoDownloadMessageSize > 0) { fetchFields.add(String.format(Locale.US, "BODY.PEEK[]<0.%d>", maximumAutoDownloadMessageSize)); } else { fetchFields.add("BODY.PEEK[]"); } } if (fetchProfile.contains(FetchProfile.Item.BODY)) { fetchFields.add("BODY.PEEK[]"); } String spaceSeparatedFetchFields = combine(fetchFields.toArray(new String[fetchFields.size()]), ' '); for (int windowStart = 0; windowStart < messages.size(); windowStart += (FETCH_WINDOW_SIZE)) { int windowEnd = Math.min(windowStart + FETCH_WINDOW_SIZE, messages.size()); List<String> uidWindow = uids.subList(windowStart, windowEnd); try { String commaSeparatedUids = combine(uidWindow.toArray(new String[uidWindow.size()]), ','); String command = String.format("UID FETCH %s (%s)", commaSeparatedUids, spaceSeparatedFetchFields); connection.sendCommand(command, false); ImapResponse response; int messageNumber = 0; ImapResponseCallback callback = null; if (fetchProfile.contains(FetchProfile.Item.BODY) || fetchProfile.contains(FetchProfile.Item.BODY_SANE)) { callback = new FetchBodyCallback(messageMap); } do { response = connection.readResponse(callback); if (response.getTag() == null && ImapResponseParser.equalsIgnoreCase(response.get(1), "FETCH")) { ImapList fetchList = (ImapList) response.getKeyedValue("FETCH"); String uid = fetchList.getKeyedString("UID"); long msgSeq = response.getLong(0); if (uid != null) { try { msgSeqUidMap.put(msgSeq, uid); if (K9MailLib.isDebug()) { Timber.v("Stored uid '%s' for msgSeq %d into map", uid, msgSeq); } } catch (Exception e) { Timber.e("Unable to store uid '%s' for msgSeq %d", uid, msgSeq); } } Message message = messageMap.get(uid); if (message == null) { if (K9MailLib.isDebug()) { Timber.d("Do not have message in messageMap for UID %s for %s", uid, getLogId()); } handleUntaggedResponse(response); continue; } if (listener != null) { listener.messageStarted(uid, messageNumber++, messageMap.size()); } ImapMessage imapMessage = (ImapMessage) message; Object literal = handleFetchResponse(imapMessage, fetchList); if (literal != null) { if (literal instanceof String) { String bodyString = (String) literal; InputStream bodyStream = new ByteArrayInputStream(bodyString.getBytes()); imapMessage.parse(bodyStream); } else if (literal instanceof Integer) { } else { throw new MessagingException("Got FETCH response with bogus parameters"); } } if (listener != null) { listener.messageFinished(imapMessage, messageNumber, messageMap.size()); } } else { handleUntaggedResponse(response); } } while (response.getTag() == null); } catch (IOException ioe) { throw ioExceptionHandler(connection, ioe); } } } ImapFolder(ImapStore store, String id);   ImapFolder(ImapStore store, String id, FolderNameCodec folderNameCodec); }
ImapFolder extends Folder<ImapMessage> { @Override public void fetch(List<ImapMessage> messages, FetchProfile fetchProfile, MessageRetrievalListener<ImapMessage> listener) throws MessagingException { if (messages == null || messages.isEmpty()) { return; } checkOpen(); List<String> uids = new ArrayList<>(messages.size()); HashMap<String, Message> messageMap = new HashMap<>(); for (Message message : messages) { String uid = message.getUid(); uids.add(uid); messageMap.put(uid, message); } Set<String> fetchFields = new LinkedHashSet<>(); fetchFields.add("UID"); if (fetchProfile.contains(FetchProfile.Item.FLAGS)) { fetchFields.add("FLAGS"); } if (fetchProfile.contains(FetchProfile.Item.ENVELOPE)) { fetchFields.add("INTERNALDATE"); fetchFields.add("RFC822.SIZE"); fetchFields.add("BODY.PEEK[HEADER.FIELDS (date subject from content-type to cc " + "reply-to message-id references in-reply-to " + K9MailLib.IDENTITY_HEADER + ")]"); } if (fetchProfile.contains(FetchProfile.Item.STRUCTURE)) { fetchFields.add("BODYSTRUCTURE"); } if (fetchProfile.contains(FetchProfile.Item.BODY_SANE)) { int maximumAutoDownloadMessageSize = store.getStoreConfig().getMaximumAutoDownloadMessageSize(); if (maximumAutoDownloadMessageSize > 0) { fetchFields.add(String.format(Locale.US, "BODY.PEEK[]<0.%d>", maximumAutoDownloadMessageSize)); } else { fetchFields.add("BODY.PEEK[]"); } } if (fetchProfile.contains(FetchProfile.Item.BODY)) { fetchFields.add("BODY.PEEK[]"); } String spaceSeparatedFetchFields = combine(fetchFields.toArray(new String[fetchFields.size()]), ' '); for (int windowStart = 0; windowStart < messages.size(); windowStart += (FETCH_WINDOW_SIZE)) { int windowEnd = Math.min(windowStart + FETCH_WINDOW_SIZE, messages.size()); List<String> uidWindow = uids.subList(windowStart, windowEnd); try { String commaSeparatedUids = combine(uidWindow.toArray(new String[uidWindow.size()]), ','); String command = String.format("UID FETCH %s (%s)", commaSeparatedUids, spaceSeparatedFetchFields); connection.sendCommand(command, false); ImapResponse response; int messageNumber = 0; ImapResponseCallback callback = null; if (fetchProfile.contains(FetchProfile.Item.BODY) || fetchProfile.contains(FetchProfile.Item.BODY_SANE)) { callback = new FetchBodyCallback(messageMap); } do { response = connection.readResponse(callback); if (response.getTag() == null && ImapResponseParser.equalsIgnoreCase(response.get(1), "FETCH")) { ImapList fetchList = (ImapList) response.getKeyedValue("FETCH"); String uid = fetchList.getKeyedString("UID"); long msgSeq = response.getLong(0); if (uid != null) { try { msgSeqUidMap.put(msgSeq, uid); if (K9MailLib.isDebug()) { Timber.v("Stored uid '%s' for msgSeq %d into map", uid, msgSeq); } } catch (Exception e) { Timber.e("Unable to store uid '%s' for msgSeq %d", uid, msgSeq); } } Message message = messageMap.get(uid); if (message == null) { if (K9MailLib.isDebug()) { Timber.d("Do not have message in messageMap for UID %s for %s", uid, getLogId()); } handleUntaggedResponse(response); continue; } if (listener != null) { listener.messageStarted(uid, messageNumber++, messageMap.size()); } ImapMessage imapMessage = (ImapMessage) message; Object literal = handleFetchResponse(imapMessage, fetchList); if (literal != null) { if (literal instanceof String) { String bodyString = (String) literal; InputStream bodyStream = new ByteArrayInputStream(bodyString.getBytes()); imapMessage.parse(bodyStream); } else if (literal instanceof Integer) { } else { throw new MessagingException("Got FETCH response with bogus parameters"); } } if (listener != null) { listener.messageFinished(imapMessage, messageNumber, messageMap.size()); } } else { handleUntaggedResponse(response); } } while (response.getTag() == null); } catch (IOException ioe) { throw ioExceptionHandler(connection, ioe); } } } ImapFolder(ImapStore store, String id);   ImapFolder(ImapStore store, String id, FolderNameCodec folderNameCodec); @Override void open(int mode); @Override boolean isOpen(); @Override int getMode(); @Override void close(); @Override String getId(); @Override String getParentId(); @Override String getName(); @Override boolean exists(); @Override boolean canHaveSubFolders(); @Override boolean create(FolderType type); @Override Map<String, String> copyMessages(List<? extends Message> messages, Folder folder); @Override Map<String, String> moveMessages(List<? extends Message> messages, Folder folder); @Override void delete(List<? extends Message> messages, String trashFolderName); @Override int getMessageCount(); @Override int getUnreadMessageCount(); @Override int getFlaggedMessageCount(); @Override void delete(boolean recurse); @Override ImapMessage getMessage(String uid); @Override List<ImapMessage> getMessages(int start, int end, Date earliestDate,
            MessageRetrievalListener<ImapMessage> listener); @Override boolean areMoreMessagesAvailable(int indexOfOldestMessage, Date earliestDate); @Override void fetch(List<ImapMessage> messages, FetchProfile fetchProfile,
            MessageRetrievalListener<ImapMessage> listener); @Override void fetchPart(Message message, Part part, MessageRetrievalListener<Message> listener,
            BodyFactory bodyFactory); @Override Map<String, String> appendMessages(List<? extends Message> messages); @Override String getUidFromMessageId(Message message); @Override void expunge(); @Override void setFlags(Set<Flag> flags, boolean value); @Override String getNewPushState(String oldSerializedPushState, Message message); @Override void setFlags(List<? extends Message> messages, final Set<Flag> flags, boolean value); @Override boolean equals(Object other); @Override int hashCode(); @Override List<ImapMessage> search(final String queryString, final Set<Flag> requiredFlags,
            final Set<Flag> forbiddenFlags); }
ImapFolder extends Folder<ImapMessage> { @Override public void fetch(List<ImapMessage> messages, FetchProfile fetchProfile, MessageRetrievalListener<ImapMessage> listener) throws MessagingException { if (messages == null || messages.isEmpty()) { return; } checkOpen(); List<String> uids = new ArrayList<>(messages.size()); HashMap<String, Message> messageMap = new HashMap<>(); for (Message message : messages) { String uid = message.getUid(); uids.add(uid); messageMap.put(uid, message); } Set<String> fetchFields = new LinkedHashSet<>(); fetchFields.add("UID"); if (fetchProfile.contains(FetchProfile.Item.FLAGS)) { fetchFields.add("FLAGS"); } if (fetchProfile.contains(FetchProfile.Item.ENVELOPE)) { fetchFields.add("INTERNALDATE"); fetchFields.add("RFC822.SIZE"); fetchFields.add("BODY.PEEK[HEADER.FIELDS (date subject from content-type to cc " + "reply-to message-id references in-reply-to " + K9MailLib.IDENTITY_HEADER + ")]"); } if (fetchProfile.contains(FetchProfile.Item.STRUCTURE)) { fetchFields.add("BODYSTRUCTURE"); } if (fetchProfile.contains(FetchProfile.Item.BODY_SANE)) { int maximumAutoDownloadMessageSize = store.getStoreConfig().getMaximumAutoDownloadMessageSize(); if (maximumAutoDownloadMessageSize > 0) { fetchFields.add(String.format(Locale.US, "BODY.PEEK[]<0.%d>", maximumAutoDownloadMessageSize)); } else { fetchFields.add("BODY.PEEK[]"); } } if (fetchProfile.contains(FetchProfile.Item.BODY)) { fetchFields.add("BODY.PEEK[]"); } String spaceSeparatedFetchFields = combine(fetchFields.toArray(new String[fetchFields.size()]), ' '); for (int windowStart = 0; windowStart < messages.size(); windowStart += (FETCH_WINDOW_SIZE)) { int windowEnd = Math.min(windowStart + FETCH_WINDOW_SIZE, messages.size()); List<String> uidWindow = uids.subList(windowStart, windowEnd); try { String commaSeparatedUids = combine(uidWindow.toArray(new String[uidWindow.size()]), ','); String command = String.format("UID FETCH %s (%s)", commaSeparatedUids, spaceSeparatedFetchFields); connection.sendCommand(command, false); ImapResponse response; int messageNumber = 0; ImapResponseCallback callback = null; if (fetchProfile.contains(FetchProfile.Item.BODY) || fetchProfile.contains(FetchProfile.Item.BODY_SANE)) { callback = new FetchBodyCallback(messageMap); } do { response = connection.readResponse(callback); if (response.getTag() == null && ImapResponseParser.equalsIgnoreCase(response.get(1), "FETCH")) { ImapList fetchList = (ImapList) response.getKeyedValue("FETCH"); String uid = fetchList.getKeyedString("UID"); long msgSeq = response.getLong(0); if (uid != null) { try { msgSeqUidMap.put(msgSeq, uid); if (K9MailLib.isDebug()) { Timber.v("Stored uid '%s' for msgSeq %d into map", uid, msgSeq); } } catch (Exception e) { Timber.e("Unable to store uid '%s' for msgSeq %d", uid, msgSeq); } } Message message = messageMap.get(uid); if (message == null) { if (K9MailLib.isDebug()) { Timber.d("Do not have message in messageMap for UID %s for %s", uid, getLogId()); } handleUntaggedResponse(response); continue; } if (listener != null) { listener.messageStarted(uid, messageNumber++, messageMap.size()); } ImapMessage imapMessage = (ImapMessage) message; Object literal = handleFetchResponse(imapMessage, fetchList); if (literal != null) { if (literal instanceof String) { String bodyString = (String) literal; InputStream bodyStream = new ByteArrayInputStream(bodyString.getBytes()); imapMessage.parse(bodyStream); } else if (literal instanceof Integer) { } else { throw new MessagingException("Got FETCH response with bogus parameters"); } } if (listener != null) { listener.messageFinished(imapMessage, messageNumber, messageMap.size()); } } else { handleUntaggedResponse(response); } } while (response.getTag() == null); } catch (IOException ioe) { throw ioExceptionHandler(connection, ioe); } } } ImapFolder(ImapStore store, String id);   ImapFolder(ImapStore store, String id, FolderNameCodec folderNameCodec); @Override void open(int mode); @Override boolean isOpen(); @Override int getMode(); @Override void close(); @Override String getId(); @Override String getParentId(); @Override String getName(); @Override boolean exists(); @Override boolean canHaveSubFolders(); @Override boolean create(FolderType type); @Override Map<String, String> copyMessages(List<? extends Message> messages, Folder folder); @Override Map<String, String> moveMessages(List<? extends Message> messages, Folder folder); @Override void delete(List<? extends Message> messages, String trashFolderName); @Override int getMessageCount(); @Override int getUnreadMessageCount(); @Override int getFlaggedMessageCount(); @Override void delete(boolean recurse); @Override ImapMessage getMessage(String uid); @Override List<ImapMessage> getMessages(int start, int end, Date earliestDate,
            MessageRetrievalListener<ImapMessage> listener); @Override boolean areMoreMessagesAvailable(int indexOfOldestMessage, Date earliestDate); @Override void fetch(List<ImapMessage> messages, FetchProfile fetchProfile,
            MessageRetrievalListener<ImapMessage> listener); @Override void fetchPart(Message message, Part part, MessageRetrievalListener<Message> listener,
            BodyFactory bodyFactory); @Override Map<String, String> appendMessages(List<? extends Message> messages); @Override String getUidFromMessageId(Message message); @Override void expunge(); @Override void setFlags(Set<Flag> flags, boolean value); @Override String getNewPushState(String oldSerializedPushState, Message message); @Override void setFlags(List<? extends Message> messages, final Set<Flag> flags, boolean value); @Override boolean equals(Object other); @Override int hashCode(); @Override List<ImapMessage> search(final String queryString, final Set<Flag> requiredFlags,
            final Set<Flag> forbiddenFlags);  }