Search in sources :

Example 51 with Message

use of com.fsck.k9.mail.Message in project k-9 by k9mail.

the class MessagingController method processPendingAppend.

/**
     * Process a pending append message command. This command uploads a local message to the
     * server, first checking to be sure that the server message is not newer than
     * the local message. Once the local message is successfully processed it is deleted so
     * that the server message will be synchronized down without an additional copy being
     * created.
     * 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 {
        String folder = command.folder;
        String uid = command.uid;
        if (account.getErrorFolderName().equals(folder)) {
            return;
        }
        LocalStore localStore = account.getLocalStore();
        localFolder = localStore.getFolder(folder);
        LocalMessage localMessage = localFolder.getMessage(uid);
        if (localMessage == null) {
            return;
        }
        Store remoteStore = account.getRemoteStore();
        remoteFolder = remoteStore.getFolder(folder);
        if (!remoteFolder.exists()) {
            if (!remoteFolder.create(FolderType.HOLDS_MESSAGES)) {
                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());
        }
        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);
                    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 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));
            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();
            } 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();
                localMessage.setFlag(Flag.X_REMOTE_COPY_STARTED, true);
                remoteFolder.appendMessages(Collections.singletonList(localMessage));
                localFolder.changeUid(localMessage);
                for (MessagingListener l : getListeners()) {
                    l.messageUidChanged(account, folder, oldUid, localMessage.getUid());
                }
                if (remoteDate != null) {
                    remoteMessage.setFlag(Flag.DELETED, true);
                    if (Expunge.EXPUNGE_IMMEDIATELY == account.getExpungePolicy()) {
                        remoteFolder.expunge();
                    }
                }
            }
        }
    } finally {
        closeFolder(remoteFolder);
        closeFolder(localFolder);
    }
}
Also used : LocalFolder(com.fsck.k9.mailstore.LocalFolder) LocalMessage(com.fsck.k9.mailstore.LocalMessage) FetchProfile(com.fsck.k9.mail.FetchProfile) LocalMessage(com.fsck.k9.mailstore.LocalMessage) MimeMessage(com.fsck.k9.mail.internet.MimeMessage) Message(com.fsck.k9.mail.Message) LocalStore(com.fsck.k9.mailstore.LocalStore) Store(com.fsck.k9.mail.Store) Pop3Store(com.fsck.k9.mail.store.pop3.Pop3Store) LocalStore(com.fsck.k9.mailstore.LocalStore) Folder(com.fsck.k9.mail.Folder) LocalFolder(com.fsck.k9.mailstore.LocalFolder) Date(java.util.Date)

Example 52 with Message

use of com.fsck.k9.mail.Message in project k-9 by k9mail.

the class MessagingController method deleteMessagesSynchronous.

private void deleteMessagesSynchronous(final Account account, final String folder, final List<? extends Message> messages, MessagingListener listener) {
    Folder localFolder = null;
    Folder localTrashFolder = null;
    List<String> uids = getUidsFromMessages(messages);
    try {
        //as messages get a new UID after being moved
        for (Message message : messages) {
            for (MessagingListener l : getListeners(listener)) {
                l.messageDeleted(account, folder, message);
            }
        }
        Store localStore = account.getLocalStore();
        localFolder = localStore.getFolder(folder);
        Map<String, String> uidMap = null;
        if (folder.equals(account.getTrashFolderName()) || !account.hasTrashFolder()) {
            Timber.d("Deleting messages in trash folder or trash set to -None-, not copying");
            localFolder.setFlags(messages, Collections.singleton(Flag.DELETED), true);
        } else {
            localTrashFolder = localStore.getFolder(account.getTrashFolderName());
            if (!localTrashFolder.exists()) {
                localTrashFolder.create(Folder.FolderType.HOLDS_MESSAGES);
            }
            if (localTrashFolder.exists()) {
                Timber.d("Deleting messages in normal folder, moving");
                uidMap = localFolder.moveMessages(messages, localTrashFolder);
            }
        }
        for (MessagingListener l : getListeners()) {
            l.folderStatusChanged(account, folder, localFolder.getUnreadMessageCount());
            if (localTrashFolder != null) {
                l.folderStatusChanged(account, account.getTrashFolderName(), localTrashFolder.getUnreadMessageCount());
            }
        }
        Timber.d("Delete policy for account %s is %s", account.getDescription(), account.getDeletePolicy());
        if (folder.equals(account.getOutboxFolderName())) {
            for (Message message : messages) {
                // 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(account.getTrashFolderName(), message.getUid());
                queuePendingCommand(account, command);
            }
            processPendingCommands(account);
        } else if (account.getDeletePolicy() == DeletePolicy.ON_DELETE) {
            if (folder.equals(account.getTrashFolderName())) {
                queueSetFlag(account, folder, true, Flag.DELETED, uids);
            } else {
                queueMoveOrCopy(account, folder, account.getTrashFolderName(), false, uids, uidMap);
            }
            processPendingCommands(account);
        } else if (account.getDeletePolicy() == DeletePolicy.MARK_AS_READ) {
            queueSetFlag(account, folder, true, Flag.SEEN, uids);
            processPendingCommands(account);
        } else {
            Timber.d("Delete policy %s prevents delete from server", account.getDeletePolicy());
        }
        unsuppressMessages(account, messages);
    } catch (UnavailableStorageException e) {
        Timber.i("Failed to delete message because storage is not available - trying again later.");
        throw new UnavailableAccountException(e);
    } catch (MessagingException me) {
        addErrorMessage(account, null, me);
        throw new RuntimeException("Error deleting message from local store.", me);
    } finally {
        closeFolder(localFolder);
        closeFolder(localTrashFolder);
    }
}
Also used : LocalMessage(com.fsck.k9.mailstore.LocalMessage) MimeMessage(com.fsck.k9.mail.internet.MimeMessage) Message(com.fsck.k9.mail.Message) MessagingException(com.fsck.k9.mail.MessagingException) UnavailableStorageException(com.fsck.k9.mailstore.UnavailableStorageException) LocalStore(com.fsck.k9.mailstore.LocalStore) Store(com.fsck.k9.mail.Store) Pop3Store(com.fsck.k9.mail.store.pop3.Pop3Store) Folder(com.fsck.k9.mail.Folder) LocalFolder(com.fsck.k9.mailstore.LocalFolder) PendingCommand(com.fsck.k9.controller.MessagingControllerCommands.PendingCommand)

Example 53 with Message

use of com.fsck.k9.mail.Message in project k-9 by k9mail.

the class MessagingController method saveDraft.

/**
     * Save a draft message.
     *
     * @param account
     *         Account we are saving for.
     * @param message
     *         Message to save.
     *
     * @return Message representing the entry in the local store.
     */
public Message saveDraft(final Account account, final Message message, long existingDraftId, boolean saveRemotely) {
    Message localMessage = null;
    try {
        LocalStore localStore = account.getLocalStore();
        LocalFolder localFolder = localStore.getFolder(account.getDraftsFolderName());
        localFolder.open(Folder.OPEN_MODE_RW);
        if (existingDraftId != INVALID_MESSAGE_ID) {
            String uid = localFolder.getMessageUidById(existingDraftId);
            message.setUid(uid);
        }
        // Save the message to the store.
        localFolder.appendMessages(Collections.singletonList(message));
        // Fetch the message back from the store.  This is the Message that's returned to the caller.
        localMessage = localFolder.getMessage(message.getUid());
        localMessage.setFlag(Flag.X_DOWNLOADED_FULL, true);
        if (saveRemotely) {
            PendingCommand command = PendingAppend.create(localFolder.getName(), localMessage.getUid());
            queuePendingCommand(account, command);
            processPendingCommands(account);
        }
    } catch (MessagingException e) {
        Timber.e(e, "Unable to save message as draft.");
        addErrorMessage(account, null, e);
    }
    return localMessage;
}
Also used : LocalFolder(com.fsck.k9.mailstore.LocalFolder) LocalMessage(com.fsck.k9.mailstore.LocalMessage) MimeMessage(com.fsck.k9.mail.internet.MimeMessage) Message(com.fsck.k9.mail.Message) MessagingException(com.fsck.k9.mail.MessagingException) LocalStore(com.fsck.k9.mailstore.LocalStore) PendingCommand(com.fsck.k9.controller.MessagingControllerCommands.PendingCommand)

Example 54 with Message

use of com.fsck.k9.mail.Message in project k-9 by k9mail.

the class MessagingController method groupMessagesByAccountAndFolder.

@NonNull
private Map<String, Map<String, List<MessageReference>>> groupMessagesByAccountAndFolder(List<MessageReference> messages) {
    Map<String, Map<String, List<MessageReference>>> accountMap = new HashMap<>();
    for (MessageReference message : messages) {
        if (message == null) {
            continue;
        }
        String accountUuid = message.getAccountUuid();
        String folderName = message.getFolderName();
        Map<String, List<MessageReference>> folderMap = accountMap.get(accountUuid);
        if (folderMap == null) {
            folderMap = new HashMap<>();
            accountMap.put(accountUuid, folderMap);
        }
        List<MessageReference> messageList = folderMap.get(folderName);
        if (messageList == null) {
            messageList = new LinkedList<>();
            folderMap.put(folderName, messageList);
        }
        messageList.add(message);
    }
    return accountMap;
}
Also used : ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) List(java.util.List) LinkedList(java.util.LinkedList) MessageReference(com.fsck.k9.activity.MessageReference) Map(java.util.Map) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) HashMap(java.util.HashMap) NonNull(android.support.annotation.NonNull)

Example 55 with Message

use of com.fsck.k9.mail.Message in project k-9 by k9mail.

the class MessagingController method downloadPartial.

private void downloadPartial(Folder remoteFolder, LocalFolder localFolder, Message message) throws MessagingException {
    /*
         * We have a structure to deal with, from which
         * we can pull down the parts we want to actually store.
         * Build a list of parts we are interested in. Text parts will be downloaded
         * right now, attachments will be left for later.
         */
    Set<Part> viewables = MessageExtractor.collectTextParts(message);
    /*
         * Now download the parts we're interested in storing.
         */
    for (Part part : viewables) {
        remoteFolder.fetchPart(message, part, null);
    }
    // Store the updated message locally
    localFolder.appendMessages(Collections.singletonList(message));
    Message localMessage = localFolder.getMessage(message.getUid());
    // Set a flag indicating this message has been fully downloaded and can be
    // viewed.
    localMessage.setFlag(Flag.X_DOWNLOADED_PARTIAL, true);
}
Also used : LocalMessage(com.fsck.k9.mailstore.LocalMessage) MimeMessage(com.fsck.k9.mail.internet.MimeMessage) Message(com.fsck.k9.mail.Message) Part(com.fsck.k9.mail.Part)

Aggregations

Test (org.junit.Test)127 Message (com.fsck.k9.mail.Message)111 MimeMessage (com.fsck.k9.mail.internet.MimeMessage)102 Part (com.fsck.k9.mail.Part)47 LocalMessage (com.fsck.k9.mailstore.LocalMessage)46 MessagingException (com.fsck.k9.mail.MessagingException)41 ArrayList (java.util.ArrayList)41 MimeBodyPart (com.fsck.k9.mail.internet.MimeBodyPart)33 BodyPart (com.fsck.k9.mail.BodyPart)32 Account (com.fsck.k9.Account)27 LocalFolder (com.fsck.k9.mailstore.LocalFolder)24 TextBody (com.fsck.k9.mail.internet.TextBody)23 IOException (java.io.IOException)22 Address (com.fsck.k9.mail.Address)21 LocalStore (com.fsck.k9.mailstore.LocalStore)21 Date (java.util.Date)20 MessageReference (com.fsck.k9.activity.MessageReference)16 MimeMultipart (com.fsck.k9.mail.internet.MimeMultipart)16 Folder (com.fsck.k9.mail.Folder)14 AuthenticationFailedException (com.fsck.k9.mail.AuthenticationFailedException)13