Navigation Menu

Skip to content

Commit

Permalink
[qmf] Handle 'Deleted' flag properly for IMAP accounts.
Browse files Browse the repository at this point in the history
Some email clients (e.g Thunderbird) have an option to just flag a email
as deleted and still leave it around, those will go way once the folder is
expunged or they can also be marked as undeleted before that. We were
not handling this case well before, now those emails are correctly updated
and the client can choose to show them or just hide them from the lists checking
the status flag QMailMessage::Removed.
  • Loading branch information
Valério Valério committed Mar 2, 2015
1 parent 9808a14 commit ddbe0d9
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 8 deletions.
3 changes: 3 additions & 0 deletions qmf/src/plugins/messageservices/imap/imapprotocol.cpp
Expand Up @@ -3700,6 +3700,9 @@ void ImapProtocol::createMail(const QString &uid, const QDateTime &timeStamp, in
if (flags & MFlag_Answered) {
mail.setStatus( QMailMessage::Replied, true );
}
if (flags & MFlag_Deleted) {
mail.setStatus( QMailMessage::Removed, true);
}

mail.setMessageType( QMailMessage::Email );
mail.setSize( size );
Expand Down
45 changes: 37 additions & 8 deletions qmf/src/plugins/messageservices/imap/imapstrategy.cpp
Expand Up @@ -155,13 +155,14 @@ bool updateMessagesMetaData(ImapStrategyContextBase *context,
const QMailMessageKey &storedKey,
const QMailMessageKey &unseenKey,
const QMailMessageKey &seenKey,
const QMailMessageKey &flaggedAsDeleted,
const QMailMessageKey &flaggedKey,
const QMailMessageKey &unreadElsewhereKey,
const QMailMessageKey &importantElsewhereKey,
const QMailMessageKey &unavailableKey)
{
bool result = true;
QMailMessageKey reportedKey(seenKey | unseenKey);
QMailMessageKey reportedKey((seenKey | unseenKey) & ~flaggedAsDeleted);
QMailMessageKey unflaggedKey(reportedKey & ~flaggedKey);

// Mark as deleted any messages that the server does not report
Expand Down Expand Up @@ -418,6 +419,22 @@ QSet<QMailFolderId> foldersApplicableTo(QMailMessageKey const& messagekey, QSet<
}
}

QStringList flaggedAsDeletedUids(ImapStrategyContextBase *context)
{
QStringList flaggedAsDeleted;
const ImapMailboxProperties &properties(context->mailbox());
foreach(FlagChange change, properties.flagChanges) {
QString uidStr(stripFolderPrefix(change.first));
MessageFlags flags(change.second);
if (!uidStr.isEmpty()) {
if (flags & MFlag_Deleted) {
flaggedAsDeleted.append(uidStr);
}
}
}
return flaggedAsDeleted;
}

}


Expand Down Expand Up @@ -2692,6 +2709,9 @@ void ImapSynchronizeAllStrategy::processUidSearchResults(ImapStrategyContextBase
qWarning() << "Unable to update folder for account:" << context->config().id();
}

// Check if any of the message is flagged as deleted on server side and not expunged yet
QStringList flaggedAsRemovedUids = flaggedAsDeletedUids(context);

// Messages reported as being on the server
QStringList reportedOnServerUids = _seenUids + _unseenUids;

Expand Down Expand Up @@ -2723,13 +2743,14 @@ void ImapSynchronizeAllStrategy::processUidSearchResults(ImapStrategyContextBase
QMailMessageKey seenKey(QMailMessageKey::serverUid(_seenUids));
QMailMessageKey flaggedKey(QMailMessageKey::serverUid(_flaggedUids));
QMailMessageKey importantElsewhereKey(QMailMessageKey::status(QMailMessage::ImportantElsewhere, QMailDataComparator::Includes));
QMailMessageKey flaggedAsRemoved(QMailMessageKey::serverUid(flaggedAsRemovedUids));

// Only delete messages the server still has
_removedUids = inFirstAndSecond(deletedUids, reportedOnServerUids);
_expungeRequired = !_removedUids.isEmpty();

if (_options & ImportChanges) {
if (!updateMessagesMetaData(context, storedKey, unseenKey, seenKey, flaggedKey, unreadElsewhereKey, importantElsewhereKey, unavailableKey)) {
if (!updateMessagesMetaData(context, storedKey, unseenKey, seenKey, flaggedAsRemoved, flaggedKey, unreadElsewhereKey, importantElsewhereKey, unavailableKey)) {
_error = true;
}
}
Expand Down Expand Up @@ -3250,6 +3271,9 @@ void ImapUpdateMessagesFlagsStrategy::processUidSearchResults(ImapStrategyContex
processNextFolder(context);
return;
}

// Check if any of the message is flagged as deleted on server side and not expunged yet
QStringList flaggedAsRemovedUids = flaggedAsDeletedUids(context);

// Compare the server message list with our message list
QMailMessageKey accountKey(QMailMessageKey::parentAccountId(context->config().id()));
Expand All @@ -3263,8 +3287,9 @@ void ImapUpdateMessagesFlagsStrategy::processUidSearchResults(ImapStrategyContex
QMailMessageKey unavailableKey(folderKey & accountKey & removedStatusKey);
QMailMessageKey flaggedKey(QMailMessageKey::serverUid(_flaggedUids));
QMailMessageKey importantElsewhereKey(QMailMessageKey::status(QMailMessage::ImportantElsewhere, QMailDataComparator::Includes));
QMailMessageKey flaggedAsRemoved(QMailMessageKey::serverUid(flaggedAsRemovedUids));

if (!updateMessagesMetaData(context, storedKey, unseenKey, seenKey, flaggedKey, unreadElsewhereKey, importantElsewhereKey, unavailableKey))
if (!updateMessagesMetaData(context, storedKey, unseenKey, seenKey, flaggedAsRemoved, flaggedKey, unreadElsewhereKey, importantElsewhereKey, unavailableKey))
_error = true;

processNextFolder(context);
Expand Down Expand Up @@ -3401,6 +3426,8 @@ static void processFlagChanges(const QList<FlagChange> &changes, const QMailFold
IntegerRegion unread;
IntegerRegion important;
IntegerRegion notImportant;
IntegerRegion deletedElsewhere;
IntegerRegion undeleted;
foreach(FlagChange change, changes) {
bool ok;
QString uidStr(stripFolderPrefix(change.first));
Expand All @@ -3417,6 +3444,11 @@ static void processFlagChanges(const QList<FlagChange> &changes, const QMailFold
} else {
notImportant.add(uid);
}
if (flags & MFlag_Deleted) {
deletedElsewhere.add(uid);
} else {
undeleted.add(uid);
}
}
}
markMessages(read, QMailMessage::Read, true, id, _error);
Expand All @@ -3427,6 +3459,8 @@ static void processFlagChanges(const QList<FlagChange> &changes, const QMailFold
markMessages(important, QMailMessage::ImportantElsewhere, true, id, _error);
markMessages(notImportant, QMailMessage::Important, false, id, _error);
markMessages(notImportant, QMailMessage::ImportantElsewhere, false, id, _error);
markMessages(deletedElsewhere, QMailMessage::Removed, true, id, _error);
markMessages(undeleted, QMailMessage::Removed, false, id, _error);
}

void ImapRetrieveMessageListStrategy::handleFetchFlags(ImapStrategyContextBase *context)
Expand Down Expand Up @@ -3613,11 +3647,6 @@ void ImapRetrieveMessageListStrategy::folderListFolderAction(ImapStrategyContext
uint minimum(_minimum);
QMailMessageKey sourceKey(QMailDisconnected::sourceKey(properties.id));

// Purge messages marked as removed, facilitates detection of messages missign on client, and prevents cruft building up
if (!purge(context, sourceKey & QMailMessageKey::status(QMailMessage::Removed))) {
_error = true;
}

// Could get flag changes mod sequences when CONDSTORE is available
if ((properties.exists == 0) || (minimum <= 0)) {
// No messages, so no need to perform search
Expand Down

0 comments on commit ddbe0d9

Please sign in to comment.