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);
}
}
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;
}
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();
}
}
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);
}
}
}
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);
}
}
}
Aggregations