Search in sources :

Example 1 with LocalMessage

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

the class MessagingController method sendPendingMessagesSynchronous.

/**
     * Attempt to send any messages that are sitting in the Outbox.
     */
@VisibleForTesting
protected void sendPendingMessagesSynchronous(final Account account) {
    LocalFolder localFolder = null;
    Exception lastFailure = null;
    boolean wasPermanentFailure = false;
    try {
        LocalStore localStore = account.getLocalStore();
        localFolder = localStore.getFolder(account.getOutboxFolderName());
        if (!localFolder.exists()) {
            Timber.v("Outbox does not exist");
            return;
        }
        for (MessagingListener l : getListeners()) {
            l.sendPendingMessagesStarted(account);
        }
        localFolder.open(Folder.OPEN_MODE_RW);
        List<LocalMessage> localMessages = localFolder.getMessages(null);
        int progress = 0;
        int todo = localMessages.size();
        for (MessagingListener l : getListeners()) {
            l.synchronizeMailboxProgress(account, account.getSentFolderName(), progress, todo);
        }
        /*
             * The profile we will use to pull all of the content
             * for a given local message into memory for sending.
             */
        FetchProfile fp = new FetchProfile();
        fp.add(FetchProfile.Item.ENVELOPE);
        fp.add(FetchProfile.Item.BODY);
        Timber.i("Scanning folder '%s' (%d) for messages to send", account.getOutboxFolderName(), localFolder.getId());
        Transport transport = transportProvider.getTransport(K9.app, account);
        for (LocalMessage message : localMessages) {
            if (message.isSet(Flag.DELETED)) {
                message.destroy();
                continue;
            }
            try {
                AtomicInteger count = new AtomicInteger(0);
                AtomicInteger oldCount = sendCount.putIfAbsent(message.getUid(), count);
                if (oldCount != null) {
                    count = oldCount;
                }
                Timber.i("Send count for message %s is %d", message.getUid(), count.get());
                if (count.incrementAndGet() > K9.MAX_SEND_ATTEMPTS) {
                    Timber.e("Send count for message %s can't be delivered after %d attempts. " + "Giving up until the user restarts the device", message.getUid(), MAX_SEND_ATTEMPTS);
                    notificationController.showSendFailedNotification(account, new MessagingException(message.getSubject()));
                    continue;
                }
                localFolder.fetch(Collections.singletonList(message), fp, null);
                try {
                    if (message.getHeader(K9.IDENTITY_HEADER).length > 0) {
                        Timber.v("The user has set the Outbox and Drafts folder to the same thing. " + "This message appears to be a draft, so K-9 will not send it");
                        continue;
                    }
                    message.setFlag(Flag.X_SEND_IN_PROGRESS, true);
                    Timber.i("Sending message with UID %s", message.getUid());
                    transport.sendMessage(message);
                    message.setFlag(Flag.X_SEND_IN_PROGRESS, false);
                    message.setFlag(Flag.SEEN, true);
                    progress++;
                    for (MessagingListener l : getListeners()) {
                        l.synchronizeMailboxProgress(account, account.getSentFolderName(), progress, todo);
                    }
                    moveOrDeleteSentMessage(account, localStore, localFolder, message);
                } catch (AuthenticationFailedException e) {
                    lastFailure = e;
                    wasPermanentFailure = false;
                    handleAuthenticationFailure(account, false);
                    handleSendFailure(account, localStore, localFolder, message, e, wasPermanentFailure);
                } catch (CertificateValidationException e) {
                    lastFailure = e;
                    wasPermanentFailure = false;
                    notifyUserIfCertificateProblem(account, e, false);
                    handleSendFailure(account, localStore, localFolder, message, e, wasPermanentFailure);
                } catch (MessagingException e) {
                    lastFailure = e;
                    wasPermanentFailure = e.isPermanentFailure();
                    handleSendFailure(account, localStore, localFolder, message, e, wasPermanentFailure);
                } catch (Exception e) {
                    lastFailure = e;
                    wasPermanentFailure = true;
                    handleSendFailure(account, localStore, localFolder, message, e, wasPermanentFailure);
                }
            } catch (Exception e) {
                lastFailure = e;
                wasPermanentFailure = false;
                Timber.e(e, "Failed to fetch message for sending");
                addErrorMessage(account, "Failed to fetch message for sending", e);
                notifySynchronizeMailboxFailed(account, localFolder, e);
            }
        }
        for (MessagingListener l : getListeners()) {
            l.sendPendingMessagesCompleted(account);
        }
        if (lastFailure != null) {
            if (wasPermanentFailure) {
                notificationController.showSendFailedNotification(account, lastFailure);
            } else {
                notificationController.showSendFailedNotification(account, lastFailure);
            }
        }
    } catch (UnavailableStorageException e) {
        Timber.i("Failed to send pending messages because storage is not available - trying again later.");
        throw new UnavailableAccountException(e);
    } catch (Exception e) {
        Timber.v(e, "Failed to send pending messages");
        for (MessagingListener l : getListeners()) {
            l.sendPendingMessagesFailed(account);
        }
        addErrorMessage(account, null, e);
    } finally {
        if (lastFailure == null) {
            notificationController.clearSendFailedNotification(account);
        }
        closeFolder(localFolder);
    }
}
Also used : LocalMessage(com.fsck.k9.mailstore.LocalMessage) FetchProfile(com.fsck.k9.mail.FetchProfile) MessagingException(com.fsck.k9.mail.MessagingException) AuthenticationFailedException(com.fsck.k9.mail.AuthenticationFailedException) UnavailableStorageException(com.fsck.k9.mailstore.UnavailableStorageException) 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) SuppressLint(android.annotation.SuppressLint) LocalFolder(com.fsck.k9.mailstore.LocalFolder) AtomicInteger(java.util.concurrent.atomic.AtomicInteger) CertificateValidationException(com.fsck.k9.mail.CertificateValidationException) Transport(com.fsck.k9.mail.Transport) VisibleForTesting(android.support.annotation.VisibleForTesting)

Example 2 with LocalMessage

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

the class MessagingController method downloadSaneBody.

private void downloadSaneBody(Account account, Folder remoteFolder, LocalFolder localFolder, Message message) throws MessagingException {
    /*
         * The provider was unable to get the structure of the message, so
         * we'll download a reasonable portion of the messge and mark it as
         * incomplete so the entire thing can be downloaded later if the user
         * wishes to download it.
         */
    FetchProfile fp = new FetchProfile();
    fp.add(FetchProfile.Item.BODY_SANE);
    /*
                 *  TODO a good optimization here would be to make sure that all Stores set
                 *  the proper size after this fetch and compare the before and after size. If
                 *  they equal we can mark this SYNCHRONIZED instead of PARTIALLY_SYNCHRONIZED
                 */
    remoteFolder.fetch(Collections.singletonList(message), fp, null);
    // Store the updated message locally
    localFolder.appendMessages(Collections.singletonList(message));
    Message localMessage = localFolder.getMessage(message.getUid());
    // Certain (POP3) servers give you the whole message even when you ask for only the first x Kb
    if (!message.isSet(Flag.X_DOWNLOADED_FULL)) {
        /*
                     * Mark the message as fully downloaded if the message size is smaller than
                     * the account's autodownload size limit, otherwise mark as only a partial
                     * download.  This will prevent the system from downloading the same message
                     * twice.
                     *
                     * If there is no limit on autodownload size, that's the same as the message
                     * being smaller than the max size
                     */
        if (account.getMaximumAutoDownloadMessageSize() == 0 || message.getSize() < account.getMaximumAutoDownloadMessageSize()) {
            localMessage.setFlag(Flag.X_DOWNLOADED_FULL, true);
        } else {
            // Set a flag indicating that the message has been partially downloaded and
            // is ready for view.
            localMessage.setFlag(Flag.X_DOWNLOADED_PARTIAL, true);
        }
    }
}
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)

Example 3 with LocalMessage

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

the class MessagingController method searchLocalMessagesSynchronous.

@VisibleForTesting
void searchLocalMessagesSynchronous(final LocalSearch search, final MessagingListener listener) {
    final AccountStats stats = new AccountStats();
    final Set<String> uuidSet = new HashSet<>(Arrays.asList(search.getAccountUuids()));
    List<Account> accounts = Preferences.getPreferences(context).getAccounts();
    boolean allAccounts = uuidSet.contains(SearchSpecification.ALL_ACCOUNTS);
    // for every account we want to search do the query in the localstore
    for (final Account account : accounts) {
        if (!allAccounts && !uuidSet.contains(account.getUuid())) {
            continue;
        }
        // Collecting statistics of the search result
        MessageRetrievalListener<LocalMessage> retrievalListener = new MessageRetrievalListener<LocalMessage>() {

            @Override
            public void messageStarted(String message, int number, int ofTotal) {
            }

            @Override
            public void messagesFinished(int number) {
            }

            @Override
            public void messageFinished(LocalMessage message, int number, int ofTotal) {
                if (!isMessageSuppressed(message)) {
                    List<LocalMessage> messages = new ArrayList<>();
                    messages.add(message);
                    stats.unreadMessageCount += (!message.isSet(Flag.SEEN)) ? 1 : 0;
                    stats.flaggedMessageCount += (message.isSet(Flag.FLAGGED)) ? 1 : 0;
                    if (listener != null) {
                        listener.listLocalMessagesAddMessages(account, null, messages);
                    }
                }
            }
        };
        // build and do the query in the localstore
        try {
            LocalStore localStore = account.getLocalStore();
            localStore.searchForMessages(retrievalListener, search);
        } catch (Exception e) {
            addErrorMessage(account, null, e);
        }
    }
    // publish the total search statistics
    if (listener != null) {
        listener.searchStats(stats);
    }
}
Also used : SearchAccount(com.fsck.k9.search.SearchAccount) Account(com.fsck.k9.Account) LocalMessage(com.fsck.k9.mailstore.LocalMessage) ArrayList(java.util.ArrayList) 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) MessageRetrievalListener(com.fsck.k9.mail.MessageRetrievalListener) AccountStats(com.fsck.k9.AccountStats) HashSet(java.util.HashSet) VisibleForTesting(android.support.annotation.VisibleForTesting)

Example 4 with LocalMessage

use of com.fsck.k9.mailstore.LocalMessage 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 5 with LocalMessage

use of com.fsck.k9.mailstore.LocalMessage 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)

Aggregations

LocalMessage (com.fsck.k9.mailstore.LocalMessage)42 Test (org.junit.Test)23 FetchProfile (com.fsck.k9.mail.FetchProfile)19 Message (com.fsck.k9.mail.Message)19 MimeMessage (com.fsck.k9.mail.internet.MimeMessage)19 MessagingException (com.fsck.k9.mail.MessagingException)15 LocalFolder (com.fsck.k9.mailstore.LocalFolder)13 LocalStore (com.fsck.k9.mailstore.LocalStore)12 SQLiteDatabase (android.database.sqlite.SQLiteDatabase)10 ArrayList (java.util.ArrayList)9 Notification (android.app.Notification)8 Part (com.fsck.k9.mail.Part)8 MessageReference (com.fsck.k9.activity.MessageReference)7 Multipart (com.fsck.k9.mail.Multipart)7 Date (java.util.Date)7 HashMap (java.util.HashMap)7 SuppressLint (android.annotation.SuppressLint)6 UnavailableStorageException (com.fsck.k9.mailstore.UnavailableStorageException)6 IOException (java.io.IOException)6 AuthenticationFailedException (com.fsck.k9.mail.AuthenticationFailedException)5