}
final MessageManager.MetaData metaData = selectMailbox(fullMailboxPath, session);
final SelectedMailbox selected = session.getSelected();
Long firstUnseen = metaData.getFirstUnseen();
flags(responder, selected);
exists(responder, metaData);
recent(responder, selected);
uidValidity(responder, metaData);
// try to write the UNSEEN message to the client and retry if we fail because of concurrent sessions.
//
// See IMAP-345
int retryCount = 0;
while(unseen(responder, firstUnseen, selected, ImapSessionUtils.getMailboxSession(session)) == false) {
// if we not was able to get find the unseen within 5 retries we should just not send it
if (retryCount == 5) {
if (session.getLog().isInfoEnabled()) {
session.getLog().info("Unable to uid for unseen message " + firstUnseen + " in mailbox " + selected.getPath());
}
break;
}
firstUnseen = selectMailbox(fullMailboxPath, session).getFirstUnseen();
retryCount++;
}
permanentFlags(responder, metaData, selected);
highestModSeq(responder, metaData, selected);
uidNext(responder, metaData);
if (request.getCondstore()) {
condstoreEnablingCommand(session, responder, metaData, false);
}
// Now do the QRESYNC processing if necessary
//
// If the mailbox does not store the mod-sequence in a permanent way its needed to not process the QRESYNC paramters
// The same is true if none are given ;)
if (metaData.isModSeqPermanent() && lastKnownUidValidity != null) {
if (lastKnownUidValidity == metaData.getUidValidity()) {
final MailboxManager mailboxManager = getMailboxManager();
final MailboxSession mailboxSession = ImapSessionUtils.getMailboxSession(session);
final MessageManager mailbox = mailboxManager.getMailbox(fullMailboxPath, mailboxSession);
// If the provided UIDVALIDITY matches that of the selected mailbox, the
// server then checks the last known modification sequence.
//
// The server sends the client any pending flag changes (using FETCH
// responses that MUST contain UIDs) and expunges those that have
// occurred in this mailbox since the provided modification sequence.
SearchQuery sq = new SearchQuery();
sq.andCriteria(SearchQuery.modSeqGreaterThan(request.getKnownModSeq()));
IdRange[] uidSet = request.getUidSet();
if (uidSet == null) {
// See mailbox had some messages stored before, if not we don't need to query at all
long uidNext = metaData.getUidNext();
if ( uidNext != 1) {
// Use UIDNEXT -1 as max uid as stated in the QRESYNC RFC
uidSet = new IdRange[] {new IdRange(1, uidNext -1)};
}
}
if (uidSet != null) {
// RFC5162 3.1. QRESYNC Parameter to SELECT/EXAMINE
//
// Message sequence match data:
//
// A client MAY provide a parenthesized list of a message sequence set
// and the corresponding UID sets. Both MUST be provided in ascending
// order. The server uses this data to restrict the range for which it
// provides expunged message information.
//
//
// Conceptually, the client provides a small sample of sequence numbers
// for which it knows the corresponding UIDs. The server then compares
// each sequence number and UID pair the client provides with the
// current state of the mailbox. If a pair matches, then the client
// knows of any expunges up to, and including, the message, and thus
// will not include that range in the VANISHED response, even if the
// "mod-sequence-value" provided by the client is too old for the server
// to have data of when those messages were expunged.
//
// Thus, if the Nth message number in the first set in the list is 4,
// and the Nth UID in the second set in the list is 8, and the mailbox's
// fourth message has UID 8, then no UIDs equal to or less than 8 are
// present in the VANISHED response. If the (N+1)th message number is
// 12, and the (N+1)th UID is 24, and the (N+1)th message in the mailbox
// has UID 25, then the lowest UID included in the VANISHED response
// would be 9.
if (knownSequences != null && knownUids != null) {
// Add all uids which are contained in the knownuidsset to a List so we can later access them via the index
List<Long> knownUidsList = new ArrayList<Long>();
for (int a = 0; a < knownUids.length; a++) {
Iterator<Long> it = knownUids[a].iterator();
while(it.hasNext()) {
knownUidsList.add(it.next());
}
}
// loop over the known sequences and check the UID for MSN X again the known UID X
long firstUid = 1;
int index = 0;
for (int a = 0; a < knownSequences.length; a++) {
boolean done = false;
Iterator<Long> it = knownSequences[a].iterator();
while(it.hasNext()) {
// Check if we have uids left to check against
if (knownUidsList.size() > index++) {
int msn = it.next().intValue();
long knownUid = knownUidsList.get(index);
// Check if the uid mathc if not we are done here
if (selected.uid(msn) != knownUid) {
done = true;
break;
} else {
firstUid = knownUid;
}