Move code to upload messages to Backend implementations
This commit is contained in:
parent
80c76e6fb9
commit
455315f62e
13 changed files with 156 additions and 115 deletions
|
@ -57,4 +57,10 @@ interface Backend {
|
|||
|
||||
@Throws(MessagingException::class)
|
||||
fun fetchMessage(folderServerId: String, messageServerId: String, fetchProfile: FetchProfile): Message
|
||||
|
||||
@Throws(MessagingException::class)
|
||||
fun findByMessageId(folderServerId: String, messageId: String): String?
|
||||
|
||||
@Throws(MessagingException::class)
|
||||
fun uploadMessage(folderServerId: String, message: Message): String?
|
||||
}
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
package com.fsck.k9.backend.imap
|
||||
|
||||
|
||||
import com.fsck.k9.mail.Folder
|
||||
import com.fsck.k9.mail.store.imap.ImapStore
|
||||
|
||||
|
||||
internal class CommandFindByMessageId(private val imapStore: ImapStore) {
|
||||
|
||||
fun findByMessageId(folderServerId: String, messageId: String): String? {
|
||||
val folder = imapStore.getFolder(folderServerId)
|
||||
try {
|
||||
folder.open(Folder.OPEN_MODE_RW)
|
||||
return folder.getUidFromMessageId(messageId)
|
||||
} finally {
|
||||
folder.close()
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
package com.fsck.k9.backend.imap
|
||||
|
||||
|
||||
import com.fsck.k9.mail.Folder
|
||||
import com.fsck.k9.mail.Message
|
||||
import com.fsck.k9.mail.store.imap.ImapStore
|
||||
|
||||
|
||||
internal class CommandUploadMessage(private val imapStore: ImapStore) {
|
||||
|
||||
fun uploadMessage(folderServerId: String, message: Message): String? {
|
||||
val folder = imapStore.getFolder(folderServerId)
|
||||
try {
|
||||
folder.open(Folder.OPEN_MODE_RW)
|
||||
|
||||
val localUid = message.uid
|
||||
val uidMap = folder.appendMessages(listOf(message))
|
||||
|
||||
return uidMap[localUid]
|
||||
} finally {
|
||||
folder.close()
|
||||
}
|
||||
}
|
||||
}
|
|
@ -30,6 +30,8 @@ public class ImapBackend implements Backend {
|
|||
private final CommandDeleteAll commandDeleteAll;
|
||||
private final CommandSearch commandSearch;
|
||||
private final CommandFetchMessage commandFetchMessage;
|
||||
private final CommandFindByMessageId commandFindByMessageId;
|
||||
private final CommandUploadMessage commandUploadMessage;
|
||||
|
||||
|
||||
public ImapBackend(String accountName, BackendStorage backendStorage, ImapStore imapStore) {
|
||||
|
@ -42,6 +44,8 @@ public class ImapBackend implements Backend {
|
|||
commandDeleteAll = new CommandDeleteAll(imapStore);
|
||||
commandSearch = new CommandSearch(imapStore);
|
||||
commandFetchMessage = new CommandFetchMessage(imapStore);
|
||||
commandFindByMessageId = new CommandFindByMessageId(imapStore);
|
||||
commandUploadMessage = new CommandUploadMessage(imapStore);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -121,4 +125,16 @@ public class ImapBackend implements Backend {
|
|||
@NotNull FetchProfile fetchProfile) throws MessagingException {
|
||||
return commandFetchMessage.fetchMessage(folderServerId, messageServerId, fetchProfile);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public String findByMessageId(@NotNull String folderServerId, @NotNull String messageId) throws MessagingException {
|
||||
return commandFindByMessageId.findByMessageId(folderServerId, messageId);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public String uploadMessage(@NotNull String folderServerId, @NotNull Message message) throws MessagingException {
|
||||
return commandUploadMessage.uploadMessage(folderServerId, message);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -77,4 +77,12 @@ class Pop3Backend(accountName: String, backendStorage: BackendStorage, pop3Store
|
|||
override fun fetchMessage(folderServerId: String, messageServerId: String, fetchProfile: FetchProfile): Message {
|
||||
return commandFetchMessage.fetchMessage(folderServerId, messageServerId, fetchProfile)
|
||||
}
|
||||
|
||||
override fun findByMessageId(folderServerId: String, messageId: String): String? {
|
||||
return null
|
||||
}
|
||||
|
||||
override fun uploadMessage(folderServerId: String, message: Message): String? {
|
||||
throw UnsupportedOperationException("not supported")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
package com.fsck.k9.backend.webdav
|
||||
|
||||
|
||||
import com.fsck.k9.mail.Folder
|
||||
import com.fsck.k9.mail.Message
|
||||
import com.fsck.k9.mail.store.webdav.WebDavStore
|
||||
|
||||
|
||||
internal class CommandUploadMessage(private val webDavStore: WebDavStore) {
|
||||
|
||||
fun uploadMessage(folderServerId: String, message: Message): String? {
|
||||
val folder = webDavStore.getFolder(folderServerId)
|
||||
try {
|
||||
folder.open(Folder.OPEN_MODE_RW)
|
||||
|
||||
folder.appendMessages(listOf(message))
|
||||
|
||||
return null
|
||||
} finally {
|
||||
folder.close()
|
||||
}
|
||||
}
|
||||
}
|
|
@ -20,6 +20,7 @@ class WebDavBackend(accountName: String, backendStorage: BackendStorage, webDavS
|
|||
private val commandMoveOrCopyMessages = CommandMoveOrCopyMessages(webDavStore)
|
||||
private val commandDeleteAll = CommandDeleteAll(webDavStore)
|
||||
private val commandFetchMessage = CommandFetchMessage(webDavStore)
|
||||
private val commandUploadMessage = CommandUploadMessage(webDavStore)
|
||||
|
||||
override val supportsSeenFlag: Boolean = true
|
||||
override val supportsExpunge: Boolean = true
|
||||
|
@ -82,4 +83,12 @@ class WebDavBackend(accountName: String, backendStorage: BackendStorage, webDavS
|
|||
override fun fetchMessage(folderServerId: String, messageServerId: String, fetchProfile: FetchProfile): Message {
|
||||
return commandFetchMessage.fetchMessage(folderServerId, messageServerId, fetchProfile)
|
||||
}
|
||||
|
||||
override fun findByMessageId(folderServerId: String, messageId: String): String? {
|
||||
return null
|
||||
}
|
||||
|
||||
override fun uploadMessage(folderServerId: String, message: Message): String? {
|
||||
return commandUploadMessage.uploadMessage(folderServerId, message)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1425,7 +1425,6 @@ public class MessagingController {
|
|||
* TODO update the local message UID instead of deleting it
|
||||
*/
|
||||
void processPendingAppend(PendingAppend command, Account account) throws MessagingException {
|
||||
Folder remoteFolder = null;
|
||||
LocalFolder localFolder = null;
|
||||
try {
|
||||
|
||||
|
@ -1440,117 +1439,62 @@ public class MessagingController {
|
|||
return;
|
||||
}
|
||||
|
||||
RemoteStore remoteStore = account.getRemoteStore();
|
||||
remoteFolder = remoteStore.getFolder(folder);
|
||||
if (!remoteFolder.exists()) {
|
||||
Timber.w("Remote folder doesn't exist: %s", folder);
|
||||
return;
|
||||
}
|
||||
remoteFolder.open(Folder.OPEN_MODE_RW);
|
||||
if (remoteFolder.getMode() != Folder.OPEN_MODE_RW) {
|
||||
return;
|
||||
}
|
||||
|
||||
Message remoteMessage = null;
|
||||
if (!localMessage.getUid().startsWith(K9.LOCAL_UID_PREFIX)) {
|
||||
remoteMessage = remoteFolder.getMessage(localMessage.getUid());
|
||||
//FIXME: This should never happen. Throw in debug builds.
|
||||
return;
|
||||
}
|
||||
|
||||
if (remoteMessage == null) {
|
||||
if (localMessage.isSet(Flag.X_REMOTE_COPY_STARTED)) {
|
||||
Timber.w("Local message with uid %s has flag %s already set, checking for remote message with " +
|
||||
"same message id", localMessage.getUid(), X_REMOTE_COPY_STARTED);
|
||||
String rUid = remoteFolder.getUidFromMessageId(localMessage);
|
||||
if (rUid != null) {
|
||||
Timber.w("Local message has flag %s already set, and there is a remote message with uid %s, " +
|
||||
"assuming message was already copied and aborting this copy",
|
||||
X_REMOTE_COPY_STARTED, rUid);
|
||||
Backend backend = getBackend(account);
|
||||
|
||||
String oldUid = localMessage.getUid();
|
||||
localMessage.setUid(rUid);
|
||||
localFolder.changeUid(localMessage);
|
||||
for (MessagingListener l : getListeners()) {
|
||||
l.messageUidChanged(account, folder, oldUid, localMessage.getUid());
|
||||
}
|
||||
return;
|
||||
} else {
|
||||
Timber.w("No remote message with message-id found, proceeding with append");
|
||||
}
|
||||
}
|
||||
if (localMessage.isSet(Flag.X_REMOTE_COPY_STARTED)) {
|
||||
Timber.w("Local message with uid %s has flag %s already set, checking for remote message with " +
|
||||
"same message id", localMessage.getUid(), X_REMOTE_COPY_STARTED);
|
||||
|
||||
/*
|
||||
* If the message does not exist remotely we just upload it and then
|
||||
* update our local copy with the new uid.
|
||||
*/
|
||||
FetchProfile fp = new FetchProfile();
|
||||
fp.add(FetchProfile.Item.BODY);
|
||||
localFolder.fetch(Collections.singletonList(localMessage), fp, null);
|
||||
String oldUid = localMessage.getUid();
|
||||
localMessage.setFlag(Flag.X_REMOTE_COPY_STARTED, true);
|
||||
remoteFolder.appendMessages(Collections.singletonList(localMessage));
|
||||
String messageServerId = backend.findByMessageId(folder, localMessage.getMessageId());
|
||||
if (messageServerId != null) {
|
||||
Timber.w("Local message has flag %s already set, and there is a remote message with uid %s, " +
|
||||
"assuming message was already copied and aborting this copy",
|
||||
X_REMOTE_COPY_STARTED, messageServerId);
|
||||
|
||||
if (localMessage.getUid().startsWith(K9.LOCAL_UID_PREFIX)) {
|
||||
// We didn't get the server UID of the uploaded message. Remove the local message now. The uploaded
|
||||
// version will be downloaded during the next sync.
|
||||
localFolder.destroyMessages(Collections.singletonList(localMessage));
|
||||
} else {
|
||||
String oldUid = localMessage.getUid();
|
||||
localMessage.setUid(messageServerId);
|
||||
localFolder.changeUid(localMessage);
|
||||
|
||||
for (MessagingListener l : getListeners()) {
|
||||
l.messageUidChanged(account, folder, oldUid, localMessage.getUid());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/*
|
||||
* If the remote message exists we need to determine which copy to keep.
|
||||
*/
|
||||
/*
|
||||
* See if the remote message is newer than ours.
|
||||
*/
|
||||
FetchProfile fp = new FetchProfile();
|
||||
fp.add(FetchProfile.Item.ENVELOPE);
|
||||
remoteFolder.fetch(Collections.singletonList(remoteMessage), fp, null);
|
||||
Date localDate = localMessage.getInternalDate();
|
||||
Date remoteDate = remoteMessage.getInternalDate();
|
||||
if (remoteDate != null && remoteDate.compareTo(localDate) > 0) {
|
||||
/*
|
||||
* If the remote message is newer than ours we'll just
|
||||
* delete ours and move on. A sync will get the server message
|
||||
* if we need to be able to see it.
|
||||
*/
|
||||
localMessage.destroy();
|
||||
|
||||
return;
|
||||
} else {
|
||||
/*
|
||||
* Otherwise we'll upload our message and then delete the remote message.
|
||||
*/
|
||||
fp = new FetchProfile();
|
||||
fp.add(FetchProfile.Item.BODY);
|
||||
localFolder.fetch(Collections.singletonList(localMessage), fp, null);
|
||||
String oldUid = localMessage.getUid();
|
||||
Timber.w("No remote message with message-id found, proceeding with append");
|
||||
}
|
||||
}
|
||||
|
||||
localMessage.setFlag(Flag.X_REMOTE_COPY_STARTED, true);
|
||||
/*
|
||||
* If the message does not exist remotely we just upload it and then
|
||||
* update our local copy with the new uid.
|
||||
*/
|
||||
FetchProfile fp = new FetchProfile();
|
||||
fp.add(FetchProfile.Item.BODY);
|
||||
localFolder.fetch(Collections.singletonList(localMessage), fp, null);
|
||||
String oldUid = localMessage.getUid();
|
||||
localMessage.setFlag(Flag.X_REMOTE_COPY_STARTED, true);
|
||||
|
||||
remoteFolder.appendMessages(Collections.singletonList(localMessage));
|
||||
if (localMessage.getUid().startsWith(K9.LOCAL_UID_PREFIX)) {
|
||||
// We didn't get the server UID of the uploaded message. Remove the local message now. The
|
||||
// uploaded version will be downloaded during the next sync.
|
||||
localFolder.destroyMessages(Collections.singletonList(localMessage));
|
||||
} else {
|
||||
localFolder.changeUid(localMessage);
|
||||
for (MessagingListener l : getListeners()) {
|
||||
l.messageUidChanged(account, folder, oldUid, localMessage.getUid());
|
||||
}
|
||||
}
|
||||
String messageServerId = backend.uploadMessage(folder, localMessage);
|
||||
|
||||
if (remoteDate != null) {
|
||||
remoteMessage.setFlag(Flag.DELETED, true);
|
||||
if (Expunge.EXPUNGE_IMMEDIATELY == account.getExpungePolicy()) {
|
||||
remoteFolder.expungeUids(Collections.singletonList(remoteMessage.getUid()));
|
||||
}
|
||||
}
|
||||
if (messageServerId == null) {
|
||||
// We didn't get the server UID of the uploaded message. Remove the local message now. The uploaded
|
||||
// version will be downloaded during the next sync.
|
||||
localFolder.destroyMessages(Collections.singletonList(localMessage));
|
||||
} else {
|
||||
localMessage.setUid(messageServerId);
|
||||
localFolder.changeUid(localMessage);
|
||||
|
||||
for (MessagingListener l : getListeners()) {
|
||||
l.messageUidChanged(account, folder, oldUid, localMessage.getUid());
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
closeFolder(remoteFolder);
|
||||
closeFolder(localFolder);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1775,7 +1775,7 @@ public class LocalFolder extends Folder<LocalMessage> {
|
|||
}
|
||||
|
||||
@Override
|
||||
public String getUidFromMessageId(Message message) throws MessagingException {
|
||||
public String getUidFromMessageId(String messageId) throws MessagingException {
|
||||
throw new MessagingException("Cannot call getUidFromMessageId on LocalFolder");
|
||||
}
|
||||
|
||||
|
|
|
@ -111,7 +111,7 @@ public abstract class Folder<T extends Message> {
|
|||
|
||||
public abstract void setFlags(Set<Flag> flags, boolean value) throws MessagingException;
|
||||
|
||||
public abstract String getUidFromMessageId(Message message) throws MessagingException;
|
||||
public abstract String getUidFromMessageId(String messageId) throws MessagingException;
|
||||
|
||||
public void expunge() throws MessagingException
|
||||
{}
|
||||
|
|
|
@ -1177,8 +1177,8 @@ public class ImapFolder extends Folder<ImapMessage> {
|
|||
String newUid = appendList.getString(2);
|
||||
|
||||
if (!TextUtils.isEmpty(newUid)) {
|
||||
message.setUid(newUid);
|
||||
uidMap.put(message.getUid(), newUid);
|
||||
message.setUid(newUid);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
@ -1189,7 +1189,8 @@ public class ImapFolder extends Folder<ImapMessage> {
|
|||
* This part is executed in case the server does not support UIDPLUS or does
|
||||
* not implement the APPENDUID response code.
|
||||
*/
|
||||
String newUid = getUidFromMessageId(message);
|
||||
String messageId = extractMessageId(message);
|
||||
String newUid = messageId != null ? getUidFromMessageId(messageId) : null;
|
||||
if (K9MailLib.isDebug()) {
|
||||
Timber.d("Got UID %s for message for %s", newUid, getLogId());
|
||||
}
|
||||
|
@ -1211,22 +1212,13 @@ public class ImapFolder extends Folder<ImapMessage> {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUidFromMessageId(Message message) throws MessagingException {
|
||||
/*
|
||||
* Try to find the UID of the message we just appended using the
|
||||
* Message-ID header.
|
||||
*/
|
||||
private String extractMessageId(Message message) {
|
||||
String[] messageIdHeader = message.getHeader("Message-ID");
|
||||
return messageIdHeader.length == 0 ? null : messageIdHeader[0];
|
||||
}
|
||||
|
||||
if (messageIdHeader.length == 0) {
|
||||
if (K9MailLib.isDebug()) {
|
||||
Timber.d("Did not get a message-id in order to search for UID for %s", getLogId());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
String messageId = messageIdHeader[0];
|
||||
@Override
|
||||
public String getUidFromMessageId(String messageId) throws MessagingException {
|
||||
if (K9MailLib.isDebug()) {
|
||||
Timber.d("Looking for UID for message with message-id %s for %s", messageId, getLogId());
|
||||
}
|
||||
|
|
|
@ -533,7 +533,7 @@ public class Pop3Folder extends Folder<Pop3Message> {
|
|||
}
|
||||
|
||||
@Override
|
||||
public String getUidFromMessageId(Message message) throws MessagingException {
|
||||
public String getUidFromMessageId(String messageId) throws MessagingException {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
|
@ -700,7 +700,7 @@ public class WebDavFolder extends Folder<WebDavMessage> {
|
|||
}
|
||||
|
||||
@Override
|
||||
public String getUidFromMessageId(Message message) throws MessagingException {
|
||||
public String getUidFromMessageId(String messageId) throws MessagingException {
|
||||
Timber.e("Unimplemented method getUidFromMessageId in WebDavStore.WebDavFolder could lead to duplicate messages "
|
||||
+ " being uploaded to the Sent folder");
|
||||
return null;
|
||||
|
|
Loading…
Reference in a new issue