Search in sources :

Example 6 with Message

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

the class MessagingController method syncFlags.

private boolean syncFlags(LocalMessage localMessage, Message remoteMessage) throws MessagingException {
    boolean messageChanged = false;
    if (localMessage == null || localMessage.isSet(Flag.DELETED)) {
        return false;
    }
    if (remoteMessage.isSet(Flag.DELETED)) {
        if (localMessage.getFolder().syncRemoteDeletions()) {
            localMessage.setFlag(Flag.DELETED, true);
            messageChanged = true;
        }
    } else {
        for (Flag flag : MessagingController.SYNC_FLAGS) {
            if (remoteMessage.isSet(flag) != localMessage.isSet(flag)) {
                localMessage.setFlag(flag, remoteMessage.isSet(flag));
                messageChanged = true;
            }
        }
    }
    return messageChanged;
}
Also used : PendingSetFlag(com.fsck.k9.controller.MessagingControllerCommands.PendingSetFlag) Flag(com.fsck.k9.mail.Flag)

Example 7 with Message

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

the class MessagingController method downloadMessages.

/**
     * Fetches the messages described by inputMessages from the remote store and writes them to
     * local storage.
     *
     * @param account
     *         The account the remote store belongs to.
     * @param remoteFolder
     *         The remote folder to download messages from.
     * @param localFolder
     *         The {@link LocalFolder} instance corresponding to the remote folder.
     * @param inputMessages
     *         A list of messages objects that store the UIDs of which messages to download.
     * @param flagSyncOnly
     *         Only flags will be fetched from the remote store if this is {@code true}.
     * @param purgeToVisibleLimit
     *         If true, local messages will be purged down to the limit of visible messages.
     *
     * @return The number of downloaded messages that are not flagged as {@link Flag#SEEN}.
     *
     * @throws MessagingException
     */
private int downloadMessages(final Account account, final Folder remoteFolder, final LocalFolder localFolder, List<Message> inputMessages, boolean flagSyncOnly, boolean purgeToVisibleLimit) throws MessagingException {
    final Date earliestDate = account.getEarliestPollDate();
    // now
    Date downloadStarted = new Date();
    if (earliestDate != null) {
        Timber.d("Only syncing messages after %s", earliestDate);
    }
    final String folder = remoteFolder.getName();
    int unreadBeforeStart = 0;
    try {
        AccountStats stats = account.getStats(context);
        unreadBeforeStart = stats.unreadMessageCount;
    } catch (MessagingException e) {
        Timber.e(e, "Unable to getUnreadMessageCount for account: %s", account);
    }
    List<Message> syncFlagMessages = new ArrayList<>();
    List<Message> unsyncedMessages = new ArrayList<>();
    final AtomicInteger newMessages = new AtomicInteger(0);
    List<Message> messages = new ArrayList<>(inputMessages);
    for (Message message : messages) {
        evaluateMessageForDownload(message, folder, localFolder, remoteFolder, account, unsyncedMessages, syncFlagMessages, flagSyncOnly);
    }
    final AtomicInteger progress = new AtomicInteger(0);
    final int todo = unsyncedMessages.size() + syncFlagMessages.size();
    for (MessagingListener l : getListeners()) {
        l.synchronizeMailboxProgress(account, folder, progress.get(), todo);
    }
    Timber.d("SYNC: Have %d unsynced messages", unsyncedMessages.size());
    messages.clear();
    final List<Message> largeMessages = new ArrayList<>();
    final List<Message> smallMessages = new ArrayList<>();
    if (!unsyncedMessages.isEmpty()) {
        /*
             * Reverse the order of the messages. Depending on the server this may get us
             * fetch results for newest to oldest. If not, no harm done.
             */
        Collections.sort(unsyncedMessages, new UidReverseComparator());
        int visibleLimit = localFolder.getVisibleLimit();
        int listSize = unsyncedMessages.size();
        if ((visibleLimit > 0) && (listSize > visibleLimit)) {
            unsyncedMessages = unsyncedMessages.subList(0, visibleLimit);
        }
        FetchProfile fp = new FetchProfile();
        if (remoteFolder.supportsFetchingFlags()) {
            fp.add(FetchProfile.Item.FLAGS);
        }
        fp.add(FetchProfile.Item.ENVELOPE);
        Timber.d("SYNC: About to fetch %d unsynced messages for folder %s", unsyncedMessages.size(), folder);
        fetchUnsyncedMessages(account, remoteFolder, unsyncedMessages, smallMessages, largeMessages, progress, todo, fp);
        String updatedPushState = localFolder.getPushState();
        for (Message message : unsyncedMessages) {
            String newPushState = remoteFolder.getNewPushState(updatedPushState, message);
            if (newPushState != null) {
                updatedPushState = newPushState;
            }
        }
        localFolder.setPushState(updatedPushState);
        Timber.d("SYNC: Synced unsynced messages for folder %s", folder);
    }
    Timber.d("SYNC: Have %d large messages and %d small messages out of %d unsynced messages", largeMessages.size(), smallMessages.size(), unsyncedMessages.size());
    unsyncedMessages.clear();
    /*
         * Grab the content of the small messages first. This is going to
         * be very fast and at very worst will be a single up of a few bytes and a single
         * download of 625k.
         */
    FetchProfile fp = new FetchProfile();
    //TODO: Only fetch small and large messages if we have some
    fp.add(FetchProfile.Item.BODY);
    //        fp.add(FetchProfile.Item.FLAGS);
    //        fp.add(FetchProfile.Item.ENVELOPE);
    downloadSmallMessages(account, remoteFolder, localFolder, smallMessages, progress, unreadBeforeStart, newMessages, todo, fp);
    smallMessages.clear();
    /*
         * Now do the large messages that require more round trips.
         */
    fp = new FetchProfile();
    fp.add(FetchProfile.Item.STRUCTURE);
    downloadLargeMessages(account, remoteFolder, localFolder, largeMessages, progress, unreadBeforeStart, newMessages, todo, fp);
    largeMessages.clear();
    /*
         * Refresh the flags for any messages in the local store that we didn't just
         * download.
         */
    refreshLocalMessageFlags(account, remoteFolder, localFolder, syncFlagMessages, progress, todo);
    Timber.d("SYNC: Synced remote messages for folder %s, %d new messages", folder, newMessages.get());
    if (purgeToVisibleLimit) {
        localFolder.purgeToVisibleLimit(new MessageRemovalListener() {

            @Override
            public void messageRemoved(Message message) {
                for (MessagingListener l : getListeners()) {
                    l.synchronizeMailboxRemovedMessage(account, folder, message);
                }
            }
        });
    }
    // If the oldest message seen on this sync is newer than
    // the oldest message seen on the previous sync, then
    // we want to move our high-water mark forward
    // this is all here just for pop which only syncs inbox
    // this would be a little wrong for IMAP (we'd want a folder-level pref, not an account level pref.)
    // fortunately, we just don't care.
    Long oldestMessageTime = localFolder.getOldestMessageDate();
    if (oldestMessageTime != null) {
        Date oldestExtantMessage = new Date(oldestMessageTime);
        if (oldestExtantMessage.before(downloadStarted) && oldestExtantMessage.after(new Date(account.getLatestOldMessageSeenTime()))) {
            account.setLatestOldMessageSeenTime(oldestExtantMessage.getTime());
            account.save(Preferences.getPreferences(context));
        }
    }
    return newMessages.get();
}
Also used : 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) MessagingException(com.fsck.k9.mail.MessagingException) ArrayList(java.util.ArrayList) Date(java.util.Date) SuppressLint(android.annotation.SuppressLint) MessageRemovalListener(com.fsck.k9.mailstore.MessageRemovalListener) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) AccountStats(com.fsck.k9.AccountStats)

Example 8 with Message

use of com.fsck.k9.mail.Message 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(final Account account, final Message message, MessagingListener listener) {
    try {
        LocalStore localStore = account.getLocalStore();
        LocalFolder localFolder = localStore.getFolder(account.getOutboxFolderName());
        localFolder.open(Folder.OPEN_MODE_RW);
        localFolder.appendMessages(Collections.singletonList(message));
        Message localMessage = localFolder.getMessage(message.getUid());
        localMessage.setFlag(Flag.X_DOWNLOADED_FULL, true);
        localFolder.close();
        sendPendingMessages(account, listener);
    } catch (Exception e) {
        /*
            for (MessagingListener l : getListeners())
            {
                // TODO general failed
            }
            */
        addErrorMessage(account, null, e);
    }
}
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) LocalStore(com.fsck.k9.mailstore.LocalStore) CertificateValidationException(com.fsck.k9.mail.CertificateValidationException) UnavailableStorageException(com.fsck.k9.mailstore.UnavailableStorageException) IOException(java.io.IOException) MessagingException(com.fsck.k9.mail.MessagingException) AuthenticationFailedException(com.fsck.k9.mail.AuthenticationFailedException)

Example 9 with Message

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

the class MessagingController method loadMessage.

public LocalMessage loadMessage(Account account, String folderName, String uid) throws MessagingException {
    LocalStore localStore = account.getLocalStore();
    LocalFolder localFolder = localStore.getFolder(folderName);
    localFolder.open(Folder.OPEN_MODE_RW);
    LocalMessage message = localFolder.getMessage(uid);
    if (message == null || message.getId() == 0) {
        throw new IllegalArgumentException("Message not found: folder=" + folderName + ", uid=" + uid);
    }
    FetchProfile fp = new FetchProfile();
    fp.add(FetchProfile.Item.BODY);
    localFolder.fetch(Collections.singletonList(message), fp, null);
    localFolder.close();
    notificationController.removeNewMailNotification(account, message.makeMessageReference());
    markMessageAsReadOnView(account, message);
    return message;
}
Also used : LocalFolder(com.fsck.k9.mailstore.LocalFolder) LocalMessage(com.fsck.k9.mailstore.LocalMessage) FetchProfile(com.fsck.k9.mail.FetchProfile) LocalStore(com.fsck.k9.mailstore.LocalStore)

Example 10 with Message

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

the class MessagingController method setFlag.

/**
     * Set or remove a flag for a set of messages in a specific folder.
     * <p>
     * <p>
     * The {@link Message} objects passed in are updated to reflect the new flag state.
     * </p>
     *
     * @param account
     *         The account the folder containing the messages belongs to.
     * @param folderName
     *         The name of the folder.
     * @param messages
     *         The messages to change the flag for.
     * @param flag
     *         The flag to change.
     * @param newState
     *         {@code true}, if the flag should be set. {@code false} if it should be removed.
     */
public void setFlag(Account account, String folderName, List<? extends Message> messages, Flag flag, boolean newState) {
    // TODO: Put this into the background, but right now some callers depend on the message
    //       objects being modified right after this method returns.
    Folder localFolder = null;
    try {
        Store localStore = account.getLocalStore();
        localFolder = localStore.getFolder(folderName);
        localFolder.open(Folder.OPEN_MODE_RW);
        // Allows for re-allowing sending of messages that could not be sent
        if (flag == Flag.FLAGGED && !newState && account.getOutboxFolderName().equals(folderName)) {
            for (Message message : messages) {
                String uid = message.getUid();
                if (uid != null) {
                    sendCount.remove(uid);
                }
            }
        }
        // Update the messages in the local store
        localFolder.setFlags(messages, Collections.singleton(flag), newState);
        int unreadMessageCount = localFolder.getUnreadMessageCount();
        for (MessagingListener l : getListeners()) {
            l.folderStatusChanged(account, folderName, unreadMessageCount);
        }
        // TODO: Skip the remote part for all local-only folders
        if (account.getErrorFolderName().equals(folderName)) {
            return;
        }
        List<String> uids = getUidsFromMessages(messages);
        queueSetFlag(account, folderName, newState, flag, uids);
        processPendingCommands(account);
    } catch (MessagingException me) {
        addErrorMessage(account, null, me);
        throw new RuntimeException(me);
    } finally {
        closeFolder(localFolder);
    }
}
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) 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) SuppressLint(android.annotation.SuppressLint)

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