Search in sources :

Example 1 with UnavailableStorageException

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

the class LocalFolder method moveMessages.

@Override
public Map<String, String> moveMessages(final List<? extends Message> msgs, final Folder destFolder) throws MessagingException {
    if (!(destFolder instanceof LocalFolder)) {
        throw new MessagingException("moveMessages called with non-LocalFolder");
    }
    final LocalFolder lDestFolder = (LocalFolder) destFolder;
    final Map<String, String> uidMap = new HashMap<>();
    try {
        this.localStore.database.execute(false, new DbCallback<Void>() {

            @Override
            public Void doDbWork(final SQLiteDatabase db) throws WrappedException, UnavailableStorageException {
                try {
                    lDestFolder.open(OPEN_MODE_RW);
                    for (Message message : msgs) {
                        LocalMessage lMessage = (LocalMessage) message;
                        String oldUID = message.getUid();
                        Timber.d("Updating folder_id to %s for message with UID %s, " + "id %d currently in folder %s", lDestFolder.getId(), message.getUid(), lMessage.getId(), getName());
                        String newUid = K9.LOCAL_UID_PREFIX + UUID.randomUUID().toString();
                        message.setUid(newUid);
                        uidMap.put(oldUID, newUid);
                        // Message threading in the target folder
                        ThreadInfo threadInfo = lDestFolder.doMessageThreading(db, message);
                        /*
                             * "Move" the message into the new folder
                             */
                        long msgId = lMessage.getId();
                        String[] idArg = new String[] { Long.toString(msgId) };
                        ContentValues cv = new ContentValues();
                        cv.put("folder_id", lDestFolder.getId());
                        cv.put("uid", newUid);
                        db.update("messages", cv, "id = ?", idArg);
                        // Create/update entry in 'threads' table for the message in the
                        // target folder
                        cv.clear();
                        cv.put("message_id", msgId);
                        if (threadInfo.threadId == -1) {
                            if (threadInfo.rootId != -1) {
                                cv.put("root", threadInfo.rootId);
                            }
                            if (threadInfo.parentId != -1) {
                                cv.put("parent", threadInfo.parentId);
                            }
                            db.insert("threads", null, cv);
                        } else {
                            db.update("threads", cv, "id = ?", new String[] { Long.toString(threadInfo.threadId) });
                        }
                        /*
                             * Add a placeholder message so we won't download the original
                             * message again if we synchronize before the remote move is
                             * complete.
                             */
                        // We need to open this folder to get the folder id
                        open(OPEN_MODE_RW);
                        cv.clear();
                        cv.put("uid", oldUID);
                        cv.putNull("flags");
                        cv.put("read", 1);
                        cv.put("deleted", 1);
                        cv.put("folder_id", mFolderId);
                        cv.put("empty", 0);
                        String messageId = message.getMessageId();
                        if (messageId != null) {
                            cv.put("message_id", messageId);
                        }
                        final long newId;
                        if (threadInfo.msgId != -1) {
                            // There already existed an empty message in the target folder.
                            // Let's use it as placeholder.
                            newId = threadInfo.msgId;
                            db.update("messages", cv, "id = ?", new String[] { Long.toString(newId) });
                        } else {
                            newId = db.insert("messages", null, cv);
                        }
                        /*
                             * Update old entry in 'threads' table to point to the newly
                             * created placeholder.
                             */
                        cv.clear();
                        cv.put("message_id", newId);
                        db.update("threads", cv, "id = ?", new String[] { Long.toString(lMessage.getThreadId()) });
                    }
                } catch (MessagingException e) {
                    throw new WrappedException(e);
                }
                return null;
            }
        });
        this.localStore.notifyChange();
        return uidMap;
    } catch (WrappedException e) {
        throw (MessagingException) e.getCause();
    }
}
Also used : ContentValues(android.content.ContentValues) WrappedException(com.fsck.k9.mailstore.LockableDatabase.WrappedException) MimeMessage(com.fsck.k9.mail.internet.MimeMessage) Message(com.fsck.k9.mail.Message) MessagingException(com.fsck.k9.mail.MessagingException) HashMap(java.util.HashMap) SQLiteDatabase(android.database.sqlite.SQLiteDatabase)

Example 2 with UnavailableStorageException

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

the class MessagingController method clearFolderSynchronous.

@VisibleForTesting
protected void clearFolderSynchronous(Account account, String folderName, MessagingListener listener) {
    LocalFolder localFolder = null;
    try {
        localFolder = account.getLocalStore().getFolder(folderName);
        localFolder.open(Folder.OPEN_MODE_RW);
        localFolder.clearAllMessages();
    } catch (UnavailableStorageException e) {
        Timber.i("Failed to clear folder because storage is not available - trying again later.");
        throw new UnavailableAccountException(e);
    } catch (Exception e) {
        Timber.e(e, "clearFolder failed");
        addErrorMessage(account, null, e);
    } finally {
        closeFolder(localFolder);
    }
    listFoldersSynchronous(account, false, listener);
}
Also used : LocalFolder(com.fsck.k9.mailstore.LocalFolder) UnavailableStorageException(com.fsck.k9.mailstore.UnavailableStorageException) 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) VisibleForTesting(android.support.annotation.VisibleForTesting)

Example 3 with UnavailableStorageException

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

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

the class EmailProvider method getAccountStats.

private Cursor getAccountStats(String accountUuid, String[] columns, final String selection, final String[] selectionArgs) {
    Account account = getAccount(accountUuid);
    LockableDatabase database = getDatabase(account);
    // Use default projection if none was given
    String[] sourceProjection = (columns == null) ? STATS_DEFAULT_PROJECTION : columns;
    // Create SQL query string
    final StringBuilder sql = new StringBuilder();
    sql.append("SELECT ");
    // Append projection for the database query
    // e.g. "SUM(read=0) AS unread_count, SUM(flagged) AS flagged_count"
    boolean first = true;
    for (String columnName : sourceProjection) {
        if (!first) {
            sql.append(',');
        } else {
            first = false;
        }
        if (StatsColumns.UNREAD_COUNT.equals(columnName)) {
            sql.append("SUM(" + MessageColumns.READ + "=0) AS " + StatsColumns.UNREAD_COUNT);
        } else if (StatsColumns.FLAGGED_COUNT.equals(columnName)) {
            sql.append("SUM(" + MessageColumns.FLAGGED + ") AS " + StatsColumns.FLAGGED_COUNT);
        } else {
            throw new IllegalArgumentException("Column name not allowed: " + columnName);
        }
    }
    // Table selection
    sql.append(" FROM messages");
    if (containsAny(selection, FOLDERS_COLUMNS)) {
        sql.append(" JOIN folders ON (folders.id = messages.folder_id)");
    }
    // WHERE clause
    sql.append(" WHERE (deleted = 0 AND empty = 0)");
    if (!TextUtils.isEmpty(selection)) {
        sql.append(" AND (");
        sql.append(selection);
        sql.append(")");
    }
    // Query the database and return the result cursor
    try {
        return database.execute(false, new DbCallback<Cursor>() {

            @Override
            public Cursor doDbWork(SQLiteDatabase db) throws WrappedException, UnavailableStorageException {
                return db.rawQuery(sql.toString(), selectionArgs);
            }
        });
    } catch (UnavailableStorageException e) {
        throw new RuntimeException("Storage not available", e);
    } catch (MessagingException e) {
        throw new RuntimeException("messaging exception", e);
    }
}
Also used : Account(com.fsck.k9.Account) WrappedException(com.fsck.k9.mailstore.LockableDatabase.WrappedException) MessagingException(com.fsck.k9.mail.MessagingException) UnavailableStorageException(com.fsck.k9.mailstore.UnavailableStorageException) EmailProviderCacheCursor(com.fsck.k9.cache.EmailProviderCacheCursor) Cursor(android.database.Cursor) LockableDatabase(com.fsck.k9.mailstore.LockableDatabase) SQLiteDatabase(android.database.sqlite.SQLiteDatabase)

Example 5 with UnavailableStorageException

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

the class MessagingControllerTest method clearFolderSynchronous_whenStorageUnavailable_shouldThrowUnavailableAccountException.

@Test(expected = UnavailableAccountException.class)
public void clearFolderSynchronous_whenStorageUnavailable_shouldThrowUnavailableAccountException() throws MessagingException {
    doThrow(new UnavailableStorageException("Test")).when(localFolder).open(Folder.OPEN_MODE_RW);
    controller.clearFolderSynchronous(account, FOLDER_NAME, listener);
}
Also used : UnavailableStorageException(com.fsck.k9.mailstore.UnavailableStorageException) Test(org.junit.Test)

Aggregations

MessagingException (com.fsck.k9.mail.MessagingException)5 UnavailableStorageException (com.fsck.k9.mailstore.UnavailableStorageException)5 Message (com.fsck.k9.mail.Message)3 MimeMessage (com.fsck.k9.mail.internet.MimeMessage)3 LocalFolder (com.fsck.k9.mailstore.LocalFolder)3 SQLiteDatabase (android.database.sqlite.SQLiteDatabase)2 Folder (com.fsck.k9.mail.Folder)2 Store (com.fsck.k9.mail.Store)2 Pop3Store (com.fsck.k9.mail.store.pop3.Pop3Store)2 LocalMessage (com.fsck.k9.mailstore.LocalMessage)2 LocalStore (com.fsck.k9.mailstore.LocalStore)2 WrappedException (com.fsck.k9.mailstore.LockableDatabase.WrappedException)2 HashMap (java.util.HashMap)2 SuppressLint (android.annotation.SuppressLint)1 ContentValues (android.content.ContentValues)1 Cursor (android.database.Cursor)1 VisibleForTesting (android.support.annotation.VisibleForTesting)1 Account (com.fsck.k9.Account)1 EmailProviderCacheCursor (com.fsck.k9.cache.EmailProviderCacheCursor)1 PendingCommand (com.fsck.k9.controller.MessagingControllerCommands.PendingCommand)1