use of com.fsck.k9.mail.FetchProfile in project k-9 by k9mail.
the class MessagingController method refreshLocalMessageFlags.
private void refreshLocalMessageFlags(final Account account, final Folder remoteFolder, final LocalFolder localFolder, List<Message> syncFlagMessages, final AtomicInteger progress, final int todo) throws MessagingException {
final String folder = remoteFolder.getName();
if (remoteFolder.supportsFetchingFlags()) {
Timber.d("SYNC: About to sync flags for %d remote messages for folder %s", syncFlagMessages.size(), folder);
FetchProfile fp = new FetchProfile();
fp.add(FetchProfile.Item.FLAGS);
List<Message> undeletedMessages = new LinkedList<>();
for (Message message : syncFlagMessages) {
if (!message.isSet(Flag.DELETED)) {
undeletedMessages.add(message);
}
}
remoteFolder.fetch(undeletedMessages, fp, null);
for (Message remoteMessage : syncFlagMessages) {
LocalMessage localMessage = localFolder.getMessage(remoteMessage.getUid());
boolean messageChanged = syncFlags(localMessage, remoteMessage);
if (messageChanged) {
boolean shouldBeNotifiedOf = false;
if (localMessage.isSet(Flag.DELETED) || isMessageSuppressed(localMessage)) {
for (MessagingListener l : getListeners()) {
l.synchronizeMailboxRemovedMessage(account, folder, localMessage);
}
} else {
if (shouldNotifyForMessage(account, localFolder, localMessage)) {
shouldBeNotifiedOf = true;
}
}
// we're only interested in messages that need removing
if (!shouldBeNotifiedOf) {
MessageReference messageReference = localMessage.makeMessageReference();
notificationController.removeNewMailNotification(account, messageReference);
}
}
progress.incrementAndGet();
for (MessagingListener l : getListeners()) {
l.synchronizeMailboxProgress(account, folder, progress.get(), todo);
}
}
}
}
use of com.fsck.k9.mail.FetchProfile in project k-9 by k9mail.
the class RawMessageProvider method loadMessage.
private LocalMessage loadMessage(MessageReference messageReference) {
String accountUuid = messageReference.getAccountUuid();
long folderId = messageReference.getFolderId();
String uid = messageReference.getUid();
Account account = Preferences.getPreferences(getContext()).getAccount(accountUuid);
if (account == null) {
Timber.w("Account not found: %s", accountUuid);
return null;
}
try {
LocalStore localStore = DI.get(LocalStoreProvider.class).getInstance(account);
LocalFolder localFolder = localStore.getFolder(folderId);
localFolder.open();
LocalMessage message = localFolder.getMessage(uid);
if (message == null || message.getDatabaseId() == 0) {
Timber.w("Message not found: folder=%s, uid=%s", folderId, uid);
return null;
}
FetchProfile fetchProfile = new FetchProfile();
fetchProfile.add(FetchProfile.Item.BODY);
localFolder.fetch(Collections.singletonList(message), fetchProfile, null);
return message;
} catch (MessagingException e) {
Timber.e(e, "Error loading message: folder=%d, uid=%s", folderId, uid);
return null;
}
}
use of com.fsck.k9.mail.FetchProfile in project k-9 by k9mail.
the class MessagingController method processPendingAppend.
/**
* Process a pending append message command. This command uploads a local message to the
* server, first checking to be sure that the server message is not newer than
* the local message. Once the local message is successfully processed it is deleted so
* that the server message will be synchronized down without an additional copy being
* created.
*/
void processPendingAppend(PendingAppend command, Account account) throws MessagingException {
LocalStore localStore = localStoreProvider.getInstance(account);
long folderId = command.folderId;
LocalFolder localFolder = localStore.getFolder(folderId);
localFolder.open();
String folderServerId = localFolder.getServerId();
String uid = command.uid;
LocalMessage localMessage = localFolder.getMessage(uid);
if (localMessage == null) {
return;
}
if (!localMessage.getUid().startsWith(K9.LOCAL_UID_PREFIX)) {
// FIXME: This should never happen. Throw in debug builds.
return;
}
Backend backend = getBackend(account);
if (localMessage.isSet(Flag.X_REMOTE_COPY_STARTED)) {
Timber.w("Local message with uid %s has flag %s already set, checking for remote message with " + "same message id", localMessage.getUid(), X_REMOTE_COPY_STARTED);
String messageServerId = backend.findByMessageId(folderServerId, localMessage.getMessageId());
if (messageServerId != null) {
Timber.w("Local message has flag %s already set, and there is a remote message with uid %s, " + "assuming message was already copied and aborting this copy", X_REMOTE_COPY_STARTED, messageServerId);
String oldUid = localMessage.getUid();
localMessage.setUid(messageServerId);
localFolder.changeUid(localMessage);
for (MessagingListener l : getListeners()) {
l.messageUidChanged(account, folderId, oldUid, localMessage.getUid());
}
return;
} else {
Timber.w("No remote message with message-id found, proceeding with append");
}
}
/*
* If the message does not exist remotely we just upload it and then
* update our local copy with the new uid.
*/
FetchProfile fp = new FetchProfile();
fp.add(FetchProfile.Item.BODY);
localFolder.fetch(Collections.singletonList(localMessage), fp, null);
String oldUid = localMessage.getUid();
localMessage.setFlag(Flag.X_REMOTE_COPY_STARTED, true);
String messageServerId = backend.uploadMessage(folderServerId, localMessage);
if (messageServerId == null) {
// We didn't get the server UID of the uploaded message. Remove the local message now. The uploaded
// version will be downloaded during the next sync.
localFolder.destroyMessages(Collections.singletonList(localMessage));
} else {
localMessage.setUid(messageServerId);
localFolder.changeUid(localMessage);
for (MessagingListener l : getListeners()) {
l.messageUidChanged(account, folderId, oldUid, localMessage.getUid());
}
}
}
use of com.fsck.k9.mail.FetchProfile in project k-9 by k9mail.
the class MessagingController method loadMessage.
public LocalMessage loadMessage(Account account, long folderId, String uid) throws MessagingException {
LocalStore localStore = localStoreProvider.getInstance(account);
LocalFolder localFolder = localStore.getFolder(folderId);
localFolder.open();
LocalMessage message = localFolder.getMessage(uid);
if (message == null || message.getDatabaseId() == 0) {
String folderName = localFolder.getName();
throw new IllegalArgumentException("Message not found: folder=" + folderName + ", uid=" + uid);
}
FetchProfile fp = new FetchProfile();
fp.add(FetchProfile.Item.BODY);
localFolder.fetch(Collections.singletonList(message), fp, null);
notificationController.removeNewMailNotification(account, message.makeMessageReference());
markMessageAsOpened(account, message);
return message;
}
use of com.fsck.k9.mail.FetchProfile 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