use of com.fsck.k9.mail.Message 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.mail.Message in project k-9 by k9mail.
the class MessagingController method downloadMessages.
/**
* Fetches the messages described by inputMessages from the remote store and writes them to
* local storage.
*
* @param account
* The account the remote store belongs to.
* @param remoteFolder
* The remote folder to download messages from.
* @param localFolder
* The {@link LocalFolder} instance corresponding to the remote folder.
* @param inputMessages
* A list of messages objects that store the UIDs of which messages to download.
* @param flagSyncOnly
* Only flags will be fetched from the remote store if this is {@code true}.
* @param purgeToVisibleLimit
* If true, local messages will be purged down to the limit of visible messages.
*
* @return The number of downloaded messages that are not flagged as {@link Flag#SEEN}.
*
* @throws MessagingException
*/
private int downloadMessages(final Account account, final Folder remoteFolder, final LocalFolder localFolder, List<Message> inputMessages, boolean flagSyncOnly, boolean purgeToVisibleLimit) throws MessagingException {
final Date earliestDate = account.getEarliestPollDate();
// now
Date downloadStarted = new Date();
if (earliestDate != null) {
Timber.d("Only syncing messages after %s", earliestDate);
}
final String folder = remoteFolder.getName();
int unreadBeforeStart = 0;
try {
AccountStats stats = account.getStats(context);
unreadBeforeStart = stats.unreadMessageCount;
} catch (MessagingException e) {
Timber.e(e, "Unable to getUnreadMessageCount for account: %s", account);
}
List<Message> syncFlagMessages = new ArrayList<>();
List<Message> unsyncedMessages = new ArrayList<>();
final AtomicInteger newMessages = new AtomicInteger(0);
List<Message> messages = new ArrayList<>(inputMessages);
for (Message message : messages) {
evaluateMessageForDownload(message, folder, localFolder, remoteFolder, account, unsyncedMessages, syncFlagMessages, flagSyncOnly);
}
final AtomicInteger progress = new AtomicInteger(0);
final int todo = unsyncedMessages.size() + syncFlagMessages.size();
for (MessagingListener l : getListeners()) {
l.synchronizeMailboxProgress(account, folder, progress.get(), todo);
}
Timber.d("SYNC: Have %d unsynced messages", unsyncedMessages.size());
messages.clear();
final List<Message> largeMessages = new ArrayList<>();
final List<Message> smallMessages = new ArrayList<>();
if (!unsyncedMessages.isEmpty()) {
/*
* Reverse the order of the messages. Depending on the server this may get us
* fetch results for newest to oldest. If not, no harm done.
*/
Collections.sort(unsyncedMessages, new UidReverseComparator());
int visibleLimit = localFolder.getVisibleLimit();
int listSize = unsyncedMessages.size();
if ((visibleLimit > 0) && (listSize > visibleLimit)) {
unsyncedMessages = unsyncedMessages.subList(0, visibleLimit);
}
FetchProfile fp = new FetchProfile();
if (remoteFolder.supportsFetchingFlags()) {
fp.add(FetchProfile.Item.FLAGS);
}
fp.add(FetchProfile.Item.ENVELOPE);
Timber.d("SYNC: About to fetch %d unsynced messages for folder %s", unsyncedMessages.size(), folder);
fetchUnsyncedMessages(account, remoteFolder, unsyncedMessages, smallMessages, largeMessages, progress, todo, fp);
String updatedPushState = localFolder.getPushState();
for (Message message : unsyncedMessages) {
String newPushState = remoteFolder.getNewPushState(updatedPushState, message);
if (newPushState != null) {
updatedPushState = newPushState;
}
}
localFolder.setPushState(updatedPushState);
Timber.d("SYNC: Synced unsynced messages for folder %s", folder);
}
Timber.d("SYNC: Have %d large messages and %d small messages out of %d unsynced messages", largeMessages.size(), smallMessages.size(), unsyncedMessages.size());
unsyncedMessages.clear();
/*
* Grab the content of the small messages first. This is going to
* be very fast and at very worst will be a single up of a few bytes and a single
* download of 625k.
*/
FetchProfile fp = new FetchProfile();
//TODO: Only fetch small and large messages if we have some
fp.add(FetchProfile.Item.BODY);
// fp.add(FetchProfile.Item.FLAGS);
// fp.add(FetchProfile.Item.ENVELOPE);
downloadSmallMessages(account, remoteFolder, localFolder, smallMessages, progress, unreadBeforeStart, newMessages, todo, fp);
smallMessages.clear();
/*
* Now do the large messages that require more round trips.
*/
fp = new FetchProfile();
fp.add(FetchProfile.Item.STRUCTURE);
downloadLargeMessages(account, remoteFolder, localFolder, largeMessages, progress, unreadBeforeStart, newMessages, todo, fp);
largeMessages.clear();
/*
* Refresh the flags for any messages in the local store that we didn't just
* download.
*/
refreshLocalMessageFlags(account, remoteFolder, localFolder, syncFlagMessages, progress, todo);
Timber.d("SYNC: Synced remote messages for folder %s, %d new messages", folder, newMessages.get());
if (purgeToVisibleLimit) {
localFolder.purgeToVisibleLimit(new MessageRemovalListener() {
@Override
public void messageRemoved(Message message) {
for (MessagingListener l : getListeners()) {
l.synchronizeMailboxRemovedMessage(account, folder, message);
}
}
});
}
// If the oldest message seen on this sync is newer than
// the oldest message seen on the previous sync, then
// we want to move our high-water mark forward
// this is all here just for pop which only syncs inbox
// this would be a little wrong for IMAP (we'd want a folder-level pref, not an account level pref.)
// fortunately, we just don't care.
Long oldestMessageTime = localFolder.getOldestMessageDate();
if (oldestMessageTime != null) {
Date oldestExtantMessage = new Date(oldestMessageTime);
if (oldestExtantMessage.before(downloadStarted) && oldestExtantMessage.after(new Date(account.getLatestOldMessageSeenTime()))) {
account.setLatestOldMessageSeenTime(oldestExtantMessage.getTime());
account.save(Preferences.getPreferences(context));
}
}
return newMessages.get();
}
use of com.fsck.k9.mail.Message 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);
}
}
use of com.fsck.k9.mail.Message in project k-9 by k9mail.
the class MessagingController method loadMessage.
public LocalMessage loadMessage(Account account, String folderName, String uid) throws MessagingException {
LocalStore localStore = account.getLocalStore();
LocalFolder localFolder = localStore.getFolder(folderName);
localFolder.open(Folder.OPEN_MODE_RW);
LocalMessage message = localFolder.getMessage(uid);
if (message == null || message.getId() == 0) {
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);
localFolder.close();
notificationController.removeNewMailNotification(account, message.makeMessageReference());
markMessageAsReadOnView(account, message);
return message;
}
use of com.fsck.k9.mail.Message in project k-9 by k9mail.
the class MessagingController method setFlag.
/**
* Set or remove a flag for a set of messages in a specific folder.
* <p>
* <p>
* The {@link Message} objects passed in are updated to reflect the new flag state.
* </p>
*
* @param account
* The account the folder containing the messages belongs to.
* @param folderName
* The name of the folder.
* @param messages
* The messages 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, List<? extends Message> messages, Flag flag, boolean newState) {
// TODO: Put this into the background, but right now some callers depend on the message
// objects being modified right after this method returns.
Folder localFolder = null;
try {
Store localStore = account.getLocalStore();
localFolder = localStore.getFolder(folderName);
localFolder.open(Folder.OPEN_MODE_RW);
// Allows for re-allowing sending of messages that could not be sent
if (flag == Flag.FLAGGED && !newState && account.getOutboxFolderName().equals(folderName)) {
for (Message message : messages) {
String uid = message.getUid();
if (uid != null) {
sendCount.remove(uid);
}
}
}
// Update the messages in the local store
localFolder.setFlags(messages, Collections.singleton(flag), newState);
int unreadMessageCount = localFolder.getUnreadMessageCount();
for (MessagingListener l : getListeners()) {
l.folderStatusChanged(account, folderName, unreadMessageCount);
}
// TODO: Skip the remote part for all local-only folders
if (account.getErrorFolderName().equals(folderName)) {
return;
}
List<String> uids = getUidsFromMessages(messages);
queueSetFlag(account, folderName, newState, flag, uids);
processPendingCommands(account);
} catch (MessagingException me) {
addErrorMessage(account, null, me);
throw new RuntimeException(me);
} finally {
closeFolder(localFolder);
}
}
Aggregations