Search in sources :

Example 1 with VisibleForTesting

use of androidx.annotation.VisibleForTesting in project k-9 by k9mail.

the class SettingsImporter method parseSettings.

@VisibleForTesting
static Imported parseSettings(InputStream inputStream, boolean globalSettings, List<String> accountUuids, boolean overview) throws SettingsImportExportException {
    if (!overview && accountUuids == null) {
        throw new IllegalArgumentException("Argument 'accountUuids' must not be null.");
    }
    try {
        XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
        // factory.setNamespaceAware(true);
        XmlPullParser xpp = factory.newPullParser();
        InputStreamReader reader = new InputStreamReader(inputStream);
        xpp.setInput(reader);
        Imported imported = null;
        int eventType = xpp.getEventType();
        while (eventType != XmlPullParser.END_DOCUMENT) {
            if (eventType == XmlPullParser.START_TAG) {
                if (SettingsExporter.ROOT_ELEMENT.equals(xpp.getName())) {
                    imported = parseRoot(xpp, globalSettings, accountUuids, overview);
                } else {
                    Timber.w("Unexpected start tag: %s", xpp.getName());
                }
            }
            eventType = xpp.next();
        }
        if (imported == null || (overview && imported.globalSettings == null && imported.accounts == null)) {
            throw new SettingsImportExportException("Invalid import data");
        }
        return imported;
    } catch (Exception e) {
        throw new SettingsImportExportException(e);
    }
}
Also used : XmlPullParserFactory(org.xmlpull.v1.XmlPullParserFactory) InputStreamReader(java.io.InputStreamReader) XmlPullParser(org.xmlpull.v1.XmlPullParser) InvalidSettingValueException(com.fsck.k9.preferences.Settings.InvalidSettingValueException) IOException(java.io.IOException) XmlPullParserException(org.xmlpull.v1.XmlPullParserException) VisibleForTesting(androidx.annotation.VisibleForTesting)

Example 2 with VisibleForTesting

use of androidx.annotation.VisibleForTesting in project k-9 by k9mail.

the class AttachmentInfoExtractor method getDecryptedFileProviderUri.

@Nullable
@VisibleForTesting
protected Uri getDecryptedFileProviderUri(DeferredFileBody decryptedTempFileBody, String mimeType) {
    Uri uri;
    try {
        File file = decryptedTempFileBody.getFile();
        uri = DecryptedFileProvider.getUriForProvidedFile(context, file, decryptedTempFileBody.getEncoding(), mimeType);
    } catch (IOException e) {
        Timber.e(e, "Decrypted temp file (no longer?) exists!");
        uri = null;
    }
    return uri;
}
Also used : IOException(java.io.IOException) Uri(android.net.Uri) File(java.io.File) VisibleForTesting(androidx.annotation.VisibleForTesting) Nullable(androidx.annotation.Nullable)

Example 3 with VisibleForTesting

use of androidx.annotation.VisibleForTesting in project k-9 by k9mail.

the class MessagingController method searchLocalMessagesSynchronous.

@VisibleForTesting
void searchLocalMessagesSynchronous(final LocalSearch search, final MessagingListener listener) {
    List<Account> searchAccounts = getAccountsFromLocalSearch(search, preferences);
    for (final Account account : searchAccounts) {
        // 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);
                    if (listener != null) {
                        listener.listLocalMessagesAddMessages(account, null, messages);
                    }
                }
            }
        };
        // build and do the query in the localstore
        try {
            LocalStore localStore = localStoreProvider.getInstance(account);
            localStore.searchForMessages(retrievalListener, search);
        } catch (Exception e) {
            Timber.e(e);
        }
    }
    if (listener != null) {
        listener.listLocalMessagesFinished();
    }
}
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) MessagingException(com.fsck.k9.mail.MessagingException) AuthenticationFailedException(com.fsck.k9.mail.AuthenticationFailedException) MessageRetrievalListener(com.fsck.k9.mail.MessageRetrievalListener) VisibleForTesting(androidx.annotation.VisibleForTesting)

Example 4 with VisibleForTesting

use of androidx.annotation.VisibleForTesting in project k-9 by k9mail.

the class MessagingController method searchRemoteMessagesSynchronous.

@VisibleForTesting
void searchRemoteMessagesSynchronous(String acctUuid, long folderId, String query, Set<Flag> requiredFlags, Set<Flag> forbiddenFlags, MessagingListener listener) {
    Account account = preferences.getAccount(acctUuid);
    if (listener != null) {
        listener.remoteSearchStarted(folderId);
    }
    List<String> extraResults = new ArrayList<>();
    try {
        LocalStore localStore = localStoreProvider.getInstance(account);
        LocalFolder localFolder = localStore.getFolder(folderId);
        if (!localFolder.exists()) {
            throw new MessagingException("Folder not found");
        }
        localFolder.open();
        String folderServerId = localFolder.getServerId();
        Backend backend = getBackend(account);
        boolean performFullTextSearch = account.isRemoteSearchFullText();
        List<String> messageServerIds = backend.search(folderServerId, query, requiredFlags, forbiddenFlags, performFullTextSearch);
        Timber.i("Remote search got %d results", messageServerIds.size());
        // There's no need to fetch messages already completely downloaded
        messageServerIds = localFolder.extractNewMessages(messageServerIds);
        if (listener != null) {
            listener.remoteSearchServerQueryComplete(folderId, messageServerIds.size(), account.getRemoteSearchNumResults());
        }
        int resultLimit = account.getRemoteSearchNumResults();
        if (resultLimit > 0 && messageServerIds.size() > resultLimit) {
            extraResults = messageServerIds.subList(resultLimit, messageServerIds.size());
            messageServerIds = messageServerIds.subList(0, resultLimit);
        }
        loadSearchResultsSynchronous(account, messageServerIds, localFolder);
    } catch (Exception e) {
        if (Thread.currentThread().isInterrupted()) {
            Timber.i(e, "Caught exception on aborted remote search; safe to ignore.");
        } else {
            Timber.e(e, "Could not complete remote search");
            if (listener != null) {
                listener.remoteSearchFailed(null, e.getMessage());
            }
            Timber.e(e);
        }
    } finally {
        if (listener != null) {
            listener.remoteSearchFinished(folderId, 0, account.getRemoteSearchNumResults(), extraResults);
        }
    }
}
Also used : LocalFolder(com.fsck.k9.mailstore.LocalFolder) SearchAccount(com.fsck.k9.search.SearchAccount) Account(com.fsck.k9.Account) Backend(com.fsck.k9.backend.api.Backend) MessagingException(com.fsck.k9.mail.MessagingException) ArrayList(java.util.ArrayList) LocalStore(com.fsck.k9.mailstore.LocalStore) SuppressLint(android.annotation.SuppressLint) CertificateValidationException(com.fsck.k9.mail.CertificateValidationException) MessagingException(com.fsck.k9.mail.MessagingException) AuthenticationFailedException(com.fsck.k9.mail.AuthenticationFailedException) VisibleForTesting(androidx.annotation.VisibleForTesting)

Example 5 with VisibleForTesting

use of androidx.annotation.VisibleForTesting 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) {
    Exception lastFailure = null;
    boolean wasPermanentFailure = false;
    try {
        ServerSettings serverSettings = account.getOutgoingServerSettings();
        if (serverSettings.isMissingCredentials()) {
            handleAuthenticationFailure(account, false);
            return;
        }
        LocalStore localStore = localStoreProvider.getInstance(account);
        OutboxStateRepository outboxStateRepository = localStore.getOutboxStateRepository();
        LocalFolder localFolder = localStore.getFolder(account.getOutboxFolderId());
        if (!localFolder.exists()) {
            Timber.w("Outbox does not exist");
            return;
        }
        localFolder.open();
        long outboxFolderId = localFolder.getDatabaseId();
        List<LocalMessage> localMessages = localFolder.getMessages(null);
        int progress = 0;
        int todo = localMessages.size();
        for (MessagingListener l : getListeners()) {
            l.synchronizeMailboxProgress(account, outboxFolderId, 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 Outbox folder for messages to send");
        Backend backend = getBackend(account);
        for (LocalMessage message : localMessages) {
            if (message.isSet(Flag.DELETED)) {
                // FIXME: When uploading a message to the remote Sent folder the move code creates a placeholder
                // message in the Outbox. This code gets rid of these messages. It'd be preferable if the
                // placeholder message was never created, though.
                message.destroy();
                continue;
            }
            try {
                long messageId = message.getDatabaseId();
                OutboxState outboxState = outboxStateRepository.getOutboxState(messageId);
                if (outboxState.getSendState() != SendState.READY) {
                    Timber.v("Skipping sending message %s", message.getUid());
                    notificationController.showSendFailedNotification(account, new MessagingException(message.getSubject()));
                    continue;
                }
                Timber.i("Send count for message %s is %d", message.getUid(), outboxState.getNumberOfSendAttempts());
                localFolder.fetch(Collections.singletonList(message), fp, null);
                try {
                    if (message.getHeader(K9.IDENTITY_HEADER).length > 0 || message.isSet(Flag.DRAFT)) {
                        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;
                    }
                    outboxStateRepository.incrementSendAttempts(messageId);
                    message.setFlag(Flag.X_SEND_IN_PROGRESS, true);
                    Timber.i("Sending message with UID %s", message.getUid());
                    backend.sendMessage(message);
                    message.setFlag(Flag.X_SEND_IN_PROGRESS, false);
                    message.setFlag(Flag.SEEN, true);
                    progress++;
                    for (MessagingListener l : getListeners()) {
                        l.synchronizeMailboxProgress(account, outboxFolderId, progress, todo);
                    }
                    moveOrDeleteSentMessage(account, localStore, message);
                    outboxStateRepository.removeOutboxState(messageId);
                } catch (AuthenticationFailedException e) {
                    outboxStateRepository.decrementSendAttempts(messageId);
                    lastFailure = e;
                    wasPermanentFailure = false;
                    handleAuthenticationFailure(account, false);
                    handleSendFailure(account, localFolder, message, e);
                } catch (CertificateValidationException e) {
                    outboxStateRepository.decrementSendAttempts(messageId);
                    lastFailure = e;
                    wasPermanentFailure = false;
                    notifyUserIfCertificateProblem(account, e, false);
                    handleSendFailure(account, localFolder, message, e);
                } catch (MessagingException e) {
                    lastFailure = e;
                    wasPermanentFailure = e.isPermanentFailure();
                    if (wasPermanentFailure) {
                        String errorMessage = e.getMessage();
                        outboxStateRepository.setSendAttemptError(messageId, errorMessage);
                    } else if (outboxState.getNumberOfSendAttempts() + 1 >= MAX_SEND_ATTEMPTS) {
                        outboxStateRepository.setSendAttemptsExceeded(messageId);
                    }
                    handleSendFailure(account, localFolder, message, e);
                } catch (Exception e) {
                    lastFailure = e;
                    wasPermanentFailure = true;
                    handleSendFailure(account, localFolder, message, e);
                }
            } catch (Exception e) {
                lastFailure = e;
                wasPermanentFailure = false;
                Timber.e(e, "Failed to fetch message for sending");
                notifySynchronizeMailboxFailed(account, localFolder, e);
            }
        }
        if (lastFailure != null) {
            if (wasPermanentFailure) {
                notificationController.showSendFailedNotification(account, lastFailure);
            } else {
                notificationController.showSendFailedNotification(account, lastFailure);
            }
        }
    } catch (Exception e) {
        Timber.v(e, "Failed to send pending messages");
    } finally {
        if (lastFailure == null) {
            notificationController.clearSendFailedNotification(account);
        }
    }
}
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) OutboxStateRepository(com.fsck.k9.mailstore.OutboxStateRepository) LocalStore(com.fsck.k9.mailstore.LocalStore) CertificateValidationException(com.fsck.k9.mail.CertificateValidationException) MessagingException(com.fsck.k9.mail.MessagingException) AuthenticationFailedException(com.fsck.k9.mail.AuthenticationFailedException) SuppressLint(android.annotation.SuppressLint) OutboxState(com.fsck.k9.mailstore.OutboxState) LocalFolder(com.fsck.k9.mailstore.LocalFolder) Backend(com.fsck.k9.backend.api.Backend) ServerSettings(com.fsck.k9.mail.ServerSettings) CertificateValidationException(com.fsck.k9.mail.CertificateValidationException) VisibleForTesting(androidx.annotation.VisibleForTesting)

Aggregations

VisibleForTesting (androidx.annotation.VisibleForTesting)187 Context (android.content.Context)18 Intent (android.content.Intent)15 Bundle (android.os.Bundle)15 ArrayList (java.util.ArrayList)15 SuppressLint (android.annotation.SuppressLint)9 TextView (android.widget.TextView)9 SubSettingLauncher (com.android.settings.core.SubSettingLauncher)9 View (android.view.View)8 RemoteException (android.os.RemoteException)7 Nullable (androidx.annotation.Nullable)7 IOException (java.io.IOException)7 Activity (android.app.Activity)6 Uri (android.net.Uri)6 Preference (androidx.preference.Preference)6 PreferenceScreen (androidx.preference.PreferenceScreen)6 MetricsFeatureProvider (com.android.settingslib.core.instrumentation.MetricsFeatureProvider)6 SharedPreferences (android.content.SharedPreferences)5 SubscriptionInfo (android.telephony.SubscriptionInfo)5 ImageView (android.widget.ImageView)5