IMAP: brand new IMAP uid workaround and refresh folder on Expunge from Gellule

git-svn-id: http://svn.code.sf.net/p/davmail/code/trunk@924 3d1905a2-6b24-0410-a738-b14d5a86fcbd
This commit is contained in:
mguessan 2010-01-21 10:49:23 +00:00
parent 6ef09d6297
commit 9ebdf91c81
3 changed files with 72 additions and 29 deletions

View File

@ -1156,8 +1156,6 @@ public class ExchangeSession {
currentFolder.noInferiors = newFolder.noInferiors;
currentFolder.unreadCount = newFolder.unreadCount;
currentFolder.contenttag = newFolder.contenttag;
// keep previous messages for Thunderbird workaround
currentFolder.previousMessages = currentFolder.messages;
currentFolder.loadMessages();
return true;
} else {
@ -1204,7 +1202,7 @@ public class ExchangeSession {
}
};
int status = DavGatewayHttpClientFacade.executeHttpMethod(httpClient, method);
// ok or alredy exists
// ok or already exists
if (status != HttpStatus.SC_MULTI_STATUS && status != HttpStatus.SC_METHOD_NOT_ALLOWED) {
throw DavGatewayHttpClientFacade.buildHttpException(method);
}
@ -1318,10 +1316,10 @@ public class ExchangeSession {
*/
public ExchangeSession.MessageList messages;
/**
* Previous folder message list before refresh.
* PermanentURL to UID map.
*/
public ExchangeSession.MessageList previousMessages;
private final HashMap<String, Long> uidUrlHashMap = new HashMap<String, Long>();
/**
* Get IMAP folder flags.
*
@ -1343,7 +1341,46 @@ public class ExchangeSession {
* @throws IOException on error
*/
public void loadMessages() throws IOException {
messages = searchMessages(folderPath, "");
messages = ExchangeSession.this.searchMessages(folderPath, "");
fixUids(messages);
}
/**
* Search messages in folder matching query.
*
* @param query search query
* @return message list
* @throws IOException on error
*/
public MessageList searchMessages(String query) throws IOException {
MessageList localMessages = ExchangeSession.this.searchMessages(folderName, query);
fixUids(localMessages);
return localMessages;
}
/**
* Restore previous uids changed by a PROPPATCH (flag change).
*
* @param messages message list
*/
protected void fixUids(MessageList messages) {
boolean sortNeeded = false;
for (Message message : messages) {
if (uidUrlHashMap.containsKey(message.getPermanentUrl())) {
long previousUid = uidUrlHashMap.get(message.getPermanentUrl());
if (message.getImapUid() != previousUid) {
LOGGER.debug("Restoring IMAP uid " + message.getImapUid() + " -> " + previousUid + " for message " + message.getPermanentUrl() + " (" + message.messageUrl + ')');
message.setImapUid(previousUid);
sortNeeded = true;
}
} else {
// add message to uid map
uidUrlHashMap.put(message.getPermanentUrl(), message.getImapUid());
}
}
if (sortNeeded) {
Collections.sort(messages);
}
}
/**
@ -1446,6 +1483,14 @@ public class ExchangeSession {
return imapUid;
}
/**
* Set IMAP uid.
* @param imapUid new uid
*/
public void setImapUid(long imapUid) {
this.imapUid = imapUid;
}
/**
* Exchange uid.
*
@ -1459,9 +1504,8 @@ public class ExchangeSession {
* Return permanent message url.
*
* @return permanent message url
* @throws URIException on error
*/
public String getPermanentUrl() throws URIException {
public String getPermanentUrl() {
return permanentUrl;
}
@ -2222,10 +2266,10 @@ public class ExchangeSession {
|| line.indexOf("RSVP=TRUE") >= 0
|| line.indexOf("PARTSTAT=NEEDS-ACTION") >= 0
// need to include other PARTSTATs participants for CANCEL notifications
|| line.indexOf("PARTSTAT=ACCEPTED") >=0
|| line.indexOf("PARTSTAT=DECLINED") >=0
|| line.indexOf("PARTSTAT=TENTATIVE") >=0
)) {
|| line.indexOf("PARTSTAT=ACCEPTED") >= 0
|| line.indexOf("PARTSTAT=DECLINED") >= 0
|| line.indexOf("PARTSTAT=TENTATIVE") >= 0
)) {
if (line.indexOf("ROLE=OPT-PARTICIPANT") >= 0) {
optionalAttendees.add(value);
} else {

View File

@ -209,8 +209,15 @@ public class ImapConnection extends AbstractConnection {
} else {
sendClient(commandId + " BAD command unrecognized");
}
} else if ("close".equalsIgnoreCase(command) || "expunge".equalsIgnoreCase(command)) {
expunge("close".equalsIgnoreCase(command));
} else if ("expunge".equalsIgnoreCase(command)) {
expunge(false);
// need to refresh folder to avoid 404 errors
session.refreshFolder(currentFolder);
sendClient(commandId + " OK " + command + " completed");
} else if ("close".equalsIgnoreCase(command)) {
expunge(true);
// deselect folder
currentFolder = null;
sendClient(commandId + " OK " + command + " completed");
} else if ("create".equalsIgnoreCase(command)) {
if (tokens.hasMoreTokens()) {
@ -252,7 +259,7 @@ public class ImapConnection extends AbstractConnection {
if (tokens.hasMoreTokens()) {
parameters = tokens.nextToken();
}
UIDRangeIterator uidRangeIterator = getUIDRangeIterator(currentFolder, ranges);
UIDRangeIterator uidRangeIterator = new UIDRangeIterator(currentFolder.messages, ranges);
while (uidRangeIterator.hasNext()) {
DavGatewayTray.switchIcon();
ExchangeSession.Message message = uidRangeIterator.next();
@ -275,13 +282,13 @@ public class ImapConnection extends AbstractConnection {
sendClient(commandId + " OK SEARCH completed");
} else if ("store".equalsIgnoreCase(subcommand)) {
UIDRangeIterator uidRangeIterator = getUIDRangeIterator(currentFolder, tokens.nextToken());
UIDRangeIterator uidRangeIterator = new UIDRangeIterator(currentFolder.messages, tokens.nextToken());
String action = tokens.nextToken();
String flags = tokens.nextToken();
handleStore(commandId, uidRangeIterator, action, flags);
} else if ("copy".equalsIgnoreCase(subcommand)) {
try {
UIDRangeIterator uidRangeIterator = getUIDRangeIterator(currentFolder, tokens.nextToken());
UIDRangeIterator uidRangeIterator = new UIDRangeIterator(currentFolder.messages, tokens.nextToken());
String targetName = BASE64MailboxDecoder.decode(tokens.nextToken());
while (uidRangeIterator.hasNext()) {
DavGatewayTray.switchIcon();
@ -648,7 +655,7 @@ public class ImapConnection extends AbstractConnection {
if ("AND ()".equals(query)) {
query = null;
}
ExchangeSession.MessageList localMessages = session.searchMessages(currentFolder.folderName, query);
ExchangeSession.MessageList localMessages = currentFolder.searchMessages(query);
int index = 1;
for (ExchangeSession.Message message : localMessages) {
if ((conditions.deleted == null || message.deleted == conditions.deleted)
@ -1177,16 +1184,6 @@ public class ImapConnection extends AbstractConnection {
return result;
}
protected UIDRangeIterator getUIDRangeIterator(ExchangeSession.Folder folder, String ranges) {
UIDRangeIterator uidRangeIterator = new UIDRangeIterator(folder.messages, ranges);
if (!uidRangeIterator.hasNext() && folder.previousMessages != null) {
// message not found in current list, try to get message
// from previous list to handle recent uid change
uidRangeIterator = new UIDRangeIterator(folder.previousMessages, ranges);
}
return uidRangeIterator;
}
/**
* Filter to output only headers, also count full size
*/

View File

@ -11,3 +11,5 @@ log4j.appender.ConsoleAppender=org.apache.log4j.ConsoleAppender
log4j.appender.ConsoleAppender.layout=org.apache.log4j.PatternLayout
log4j.appender.ConsoleAppender.layout.ConversionPattern=%d{ISO8601} %-5p [%t] %c %x - %m%n
#log4j.logger.org.apache.commons.httpclient.util.IdleConnectionHandler=DEBUG
#log4j.logger.org.apache.commons.httpclient.util.MultiThreadedHttpConnectionManager=DEBUG