Search in sources :

Example 71 with LocalStore

use of com.fsck.k9.mailstore.LocalStore in project k-9 by k9mail.

the class MessagingController method setFlag.

/**
 * Set or remove a flag for a message referenced by message UID.
 */
public void setFlag(Account account, long folderId, String uid, Flag flag, boolean newState) {
    try {
        LocalStore localStore = localStoreProvider.getInstance(account);
        LocalFolder localFolder = localStore.getFolder(folderId);
        localFolder.open();
        LocalMessage message = localFolder.getMessage(uid);
        if (message != null) {
            setFlag(account, folderId, Collections.singletonList(message), flag, newState);
        }
    } catch (MessagingException me) {
        throw new RuntimeException(me);
    }
}
Also used : LocalFolder(com.fsck.k9.mailstore.LocalFolder) LocalMessage(com.fsck.k9.mailstore.LocalMessage) MessagingException(com.fsck.k9.mail.MessagingException) LocalStore(com.fsck.k9.mailstore.LocalStore)

Example 72 with LocalStore

use of com.fsck.k9.mailstore.LocalStore in project k-9 by k9mail.

the class MessagingController method processPendingMoveOrCopy.

@VisibleForTesting
void processPendingMoveOrCopy(Account account, long srcFolderId, long destFolderId, List<String> uids, MoveOrCopyFlavor operation, Map<String, String> newUidMap) throws MessagingException {
    checkNotNull(newUidMap);
    LocalStore localStore = localStoreProvider.getInstance(account);
    LocalFolder localSourceFolder = localStore.getFolder(srcFolderId);
    localSourceFolder.open();
    String srcFolderServerId = localSourceFolder.getServerId();
    LocalFolder localDestFolder = localStore.getFolder(destFolderId);
    localDestFolder.open();
    String destFolderServerId = localDestFolder.getServerId();
    Backend backend = getBackend(account);
    Map<String, String> remoteUidMap;
    switch(operation) {
        case COPY:
            remoteUidMap = backend.copyMessages(srcFolderServerId, destFolderServerId, uids);
            break;
        case MOVE:
            remoteUidMap = backend.moveMessages(srcFolderServerId, destFolderServerId, uids);
            break;
        case MOVE_AND_MARK_AS_READ:
            remoteUidMap = backend.moveMessagesAndMarkAsRead(srcFolderServerId, destFolderServerId, uids);
            break;
        default:
            throw new RuntimeException("Unsupported messaging operation");
    }
    if (operation != MoveOrCopyFlavor.COPY) {
        if (backend.getSupportsExpunge() && account.getExpungePolicy() == Expunge.EXPUNGE_IMMEDIATELY) {
            Timber.i("processingPendingMoveOrCopy expunging folder %s:%s", account, srcFolderServerId);
            backend.expungeMessages(srcFolderServerId, uids);
        }
        destroyPlaceholderMessages(localSourceFolder, uids);
    }
    // TODO: Change Backend interface to ensure we never receive null for remoteUidMap
    if (remoteUidMap == null) {
        remoteUidMap = Collections.emptyMap();
    }
    // Update local messages (that currently have local UIDs) with new server IDs
    for (String uid : uids) {
        String localUid = newUidMap.get(uid);
        String newUid = remoteUidMap.get(uid);
        LocalMessage localMessage = localDestFolder.getMessage(localUid);
        if (localMessage == null) {
            // Local message no longer exists
            continue;
        }
        if (newUid != null) {
            // Update local message with new server ID
            localMessage.setUid(newUid);
            localDestFolder.changeUid(localMessage);
            for (MessagingListener l : getListeners()) {
                l.messageUidChanged(account, destFolderId, localUid, newUid);
            }
        } else {
            // New server ID wasn't provided. Remove local message.
            localMessage.destroy();
        }
    }
}
Also used : LocalFolder(com.fsck.k9.mailstore.LocalFolder) LocalMessage(com.fsck.k9.mailstore.LocalMessage) Backend(com.fsck.k9.backend.api.Backend) LocalStore(com.fsck.k9.mailstore.LocalStore) VisibleForTesting(androidx.annotation.VisibleForTesting)

Example 73 with LocalStore

use of com.fsck.k9.mailstore.LocalStore in project k-9 by k9mail.

the class MessagingController method sendMessage.

/**
 * Stores the given message in the Outbox and starts a sendPendingMessages command to attempt to send the message.
 */
public void sendMessage(Account account, Message message, String plaintextSubject, MessagingListener listener) {
    try {
        Long outboxFolderId = account.getOutboxFolderId();
        if (outboxFolderId == null) {
            if (BuildConfig.DEBUG) {
                throw new AssertionError("Outbox does not exist");
            }
            Timber.w("Outbox does not exist");
            outboxFolderId = specialLocalFoldersCreator.createOutbox(account);
        }
        message.setFlag(Flag.SEEN, true);
        MessageStore messageStore = messageStoreManager.getMessageStore(account);
        SaveMessageData messageData = saveMessageDataCreator.createSaveMessageData(message, MessageDownloadState.FULL, plaintextSubject);
        long messageId = messageStore.saveLocalMessage(outboxFolderId, messageData, null);
        LocalStore localStore = localStoreProvider.getInstance(account);
        OutboxStateRepository outboxStateRepository = localStore.getOutboxStateRepository();
        outboxStateRepository.initializeOutboxState(messageId);
        sendPendingMessages(account, listener);
    } catch (Exception e) {
        Timber.e(e, "Error sending message");
    }
}
Also used : MessageStore(com.fsck.k9.mailstore.MessageStore) OutboxStateRepository(com.fsck.k9.mailstore.OutboxStateRepository) SaveMessageData(com.fsck.k9.mailstore.SaveMessageData) LocalStore(com.fsck.k9.mailstore.LocalStore) CertificateValidationException(com.fsck.k9.mail.CertificateValidationException) MessagingException(com.fsck.k9.mail.MessagingException) AuthenticationFailedException(com.fsck.k9.mail.AuthenticationFailedException)

Example 74 with LocalStore

use of com.fsck.k9.mailstore.LocalStore in project k-9 by k9mail.

the class MessagingController method deleteMessagesSynchronous.

private void deleteMessagesSynchronous(Account account, long folderId, List<LocalMessage> messages) {
    try {
        List<LocalMessage> localOnlyMessages = new ArrayList<>();
        List<LocalMessage> syncedMessages = new ArrayList<>();
        List<String> syncedMessageUids = new ArrayList<>();
        for (LocalMessage message : messages) {
            notificationController.removeNewMailNotification(account, message.makeMessageReference());
            String uid = message.getUid();
            if (uid.startsWith(K9.LOCAL_UID_PREFIX)) {
                localOnlyMessages.add(message);
            } else {
                syncedMessages.add(message);
                syncedMessageUids.add(uid);
            }
        }
        Backend backend = getBackend(account);
        LocalStore localStore = localStoreProvider.getInstance(account);
        LocalFolder localFolder = localStore.getFolder(folderId);
        localFolder.open();
        Map<String, String> uidMap = null;
        Long trashFolderId = account.getTrashFolderId();
        LocalFolder localTrashFolder = null;
        if (!account.hasTrashFolder() || folderId == trashFolderId || (backend.getSupportsTrashFolder() && !backend.isDeleteMoveToTrash())) {
            Timber.d("Not moving deleted messages to local Trash folder. Removing local copies.");
            if (!localOnlyMessages.isEmpty()) {
                localFolder.destroyMessages(localOnlyMessages);
            }
            if (!syncedMessages.isEmpty()) {
                localFolder.setFlags(syncedMessages, Collections.singleton(Flag.DELETED), true);
            }
        } else {
            Timber.d("Deleting messages in normal folder, moving");
            localTrashFolder = localStore.getFolder(trashFolderId);
            MessageStore messageStore = messageStoreManager.getMessageStore(account);
            List<Long> messageIds = new ArrayList<>();
            Map<Long, String> messageIdToUidMapping = new HashMap<>();
            for (LocalMessage message : messages) {
                long messageId = message.getDatabaseId();
                messageIds.add(messageId);
                messageIdToUidMapping.put(messageId, message.getUid());
            }
            Map<Long, Long> moveMessageIdMapping = messageStore.moveMessages(messageIds, trashFolderId);
            Map<Long, String> destinationMapping = messageStore.getMessageServerIds(moveMessageIdMapping.values());
            uidMap = new HashMap<>();
            for (Entry<Long, Long> entry : moveMessageIdMapping.entrySet()) {
                long sourceMessageId = entry.getKey();
                long destinationMessageId = entry.getValue();
                String sourceUid = messageIdToUidMapping.get(sourceMessageId);
                String destinationUid = destinationMapping.get(destinationMessageId);
                uidMap.put(sourceUid, destinationUid);
            }
            if (account.isMarkMessageAsReadOnDelete()) {
                Collection<Long> destinationMessageIds = moveMessageIdMapping.values();
                messageStore.setFlag(destinationMessageIds, Flag.SEEN, true);
            }
        }
        for (MessagingListener l : getListeners()) {
            l.folderStatusChanged(account, folderId);
            if (localTrashFolder != null) {
                l.folderStatusChanged(account, trashFolderId);
            }
        }
        Timber.d("Delete policy for account %s is %s", account, account.getDeletePolicy());
        Long outboxFolderId = account.getOutboxFolderId();
        if (outboxFolderId != null && folderId == outboxFolderId && supportsUpload(account)) {
            for (String destinationUid : uidMap.values()) {
                // If the message was in the Outbox, then it has been copied to local Trash, and has
                // to be copied to remote trash
                PendingCommand command = PendingAppend.create(trashFolderId, destinationUid);
                queuePendingCommand(account, command);
            }
            processPendingCommands(account);
        } else if (localFolder.isLocalOnly()) {
        // Nothing to do on the remote side
        } else if (!syncedMessageUids.isEmpty()) {
            if (account.getDeletePolicy() == DeletePolicy.ON_DELETE) {
                if (!account.hasTrashFolder() || folderId == trashFolderId || !backend.isDeleteMoveToTrash()) {
                    queueDelete(account, folderId, syncedMessageUids);
                } else if (account.isMarkMessageAsReadOnDelete()) {
                    queueMoveOrCopy(account, folderId, trashFolderId, MoveOrCopyFlavor.MOVE_AND_MARK_AS_READ, uidMap);
                } else {
                    queueMoveOrCopy(account, folderId, trashFolderId, MoveOrCopyFlavor.MOVE, uidMap);
                }
                processPendingCommands(account);
            } else if (account.getDeletePolicy() == DeletePolicy.MARK_AS_READ) {
                queueSetFlag(account, localFolder.getDatabaseId(), true, Flag.SEEN, syncedMessageUids);
                processPendingCommands(account);
            } else {
                Timber.d("Delete policy %s prevents delete from server", account.getDeletePolicy());
            }
        }
        unsuppressMessages(account, messages);
    } catch (MessagingException me) {
        throw new RuntimeException("Error deleting message from local store.", me);
    }
}
Also used : MessageStore(com.fsck.k9.mailstore.MessageStore) LocalMessage(com.fsck.k9.mailstore.LocalMessage) HashMap(java.util.HashMap) MessagingException(com.fsck.k9.mail.MessagingException) ArrayList(java.util.ArrayList) LocalStore(com.fsck.k9.mailstore.LocalStore) LocalFolder(com.fsck.k9.mailstore.LocalFolder) Backend(com.fsck.k9.backend.api.Backend) PendingCommand(com.fsck.k9.controller.MessagingControllerCommands.PendingCommand)

Example 75 with LocalStore

use of com.fsck.k9.mailstore.LocalStore in project k-9 by k9mail.

the class MessagingController method clearAllPending.

public void clearAllPending(final Account account) {
    try {
        Timber.w("Clearing pending commands!");
        LocalStore localStore = localStoreProvider.getInstance(account);
        localStore.removePendingCommands();
    } catch (MessagingException me) {
        Timber.e(me, "Unable to clear pending command");
    }
}
Also used : MessagingException(com.fsck.k9.mail.MessagingException) LocalStore(com.fsck.k9.mailstore.LocalStore)

Aggregations

LocalStore (com.fsck.k9.mailstore.LocalStore)63 LocalFolder (com.fsck.k9.mailstore.LocalFolder)53 MessagingException (com.fsck.k9.mail.MessagingException)46 LocalMessage (com.fsck.k9.mailstore.LocalMessage)27 FetchProfile (com.fsck.k9.mail.FetchProfile)17 AuthenticationFailedException (com.fsck.k9.mail.AuthenticationFailedException)16 CertificateValidationException (com.fsck.k9.mail.CertificateValidationException)16 Store (com.fsck.k9.mail.Store)16 Folder (com.fsck.k9.mail.Folder)15 Pop3Store (com.fsck.k9.mail.store.pop3.Pop3Store)15 Account (com.fsck.k9.Account)13 Message (com.fsck.k9.mail.Message)13 MimeMessage (com.fsck.k9.mail.internet.MimeMessage)13 ArrayList (java.util.ArrayList)13 UnavailableStorageException (com.fsck.k9.mailstore.UnavailableStorageException)10 Test (org.junit.Test)10 Backend (com.fsck.k9.backend.api.Backend)9 IOException (java.io.IOException)9 SQLiteDatabase (android.database.sqlite.SQLiteDatabase)8 SuppressLint (android.annotation.SuppressLint)7