Search in sources :

Example 6 with FetchProfile

use of com.fsck.k9.mail.FetchProfile 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 7 with FetchProfile

use of com.fsck.k9.mail.FetchProfile 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 FetchProfile

use of com.fsck.k9.mail.FetchProfile 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 9 with FetchProfile

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

the class MigrationTest method migrateTextHtml.

@Test
public void migrateTextHtml() throws Exception {
    SQLiteDatabase db = createV50Database();
    insertMultipartAlternativeMessage(db);
    db.close();
    LocalStore localStore = LocalStore.getInstance(account, RuntimeEnvironment.application);
    LocalMessage msg = localStore.getFolder("dev").getMessage("9");
    FetchProfile fp = new FetchProfile();
    fp.add(FetchProfile.Item.BODY);
    localStore.getFolder("dev").fetch(Collections.singletonList(msg), fp, null);
    Assert.assertEquals(8, msg.getId());
    Assert.assertEquals(9, msg.getHeaderNames().size());
    Assert.assertEquals("multipart/alternative", msg.getMimeType());
    Assert.assertEquals(0, msg.getAttachmentCount());
    Multipart msgBody = (Multipart) msg.getBody();
    Assert.assertEquals("------------060200010509000000040004", msgBody.getBoundary());
}
Also used : FetchProfile(com.fsck.k9.mail.FetchProfile) Multipart(com.fsck.k9.mail.Multipart) SQLiteDatabase(android.database.sqlite.SQLiteDatabase) Test(org.junit.Test)

Example 10 with FetchProfile

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

the class MigrationTest method migratePgpInlineEncryptedMessage.

@Test
public void migratePgpInlineEncryptedMessage() throws Exception {
    SQLiteDatabase db = createV50Database();
    insertPgpInlineEncryptedMessage(db);
    db.close();
    LocalStore localStore = LocalStore.getInstance(account, RuntimeEnvironment.application);
    LocalMessage msg = localStore.getFolder("dev").getMessage("7");
    FetchProfile fp = new FetchProfile();
    fp.add(FetchProfile.Item.BODY);
    localStore.getFolder("dev").fetch(Collections.singletonList(msg), fp, null);
    Assert.assertEquals(6, msg.getId());
    Assert.assertEquals(12, msg.getHeaderNames().size());
    Assert.assertEquals("text/plain", msg.getMimeType());
    Assert.assertEquals(0, msg.getAttachmentCount());
    Assert.assertTrue(msg.getBody() instanceof BinaryMemoryBody);
    String msgTextContent = MessageExtractor.getTextFromPart(msg);
    Assert.assertEquals(OpenPgpUtils.PARSE_RESULT_MESSAGE, OpenPgpUtils.parseMessage(msgTextContent));
}
Also used : FetchProfile(com.fsck.k9.mail.FetchProfile) SQLiteDatabase(android.database.sqlite.SQLiteDatabase) Test(org.junit.Test)

Aggregations

FetchProfile (com.fsck.k9.mail.FetchProfile)49 Test (org.junit.Test)27 LocalMessage (com.fsck.k9.mailstore.LocalMessage)15 MessagingException (com.fsck.k9.mail.MessagingException)12 ArrayList (java.util.ArrayList)10 LocalFolder (com.fsck.k9.mailstore.LocalFolder)9 LocalStore (com.fsck.k9.mailstore.LocalStore)9 SQLiteDatabase (android.database.sqlite.SQLiteDatabase)8 Date (java.util.Date)8 Message (com.fsck.k9.mail.Message)7 SuppressLint (android.annotation.SuppressLint)6 MimeMessage (com.fsck.k9.mail.internet.MimeMessage)6 AuthenticationFailedException (com.fsck.k9.mail.AuthenticationFailedException)5 Multipart (com.fsck.k9.mail.Multipart)5 ByteArrayInputStream (java.io.ByteArrayInputStream)5 IOException (java.io.IOException)5 WebDavMessage (com.fsck.k9.mail.store.webdav.WebDavMessage)4 LinkedList (java.util.LinkedList)4 HttpResponse (org.apache.http.HttpResponse)4 StatusLine (org.apache.http.StatusLine)4