use of com.fsck.k9.mailstore.LocalMessage 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) {
LocalFolder localFolder = null;
Exception lastFailure = null;
boolean wasPermanentFailure = false;
try {
LocalStore localStore = account.getLocalStore();
localFolder = localStore.getFolder(account.getOutboxFolderName());
if (!localFolder.exists()) {
Timber.v("Outbox does not exist");
return;
}
for (MessagingListener l : getListeners()) {
l.sendPendingMessagesStarted(account);
}
localFolder.open(Folder.OPEN_MODE_RW);
List<LocalMessage> localMessages = localFolder.getMessages(null);
int progress = 0;
int todo = localMessages.size();
for (MessagingListener l : getListeners()) {
l.synchronizeMailboxProgress(account, account.getSentFolderName(), 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 folder '%s' (%d) for messages to send", account.getOutboxFolderName(), localFolder.getId());
Transport transport = transportProvider.getTransport(K9.app, account);
for (LocalMessage message : localMessages) {
if (message.isSet(Flag.DELETED)) {
message.destroy();
continue;
}
try {
AtomicInteger count = new AtomicInteger(0);
AtomicInteger oldCount = sendCount.putIfAbsent(message.getUid(), count);
if (oldCount != null) {
count = oldCount;
}
Timber.i("Send count for message %s is %d", message.getUid(), count.get());
if (count.incrementAndGet() > K9.MAX_SEND_ATTEMPTS) {
Timber.e("Send count for message %s can't be delivered after %d attempts. " + "Giving up until the user restarts the device", message.getUid(), MAX_SEND_ATTEMPTS);
notificationController.showSendFailedNotification(account, new MessagingException(message.getSubject()));
continue;
}
localFolder.fetch(Collections.singletonList(message), fp, null);
try {
if (message.getHeader(K9.IDENTITY_HEADER).length > 0) {
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;
}
message.setFlag(Flag.X_SEND_IN_PROGRESS, true);
Timber.i("Sending message with UID %s", message.getUid());
transport.sendMessage(message);
message.setFlag(Flag.X_SEND_IN_PROGRESS, false);
message.setFlag(Flag.SEEN, true);
progress++;
for (MessagingListener l : getListeners()) {
l.synchronizeMailboxProgress(account, account.getSentFolderName(), progress, todo);
}
moveOrDeleteSentMessage(account, localStore, localFolder, message);
} catch (AuthenticationFailedException e) {
lastFailure = e;
wasPermanentFailure = false;
handleAuthenticationFailure(account, false);
handleSendFailure(account, localStore, localFolder, message, e, wasPermanentFailure);
} catch (CertificateValidationException e) {
lastFailure = e;
wasPermanentFailure = false;
notifyUserIfCertificateProblem(account, e, false);
handleSendFailure(account, localStore, localFolder, message, e, wasPermanentFailure);
} catch (MessagingException e) {
lastFailure = e;
wasPermanentFailure = e.isPermanentFailure();
handleSendFailure(account, localStore, localFolder, message, e, wasPermanentFailure);
} catch (Exception e) {
lastFailure = e;
wasPermanentFailure = true;
handleSendFailure(account, localStore, localFolder, message, e, wasPermanentFailure);
}
} catch (Exception e) {
lastFailure = e;
wasPermanentFailure = false;
Timber.e(e, "Failed to fetch message for sending");
addErrorMessage(account, "Failed to fetch message for sending", e);
notifySynchronizeMailboxFailed(account, localFolder, e);
}
}
for (MessagingListener l : getListeners()) {
l.sendPendingMessagesCompleted(account);
}
if (lastFailure != null) {
if (wasPermanentFailure) {
notificationController.showSendFailedNotification(account, lastFailure);
} else {
notificationController.showSendFailedNotification(account, lastFailure);
}
}
} catch (UnavailableStorageException e) {
Timber.i("Failed to send pending messages because storage is not available - trying again later.");
throw new UnavailableAccountException(e);
} catch (Exception e) {
Timber.v(e, "Failed to send pending messages");
for (MessagingListener l : getListeners()) {
l.sendPendingMessagesFailed(account);
}
addErrorMessage(account, null, e);
} finally {
if (lastFailure == null) {
notificationController.clearSendFailedNotification(account);
}
closeFolder(localFolder);
}
}
use of com.fsck.k9.mailstore.LocalMessage 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);
}
}
}
use of com.fsck.k9.mailstore.LocalMessage in project k-9 by k9mail.
the class MessagingController method searchLocalMessagesSynchronous.
@VisibleForTesting
void searchLocalMessagesSynchronous(final LocalSearch search, final MessagingListener listener) {
final AccountStats stats = new AccountStats();
final Set<String> uuidSet = new HashSet<>(Arrays.asList(search.getAccountUuids()));
List<Account> accounts = Preferences.getPreferences(context).getAccounts();
boolean allAccounts = uuidSet.contains(SearchSpecification.ALL_ACCOUNTS);
// for every account we want to search do the query in the localstore
for (final Account account : accounts) {
if (!allAccounts && !uuidSet.contains(account.getUuid())) {
continue;
}
// 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);
stats.unreadMessageCount += (!message.isSet(Flag.SEEN)) ? 1 : 0;
stats.flaggedMessageCount += (message.isSet(Flag.FLAGGED)) ? 1 : 0;
if (listener != null) {
listener.listLocalMessagesAddMessages(account, null, messages);
}
}
}
};
// build and do the query in the localstore
try {
LocalStore localStore = account.getLocalStore();
localStore.searchForMessages(retrievalListener, search);
} catch (Exception e) {
addErrorMessage(account, null, e);
}
}
// publish the total search statistics
if (listener != null) {
listener.searchStats(stats);
}
}
use of com.fsck.k9.mailstore.LocalMessage in project k-9 by k9mail.
the class MessagingController method syncFlags.
private boolean syncFlags(LocalMessage localMessage, Message remoteMessage) throws MessagingException {
boolean messageChanged = false;
if (localMessage == null || localMessage.isSet(Flag.DELETED)) {
return false;
}
if (remoteMessage.isSet(Flag.DELETED)) {
if (localMessage.getFolder().syncRemoteDeletions()) {
localMessage.setFlag(Flag.DELETED, true);
messageChanged = true;
}
} else {
for (Flag flag : MessagingController.SYNC_FLAGS) {
if (remoteMessage.isSet(flag) != localMessage.isSet(flag)) {
localMessage.setFlag(flag, remoteMessage.isSet(flag));
messageChanged = true;
}
}
}
return messageChanged;
}
use of com.fsck.k9.mailstore.LocalMessage in project k-9 by k9mail.
the class MessagingController method sendMessage.
/**
* Stores the given message in the Outbox and starts a sendPendingMessages command to
* attempt to send the message.
*/
public void sendMessage(final Account account, final Message message, MessagingListener listener) {
try {
LocalStore localStore = account.getLocalStore();
LocalFolder localFolder = localStore.getFolder(account.getOutboxFolderName());
localFolder.open(Folder.OPEN_MODE_RW);
localFolder.appendMessages(Collections.singletonList(message));
Message localMessage = localFolder.getMessage(message.getUid());
localMessage.setFlag(Flag.X_DOWNLOADED_FULL, true);
localFolder.close();
sendPendingMessages(account, listener);
} catch (Exception e) {
/*
for (MessagingListener l : getListeners())
{
// TODO general failed
}
*/
addErrorMessage(account, null, e);
}
}
Aggregations