Search in sources :

Example 51 with LocalStore

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

the class MessagingController method moveOrCopyMessageSynchronous.

private void moveOrCopyMessageSynchronous(final Account account, final String srcFolder, final List<? extends Message> inMessages, final String destFolder, final boolean isCopy) {
    try {
        LocalStore localStore = account.getLocalStore();
        Store remoteStore = account.getRemoteStore();
        if (!isCopy && (!remoteStore.isMoveCapable() || !localStore.isMoveCapable())) {
            return;
        }
        if (isCopy && (!remoteStore.isCopyCapable() || !localStore.isCopyCapable())) {
            return;
        }
        LocalFolder localSrcFolder = localStore.getFolder(srcFolder);
        Folder localDestFolder = localStore.getFolder(destFolder);
        boolean unreadCountAffected = false;
        List<String> uids = new LinkedList<>();
        for (Message message : inMessages) {
            String uid = message.getUid();
            if (!uid.startsWith(K9.LOCAL_UID_PREFIX)) {
                uids.add(uid);
            }
            if (!unreadCountAffected && !message.isSet(Flag.SEEN)) {
                unreadCountAffected = true;
            }
        }
        List<LocalMessage> messages = localSrcFolder.getMessagesByUids(uids);
        if (messages.size() > 0) {
            Map<String, Message> origUidMap = new HashMap<>();
            for (Message message : messages) {
                origUidMap.put(message.getUid(), message);
            }
            Timber.i("moveOrCopyMessageSynchronous: source folder = %s, %d messages, destination folder = %s, " + "isCopy = %s", srcFolder, messages.size(), destFolder, isCopy);
            Map<String, String> uidMap;
            if (isCopy) {
                FetchProfile fp = new FetchProfile();
                fp.add(Item.ENVELOPE);
                fp.add(Item.BODY);
                localSrcFolder.fetch(messages, fp, null);
                uidMap = localSrcFolder.copyMessages(messages, localDestFolder);
                if (unreadCountAffected) {
                    // If this copy operation changes the unread count in the destination
                    // folder, notify the listeners.
                    int unreadMessageCount = localDestFolder.getUnreadMessageCount();
                    for (MessagingListener l : getListeners()) {
                        l.folderStatusChanged(account, destFolder, unreadMessageCount);
                    }
                }
            } else {
                uidMap = localSrcFolder.moveMessages(messages, localDestFolder);
                for (Entry<String, Message> entry : origUidMap.entrySet()) {
                    String origUid = entry.getKey();
                    Message message = entry.getValue();
                    for (MessagingListener l : getListeners()) {
                        l.messageUidChanged(account, srcFolder, origUid, message.getUid());
                    }
                }
                unsuppressMessages(account, messages);
                if (unreadCountAffected) {
                    // If this move operation changes the unread count, notify the listeners
                    // that the unread count changed in both the source and destination folder.
                    int unreadMessageCountSrc = localSrcFolder.getUnreadMessageCount();
                    int unreadMessageCountDest = localDestFolder.getUnreadMessageCount();
                    for (MessagingListener l : getListeners()) {
                        l.folderStatusChanged(account, srcFolder, unreadMessageCountSrc);
                        l.folderStatusChanged(account, destFolder, unreadMessageCountDest);
                    }
                }
            }
            List<String> origUidKeys = new ArrayList<>(origUidMap.keySet());
            queueMoveOrCopy(account, srcFolder, destFolder, isCopy, origUidKeys, uidMap);
        }
        processPendingCommands(account);
    } catch (UnavailableStorageException e) {
        Timber.i("Failed to move/copy message because storage is not available - trying again later.");
        throw new UnavailableAccountException(e);
    } catch (MessagingException me) {
        addErrorMessage(account, null, me);
        throw new RuntimeException("Error moving message", me);
    }
}
Also used : 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) ConcurrentHashMap(java.util.concurrent.ConcurrentHashMap) HashMap(java.util.HashMap) MessagingException(com.fsck.k9.mail.MessagingException) UnavailableStorageException(com.fsck.k9.mailstore.UnavailableStorageException) ArrayList(java.util.ArrayList) 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) LinkedList(java.util.LinkedList) SuppressLint(android.annotation.SuppressLint) LocalFolder(com.fsck.k9.mailstore.LocalFolder)

Example 52 with LocalStore

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

the class MessagingController method setFlagSynchronous.

private void setFlagSynchronous(final Account account, final List<Long> ids, final Flag flag, final boolean newState, final boolean threadedList) {
    LocalStore localStore;
    try {
        localStore = account.getLocalStore();
    } catch (MessagingException e) {
        Timber.e(e, "Couldn't get LocalStore instance");
        return;
    }
    // can be updated with the new state.
    try {
        if (threadedList) {
            localStore.setFlagForThreads(ids, flag, newState);
            removeFlagForThreadsFromCache(account, ids, flag);
        } else {
            localStore.setFlag(ids, flag, newState);
            removeFlagFromCache(account, ids, flag);
        }
    } catch (MessagingException e) {
        Timber.e(e, "Couldn't set flags in local database");
    }
    // Read folder name and UID of messages from the database
    Map<String, List<String>> folderMap;
    try {
        folderMap = localStore.getFoldersAndUids(ids, threadedList);
    } catch (MessagingException e) {
        Timber.e(e, "Couldn't get folder name and UID of messages");
        return;
    }
    // Loop over all folders
    for (Entry<String, List<String>> entry : folderMap.entrySet()) {
        String folderName = entry.getKey();
        // Notify listeners of changed folder status
        LocalFolder localFolder = localStore.getFolder(folderName);
        try {
            int unreadMessageCount = localFolder.getUnreadMessageCount();
            for (MessagingListener l : getListeners()) {
                l.folderStatusChanged(account, folderName, unreadMessageCount);
            }
        } catch (MessagingException e) {
            Timber.w(e, "Couldn't get unread count for folder: %s", folderName);
        }
        // TODO: Skip the remote part for all local-only folders
        if (account.getErrorFolderName().equals(folderName)) {
            continue;
        }
        // Send flag change to server
        queueSetFlag(account, folderName, newState, flag, entry.getValue());
        processPendingCommands(account);
    }
}
Also used : LocalFolder(com.fsck.k9.mailstore.LocalFolder) MessagingException(com.fsck.k9.mail.MessagingException) ArrayList(java.util.ArrayList) List(java.util.List) LinkedList(java.util.LinkedList) LocalStore(com.fsck.k9.mailstore.LocalStore) SuppressLint(android.annotation.SuppressLint)

Example 53 with LocalStore

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

the class MessagingController method setFlag.

/**
     * Set or remove a flag for a message referenced by message UID.
     *
     * @param account
     *         The account the folder containing the message belongs to.
     * @param folderName
     *         The name of the folder.
     * @param uid
     *         The UID of the message 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, String uid, Flag flag, boolean newState) {
    Folder localFolder = null;
    try {
        LocalStore localStore = account.getLocalStore();
        localFolder = localStore.getFolder(folderName);
        localFolder.open(Folder.OPEN_MODE_RW);
        Message message = localFolder.getMessage(uid);
        if (message != null) {
            setFlag(account, folderName, Collections.singletonList(message), flag, newState);
        }
    } 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) Folder(com.fsck.k9.mail.Folder) LocalFolder(com.fsck.k9.mailstore.LocalFolder)

Example 54 with LocalStore

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

the class MessagingController method collectMessagesInThreads.

private static List<Message> collectMessagesInThreads(Account account, List<? extends Message> messages) throws MessagingException {
    LocalStore localStore = account.getLocalStore();
    List<Message> messagesInThreads = new ArrayList<>();
    for (Message message : messages) {
        LocalMessage localMessage = (LocalMessage) message;
        long rootId = localMessage.getRootId();
        long threadId = (rootId == -1) ? localMessage.getThreadId() : rootId;
        List<? extends Message> messagesInThread = localStore.getMessagesInThread(threadId);
        messagesInThreads.addAll(messagesInThread);
    }
    return messagesInThreads;
}
Also used : LocalMessage(com.fsck.k9.mailstore.LocalMessage) LocalMessage(com.fsck.k9.mailstore.LocalMessage) MimeMessage(com.fsck.k9.mail.internet.MimeMessage) Message(com.fsck.k9.mail.Message) ArrayList(java.util.ArrayList) LocalStore(com.fsck.k9.mailstore.LocalStore)

Example 55 with LocalStore

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

the class SettingsImporter method importAccount.

private static AccountDescriptionPair importAccount(Context context, StorageEditor editor, int contentVersion, ImportedAccount account, boolean overwrite) throws InvalidSettingValueException {
    AccountDescription original = new AccountDescription(account.name, account.uuid);
    Preferences prefs = Preferences.getPreferences(context);
    List<Account> accounts = prefs.getAccounts();
    String uuid = account.uuid;
    Account existingAccount = prefs.getAccount(uuid);
    boolean mergeImportedAccount = (overwrite && existingAccount != null);
    if (!overwrite && existingAccount != null) {
        // An account with this UUID already exists, but we're not allowed to overwrite it.
        // So generate a new UUID.
        uuid = UUID.randomUUID().toString();
    }
    // Make sure the account name is unique
    String accountName = account.name;
    if (isAccountNameUsed(accountName, accounts)) {
        // number >= 1 that results in an unused account name.
        for (int i = 1; i <= accounts.size(); i++) {
            accountName = account.name + " (" + i + ")";
            if (!isAccountNameUsed(accountName, accounts)) {
                break;
            }
        }
    }
    // Write account name
    String accountKeyPrefix = uuid + ".";
    putString(editor, accountKeyPrefix + Account.ACCOUNT_DESCRIPTION_KEY, accountName);
    if (account.incoming == null) {
        // We don't import accounts without incoming server settings
        throw new InvalidSettingValueException();
    }
    // Write incoming server settings (storeUri)
    ServerSettings incoming = new ImportedServerSettings(account.incoming);
    String storeUri = RemoteStore.createStoreUri(incoming);
    putString(editor, accountKeyPrefix + Account.STORE_URI_KEY, Base64.encode(storeUri));
    // Mark account as disabled if the AuthType isn't EXTERNAL and the
    // settings file didn't contain a password
    boolean createAccountDisabled = AuthType.EXTERNAL != incoming.authenticationType && (incoming.password == null || incoming.password.isEmpty());
    if (account.outgoing == null && !ServerSettings.Type.WebDAV.name().equals(account.incoming.type)) {
        // All account types except WebDAV need to provide outgoing server settings
        throw new InvalidSettingValueException();
    }
    if (account.outgoing != null) {
        // Write outgoing server settings (transportUri)
        ServerSettings outgoing = new ImportedServerSettings(account.outgoing);
        String transportUri = Transport.createTransportUri(outgoing);
        putString(editor, accountKeyPrefix + Account.TRANSPORT_URI_KEY, Base64.encode(transportUri));
        /*
             * Mark account as disabled if the settings file contained a username but no password. However, no password
             * is required for the outgoing server for WebDAV accounts, because incoming and outgoing servers are 
             * identical for this account type. Nor is a password required if the AuthType is EXTERNAL.
             */
        boolean outgoingPasswordNeeded = AuthType.EXTERNAL != outgoing.authenticationType && !(ServerSettings.Type.WebDAV == outgoing.type) && outgoing.username != null && !outgoing.username.isEmpty() && (outgoing.password == null || outgoing.password.isEmpty());
        createAccountDisabled = outgoingPasswordNeeded || createAccountDisabled;
    }
    // Write key to mark account as disabled if necessary
    if (createAccountDisabled) {
        editor.putBoolean(accountKeyPrefix + "enabled", false);
    }
    // Validate account settings
    Map<String, Object> validatedSettings = AccountSettings.validate(contentVersion, account.settings.settings, !mergeImportedAccount);
    // Upgrade account settings to current content version
    if (contentVersion != Settings.VERSION) {
        AccountSettings.upgrade(contentVersion, validatedSettings);
    }
    // Convert account settings to the string representation used in preference storage
    Map<String, String> stringSettings = AccountSettings.convert(validatedSettings);
    // Merge account settings if necessary
    Map<String, String> writeSettings;
    if (mergeImportedAccount) {
        writeSettings = new HashMap<>(AccountSettings.getAccountSettings(prefs.getStorage(), uuid));
        writeSettings.putAll(stringSettings);
    } else {
        writeSettings = stringSettings;
    }
    // Write account settings
    for (Map.Entry<String, String> setting : writeSettings.entrySet()) {
        String key = accountKeyPrefix + setting.getKey();
        String value = setting.getValue();
        putString(editor, key, value);
    }
    // If it's a new account generate and write a new "accountNumber"
    if (!mergeImportedAccount) {
        int newAccountNumber = Account.generateAccountNumber(prefs);
        putString(editor, accountKeyPrefix + "accountNumber", Integer.toString(newAccountNumber));
    }
    // Write identities
    if (account.identities != null) {
        importIdentities(editor, contentVersion, uuid, account, overwrite, existingAccount, prefs);
    } else if (!mergeImportedAccount) {
        // Require accounts to at least have one identity
        throw new InvalidSettingValueException();
    }
    // Write folder settings
    if (account.folders != null) {
        for (ImportedFolder folder : account.folders) {
            importFolder(editor, contentVersion, uuid, folder, mergeImportedAccount, prefs);
        }
    }
    //TODO: sync folder settings with localstore?
    AccountDescription imported = new AccountDescription(accountName, uuid);
    return new AccountDescriptionPair(original, imported, mergeImportedAccount);
}
Also used : Account(com.fsck.k9.Account) InvalidSettingValueException(com.fsck.k9.preferences.Settings.InvalidSettingValueException) ServerSettings(com.fsck.k9.mail.ServerSettings) SharedPreferences(android.content.SharedPreferences) Preferences(com.fsck.k9.Preferences) HashMap(java.util.HashMap) Map(java.util.Map)

Aggregations

LocalStore (com.fsck.k9.mailstore.LocalStore)41 MessagingException (com.fsck.k9.mail.MessagingException)33 LocalFolder (com.fsck.k9.mailstore.LocalFolder)33 Store (com.fsck.k9.mail.Store)18 LocalMessage (com.fsck.k9.mailstore.LocalMessage)18 Folder (com.fsck.k9.mail.Folder)17 Pop3Store (com.fsck.k9.mail.store.pop3.Pop3Store)17 MimeMessage (com.fsck.k9.mail.internet.MimeMessage)15 FetchProfile (com.fsck.k9.mail.FetchProfile)14 Message (com.fsck.k9.mail.Message)13 UnavailableStorageException (com.fsck.k9.mailstore.UnavailableStorageException)13 IOException (java.io.IOException)12 AuthenticationFailedException (com.fsck.k9.mail.AuthenticationFailedException)11 CertificateValidationException (com.fsck.k9.mail.CertificateValidationException)11 Test (org.junit.Test)10 Account (com.fsck.k9.Account)9 ArrayList (java.util.ArrayList)9 SuppressLint (android.annotation.SuppressLint)8 SQLiteDatabase (android.database.sqlite.SQLiteDatabase)8 VisibleForTesting (android.support.annotation.VisibleForTesting)5