mirror of
https://github.com/moparisthebest/k-9
synced 2024-11-24 02:12:15 -05:00
Automatically re-synchronize the IMAP protocol. Previously, losses of
synchronization could happen if an Exception was thrown while parsing an untagged response without using executeSimpleCommand. For instance, while doing a fetch. Once synchronization was lost, later commands would fail in surprising ways. One manifestation of such failures was spontaneously emptying of folders when search results were not returned properly. The new code makes sure to only accept OK responses with the tag of the command, and discards the untagged responses from previous command.
This commit is contained in:
parent
7daf4ef1e6
commit
651642faeb
@ -753,15 +753,12 @@ public class MessagingController implements Runnable {
|
|||||||
for (Message thisMess : remoteMessageArray)
|
for (Message thisMess : remoteMessageArray)
|
||||||
{
|
{
|
||||||
remoteMessages.add(thisMess);
|
remoteMessages.add(thisMess);
|
||||||
|
remoteUidMap.put(thisMess.getUid(), thisMess);
|
||||||
}
|
}
|
||||||
if (Config.LOGV) {
|
if (Config.LOGV) {
|
||||||
Log.v(Email.LOG_TAG, "SYNC: Got messages for folder " + folder);
|
Log.v(Email.LOG_TAG, "SYNC: Got " + remoteUidMap.size() + " messages for folder " + folder);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (Message message : remoteMessages) {
|
|
||||||
remoteUidMap.put(message.getUid(), message);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Get a list of the messages that are in the remote list but not on the
|
* Get a list of the messages that are in the remote list but not on the
|
||||||
* local store, or messages that are in the local store but failed to download
|
* local store, or messages that are in the local store but failed to download
|
||||||
@ -923,6 +920,7 @@ s * critical data as fast as possible, and then we'll fill in the de
|
|||||||
!localMessage.isSet(Flag.DELETED))
|
!localMessage.isSet(Flag.DELETED))
|
||||||
{
|
{
|
||||||
localMessage.setFlag(Flag.X_DESTROYED, true);
|
localMessage.setFlag(Flag.X_DESTROYED, true);
|
||||||
|
// Log.d(Email.LOG_TAG, "Destroying message " + localMessage.getUid() + " which isn't in the most recent group on server");
|
||||||
for (MessagingListener l : getListeners()) {
|
for (MessagingListener l : getListeners()) {
|
||||||
l.synchronizeMailboxRemovedMessage(account, folder, localMessage);
|
l.synchronizeMailboxRemovedMessage(account, folder, localMessage);
|
||||||
}
|
}
|
||||||
|
@ -384,10 +384,13 @@ public class ImapStore extends Store {
|
|||||||
mPathDelimeter = nameResponses.get(0).getString(2);
|
mPathDelimeter = nameResponses.get(0).getString(2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// executeSimpleCommand("CLOSE");
|
||||||
|
|
||||||
String command = String.format("SELECT \"%s\"",
|
String command = String.format("SELECT \"%s\"",
|
||||||
encodeFolderName(getPrefixedName()));
|
encodeFolderName(getPrefixedName()));
|
||||||
|
|
||||||
mMessageCount = -1;
|
//mMessageCount = -1;
|
||||||
|
|
||||||
List<ImapResponse> responses = executeSimpleCommand(command);
|
List<ImapResponse> responses = executeSimpleCommand(command);
|
||||||
|
|
||||||
@ -429,6 +432,11 @@ public class ImapStore extends Store {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void close(boolean expunge) throws MessagingException {
|
public void close(boolean expunge) throws MessagingException {
|
||||||
|
if (mMessageCount != -1)
|
||||||
|
{
|
||||||
|
// close();
|
||||||
|
mMessageCount = -1;
|
||||||
|
}
|
||||||
if (!isOpen()) {
|
if (!isOpen()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -436,7 +444,6 @@ public class ImapStore extends Store {
|
|||||||
{
|
{
|
||||||
expunge();
|
expunge();
|
||||||
}
|
}
|
||||||
mMessageCount = -1;
|
|
||||||
synchronized (this) {
|
synchronized (this) {
|
||||||
releaseConnection(mConnection);
|
releaseConnection(mConnection);
|
||||||
mConnection = null;
|
mConnection = null;
|
||||||
@ -584,6 +591,7 @@ public class ImapStore extends Store {
|
|||||||
List<ImapResponse> responses =
|
List<ImapResponse> responses =
|
||||||
executeSimpleCommand(String.format("UID SEARCH UID %S", uid));
|
executeSimpleCommand(String.format("UID SEARCH UID %S", uid));
|
||||||
for (ImapResponse response : responses) {
|
for (ImapResponse response : responses) {
|
||||||
|
// Log.d(Email.LOG_TAG, "Got search response: " + response.get(0) + ", size " + response.size());
|
||||||
if (response.mTag == null && response.get(0).equals("SEARCH")) {
|
if (response.mTag == null && response.get(0).equals("SEARCH")) {
|
||||||
for (int i = 1, count = response.size(); i < count; i++) {
|
for (int i = 1, count = response.size(); i < count; i++) {
|
||||||
if (uid.equals(response.get(i))) {
|
if (uid.equals(response.get(i))) {
|
||||||
@ -614,15 +622,24 @@ public class ImapStore extends Store {
|
|||||||
checkOpen();
|
checkOpen();
|
||||||
ArrayList<Message> messages = new ArrayList<Message>();
|
ArrayList<Message> messages = new ArrayList<Message>();
|
||||||
try {
|
try {
|
||||||
|
boolean gotSearchValues = false;
|
||||||
ArrayList<Integer> uids = new ArrayList<Integer>();
|
ArrayList<Integer> uids = new ArrayList<Integer>();
|
||||||
List<ImapResponse> responses = executeSimpleCommand(String.format("UID SEARCH %d:%d NOT DELETED", start, end));
|
List<ImapResponse> responses = executeSimpleCommand(String.format("UID SEARCH %d:%d NOT DELETED", start, end));
|
||||||
for (ImapResponse response : responses) {
|
for (ImapResponse response : responses) {
|
||||||
|
// Log.d(Email.LOG_TAG, "Got search response: " + response.get(0) + ", size " + response.size());
|
||||||
if (response.get(0).equals("SEARCH")) {
|
if (response.get(0).equals("SEARCH")) {
|
||||||
|
gotSearchValues = true;
|
||||||
for (int i = 1, count = response.size(); i < count; i++) {
|
for (int i = 1, count = response.size(); i < count; i++) {
|
||||||
|
// Log.d(Email.LOG_TAG, "Got search response UID: " + response.getString(i));
|
||||||
|
|
||||||
uids.add(Integer.parseInt(response.getString(i)));
|
uids.add(Integer.parseInt(response.getString(i)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (gotSearchValues == false)
|
||||||
|
{
|
||||||
|
throw new MessagingException("Did not get proper search response");
|
||||||
|
}
|
||||||
// Sort the uids in numerically ascending order
|
// Sort the uids in numerically ascending order
|
||||||
Collections.sort(uids);
|
Collections.sort(uids);
|
||||||
for (int i = 0, count = uids.size(); i < count; i++) {
|
for (int i = 0, count = uids.size(); i < count; i++) {
|
||||||
@ -868,7 +885,7 @@ public class ImapStore extends Store {
|
|||||||
private void handleUntaggedResponse(ImapResponse response) {
|
private void handleUntaggedResponse(ImapResponse response) {
|
||||||
if (response.mTag == null && response.size() > 1 && response.get(1).equals("EXISTS")) {
|
if (response.mTag == null && response.size() > 1 && response.get(1).equals("EXISTS")) {
|
||||||
mMessageCount = response.getNumber(0);
|
mMessageCount = response.getNumber(0);
|
||||||
Log.i(Email.LOG_TAG, "Got untagged EXISTS with value " + mMessageCount);
|
//Log.i(Email.LOG_TAG, "Got untagged EXISTS with value " + mMessageCount);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1137,6 +1154,15 @@ public class ImapStore extends Store {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void close() throws MessagingException {
|
||||||
|
checkOpen();
|
||||||
|
try {
|
||||||
|
executeSimpleCommand("CLOSE");
|
||||||
|
} catch (IOException ioe) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private String combineFlags(Flag[] flags)
|
private String combineFlags(Flag[] flags)
|
||||||
{
|
{
|
||||||
ArrayList<String> flagNames = new ArrayList<String>();
|
ArrayList<String> flagNames = new ArrayList<String>();
|
||||||
@ -1467,9 +1493,13 @@ public class ImapStore extends Store {
|
|||||||
throws IOException, ImapException, MessagingException {
|
throws IOException, ImapException, MessagingException {
|
||||||
if (Config.LOGV)
|
if (Config.LOGV)
|
||||||
{
|
{
|
||||||
Log.v(Email.LOG_TAG, "Sending IMAP command " + command);
|
Log.v(Email.LOG_TAG, "Sending IMAP command " + command + " on connection " + this.hashCode());
|
||||||
}
|
}
|
||||||
String tag = sendCommand(command, sensitive);
|
String tag = sendCommand(command, sensitive);
|
||||||
|
if (Config.LOGV)
|
||||||
|
{
|
||||||
|
Log.v(Email.LOG_TAG, "Sent IMAP command " + command + " with tag " + tag);
|
||||||
|
}
|
||||||
ArrayList<ImapResponse> responses = new ArrayList<ImapResponse>();
|
ArrayList<ImapResponse> responses = new ArrayList<ImapResponse>();
|
||||||
ImapResponse response;
|
ImapResponse response;
|
||||||
do {
|
do {
|
||||||
@ -1478,6 +1508,13 @@ public class ImapStore extends Store {
|
|||||||
{
|
{
|
||||||
Log.v(Email.LOG_TAG, "Got IMAP response " + response);
|
Log.v(Email.LOG_TAG, "Got IMAP response " + response);
|
||||||
}
|
}
|
||||||
|
if (response.mTag != null && response.mTag.equals(tag) == false)
|
||||||
|
{
|
||||||
|
Log.w(Email.LOG_TAG, "Got tag response from previous command " + response);
|
||||||
|
responses.clear();
|
||||||
|
response.mTag = null;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
responses.add(response);
|
responses.add(response);
|
||||||
} while (response.mTag == null);
|
} while (response.mTag == null);
|
||||||
if (response.size() < 1 || !response.get(0).equals("OK")) {
|
if (response.size() < 1 || !response.get(0).equals("OK")) {
|
||||||
|
Loading…
Reference in New Issue
Block a user