Rewrite IMAP expunge

This commit is contained in:
Hari 2017-11-11 02:31:13 +05:30
parent f78ed69a88
commit 31b7cf8dae
7 changed files with 63 additions and 4 deletions

View file

@ -116,6 +116,9 @@ public abstract class Folder<T extends Message> {
public void expunge() throws MessagingException public void expunge() throws MessagingException
{} {}
public void expungeUids(List<String> uids) throws MessagingException {
}
/** /**
* Populate a list of messages based upon a FetchProfile. See {@link FetchProfile} for the things that can * Populate a list of messages based upon a FetchProfile. See {@link FetchProfile} for the things that can
* be fetched. * be fetched.

View file

@ -14,4 +14,5 @@ class Capabilities {
public static final String COMPRESS_DEFLATE = "COMPRESS=DEFLATE"; public static final String COMPRESS_DEFLATE = "COMPRESS=DEFLATE";
public static final String STARTTLS = "STARTTLS"; public static final String STARTTLS = "STARTTLS";
public static final String SPECIAL_USE = "SPECIAL-USE"; public static final String SPECIAL_USE = "SPECIAL-USE";
public static final String UID_PLUS = "UIDPLUS";
} }

View file

@ -18,4 +18,5 @@ class Commands {
public static final String UID_STORE = "UID STORE"; public static final String UID_STORE = "UID STORE";
public static final String UID_FETCH = "UID FETCH"; public static final String UID_FETCH = "UID FETCH";
public static final String UID_COPY = "UID COPY"; public static final String UID_COPY = "UID COPY";
public static final String UID_EXPUNGE = "UID EXPUNGE";
} }

View file

@ -710,6 +710,10 @@ class ImapConnection {
return capabilities.contains(Capabilities.IDLE); return capabilities.contains(Capabilities.IDLE);
} }
boolean isUidPlusCapable() {
return capabilities.contains(Capabilities.UID_PLUS);
}
public void close() { public void close() {
open = false; open = false;
stacktraceForClose = new Exception(); stacktraceForClose = new Exception();

View file

@ -1259,6 +1259,30 @@ class ImapFolder extends Folder<ImapMessage> {
} }
} }
@Override
public void expungeUids(List<String> uids) throws MessagingException {
if (uids == null || uids.isEmpty()) {
throw new IllegalArgumentException("expungeUids() must be called with a non-empty set of UIDs");
}
open(OPEN_MODE_RW);
checkOpen();
try {
if (connection.isUidPlusCapable()) {
Set<Long> longUids = new HashSet<>(uids.size());
for (String uid : uids) {
longUids.add(Long.parseLong(uid));
}
connection.executeCommandWithIdSet(Commands.UID_EXPUNGE, "", longUids);
} else {
executeSimpleCommand("EXPUNGE");
}
} catch (IOException ioe) {
throw ioExceptionHandler(connection, ioe);
}
}
@Override @Override
public void setFlags(Set<Flag> flags, boolean value) throws MessagingException { public void setFlags(Set<Flag> flags, boolean value) throws MessagingException {
open(OPEN_MODE_RW); open(OPEN_MODE_RW);

View file

@ -1005,6 +1005,28 @@ public class ImapFolderTest {
verify(imapConnection).executeSimpleCommand("EXPUNGE"); verify(imapConnection).executeSimpleCommand("EXPUNGE");
} }
@Test
public void expungeUids_withUidPlus_shouldIssueUidExpungeCommand() throws Exception {
ImapFolder folder = createFolder("Folder");
prepareImapFolderForOpen(OPEN_MODE_RW);
when(imapConnection.isUidPlusCapable()).thenReturn(true);
folder.expungeUids(singletonList("1"));
assertCommandWithIdsIssued("UID EXPUNGE 1");
}
@Test
public void expungeUids_withoutUidPlus_shouldIssueExpungeCommand() throws Exception {
ImapFolder folder = createFolder("Folder");
prepareImapFolderForOpen(OPEN_MODE_RW);
when(imapConnection.isUidPlusCapable()).thenReturn(false);
folder.expungeUids(singletonList("1"));
verify(imapConnection).executeSimpleCommand("EXPUNGE");
}
@Test @Test
public void setFlags_shouldIssueUidStoreCommand() throws Exception { public void setFlags_shouldIssueUidStoreCommand() throws Exception {
ImapFolder folder = createFolder("Folder"); ImapFolder folder = createFolder("Folder");
@ -1226,8 +1248,8 @@ public class ImapFolderTest {
for (int i = 0, end = commandPrefixes.size(); i < end; i++) { for (int i = 0, end = commandPrefixes.size(); i < end; i++) {
String command = commandPrefixes.get(i) + String command = commandPrefixes.get(i) +
" " + ImapUtility.join(",", commandUids.get(i)) + " " + " " + ImapUtility.join(",", commandUids.get(i)) +
commandSuffixes.get(i); ((commandSuffixes.get(i).length() == 0) ? "" : " " + commandSuffixes.get(i));
if (command.equals(expectedCommand)) { if (command.equals(expectedCommand)) {
return; return;
} }

View file

@ -1830,7 +1830,7 @@ public class MessagingController {
if (remoteDate != null) { if (remoteDate != null) {
remoteMessage.setFlag(Flag.DELETED, true); remoteMessage.setFlag(Flag.DELETED, true);
if (Expunge.EXPUNGE_IMMEDIATELY == account.getExpungePolicy()) { if (Expunge.EXPUNGE_IMMEDIATELY == account.getExpungePolicy()) {
remoteFolder.expunge(); remoteFolder.expungeUids(Collections.singletonList(remoteMessage.getUid()));
} }
} }
} }
@ -1914,7 +1914,11 @@ public class MessagingController {
} }
if (!isCopy && Expunge.EXPUNGE_IMMEDIATELY == account.getExpungePolicy()) { if (!isCopy && Expunge.EXPUNGE_IMMEDIATELY == account.getExpungePolicy()) {
Timber.i("processingPendingMoveOrCopy expunging folder %s:%s", account.getDescription(), srcFolder); Timber.i("processingPendingMoveOrCopy expunging folder %s:%s", account.getDescription(), srcFolder);
remoteSrcFolder.expunge(); List<String> movedUids = new ArrayList<>(messages.size());
for (Message message : messages) {
movedUids.add(message.getUid());
}
remoteSrcFolder.expungeUids(movedUids);
} }
/* /*