1
0
mirror of https://github.com/moparisthebest/davmail synced 2024-12-14 11:42:23 -05:00

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.noInferiors = newFolder.noInferiors;
currentFolder.unreadCount = newFolder.unreadCount; currentFolder.unreadCount = newFolder.unreadCount;
currentFolder.contenttag = newFolder.contenttag; currentFolder.contenttag = newFolder.contenttag;
// keep previous messages for Thunderbird workaround
currentFolder.previousMessages = currentFolder.messages;
currentFolder.loadMessages(); currentFolder.loadMessages();
return true; return true;
} else { } else {
@ -1204,7 +1202,7 @@ public class ExchangeSession {
} }
}; };
int status = DavGatewayHttpClientFacade.executeHttpMethod(httpClient, method); 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) { if (status != HttpStatus.SC_MULTI_STATUS && status != HttpStatus.SC_METHOD_NOT_ALLOWED) {
throw DavGatewayHttpClientFacade.buildHttpException(method); throw DavGatewayHttpClientFacade.buildHttpException(method);
} }
@ -1318,9 +1316,9 @@ public class ExchangeSession {
*/ */
public ExchangeSession.MessageList messages; 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. * Get IMAP folder flags.
@ -1343,7 +1341,46 @@ public class ExchangeSession {
* @throws IOException on error * @throws IOException on error
*/ */
public void loadMessages() throws IOException { 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; return imapUid;
} }
/**
* Set IMAP uid.
* @param imapUid new uid
*/
public void setImapUid(long imapUid) {
this.imapUid = imapUid;
}
/** /**
* Exchange uid. * Exchange uid.
* *
@ -1459,9 +1504,8 @@ public class ExchangeSession {
* Return permanent message url. * Return permanent message url.
* *
* @return permanent message url * @return permanent message url
* @throws URIException on error
*/ */
public String getPermanentUrl() throws URIException { public String getPermanentUrl() {
return permanentUrl; return permanentUrl;
} }

View File

@ -209,8 +209,15 @@ public class ImapConnection extends AbstractConnection {
} else { } else {
sendClient(commandId + " BAD command unrecognized"); sendClient(commandId + " BAD command unrecognized");
} }
} else if ("close".equalsIgnoreCase(command) || "expunge".equalsIgnoreCase(command)) { } else if ("expunge".equalsIgnoreCase(command)) {
expunge("close".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"); sendClient(commandId + " OK " + command + " completed");
} else if ("create".equalsIgnoreCase(command)) { } else if ("create".equalsIgnoreCase(command)) {
if (tokens.hasMoreTokens()) { if (tokens.hasMoreTokens()) {
@ -252,7 +259,7 @@ public class ImapConnection extends AbstractConnection {
if (tokens.hasMoreTokens()) { if (tokens.hasMoreTokens()) {
parameters = tokens.nextToken(); parameters = tokens.nextToken();
} }
UIDRangeIterator uidRangeIterator = getUIDRangeIterator(currentFolder, ranges); UIDRangeIterator uidRangeIterator = new UIDRangeIterator(currentFolder.messages, ranges);
while (uidRangeIterator.hasNext()) { while (uidRangeIterator.hasNext()) {
DavGatewayTray.switchIcon(); DavGatewayTray.switchIcon();
ExchangeSession.Message message = uidRangeIterator.next(); ExchangeSession.Message message = uidRangeIterator.next();
@ -275,13 +282,13 @@ public class ImapConnection extends AbstractConnection {
sendClient(commandId + " OK SEARCH completed"); sendClient(commandId + " OK SEARCH completed");
} else if ("store".equalsIgnoreCase(subcommand)) { } else if ("store".equalsIgnoreCase(subcommand)) {
UIDRangeIterator uidRangeIterator = getUIDRangeIterator(currentFolder, tokens.nextToken()); UIDRangeIterator uidRangeIterator = new UIDRangeIterator(currentFolder.messages, tokens.nextToken());
String action = tokens.nextToken(); String action = tokens.nextToken();
String flags = tokens.nextToken(); String flags = tokens.nextToken();
handleStore(commandId, uidRangeIterator, action, flags); handleStore(commandId, uidRangeIterator, action, flags);
} else if ("copy".equalsIgnoreCase(subcommand)) { } else if ("copy".equalsIgnoreCase(subcommand)) {
try { try {
UIDRangeIterator uidRangeIterator = getUIDRangeIterator(currentFolder, tokens.nextToken()); UIDRangeIterator uidRangeIterator = new UIDRangeIterator(currentFolder.messages, tokens.nextToken());
String targetName = BASE64MailboxDecoder.decode(tokens.nextToken()); String targetName = BASE64MailboxDecoder.decode(tokens.nextToken());
while (uidRangeIterator.hasNext()) { while (uidRangeIterator.hasNext()) {
DavGatewayTray.switchIcon(); DavGatewayTray.switchIcon();
@ -648,7 +655,7 @@ public class ImapConnection extends AbstractConnection {
if ("AND ()".equals(query)) { if ("AND ()".equals(query)) {
query = null; query = null;
} }
ExchangeSession.MessageList localMessages = session.searchMessages(currentFolder.folderName, query); ExchangeSession.MessageList localMessages = currentFolder.searchMessages(query);
int index = 1; int index = 1;
for (ExchangeSession.Message message : localMessages) { for (ExchangeSession.Message message : localMessages) {
if ((conditions.deleted == null || message.deleted == conditions.deleted) if ((conditions.deleted == null || message.deleted == conditions.deleted)
@ -1177,16 +1184,6 @@ public class ImapConnection extends AbstractConnection {
return result; 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 * 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=org.apache.log4j.PatternLayout
log4j.appender.ConsoleAppender.layout.ConversionPattern=%d{ISO8601} %-5p [%t] %c %x - %m%n 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