From 14d33366f8ed61105f0d10328a03ccb07cf8970a Mon Sep 17 00:00:00 2001 From: Christian Mollekopf Date: Thu, 1 Mar 2018 10:30:42 +0100 Subject: Select all folders and emit notification if new mails are available --- examples/imapresource/imapresource.cpp | 24 +++++++++- examples/imapresource/tests/imapmailsynctest.cpp | 61 ++++++++++++++++++++++++ 2 files changed, 83 insertions(+), 2 deletions(-) (limited to 'examples') diff --git a/examples/imapresource/imapresource.cpp b/examples/imapresource/imapresource.cpp index 5f7304d..061fdb1 100644 --- a/examples/imapresource/imapresource.cpp +++ b/examples/imapresource/imapresource.cpp @@ -287,6 +287,7 @@ public: .then([=](const SelectResult &selectResult) { SinkLogCtx(mLogCtx) << "Flags updated. New changedsince value: " << selectResult.highestModSequence; syncStore().writeValue(folderRemoteId, "changedsince", QByteArray::number(selectResult.highestModSequence)); + return selectResult.uidNext; }); } else { //We hit this path on initial sync and simply record the current changedsince value @@ -294,13 +295,14 @@ public: .then([=](const SelectResult &selectResult) { SinkLogCtx(mLogCtx) << "No flags to update. New changedsince value: " << selectResult.highestModSequence; syncStore().writeValue(folderRemoteId, "changedsince", QByteArray::number(selectResult.highestModSequence)); + return selectResult.uidNext; }); } }) //Next we synchronize the full set that is given by the date limit. //We fetch all data for this set. //This will also pull in any new messages in subsequent runs. - .then([=] { + .then([=] (qint64 serverUidNext){ auto job = [&] { if (dateFilter.isValid()) { SinkLogCtx(mLogCtx) << "Fetching messages since: " << dateFilter; @@ -349,6 +351,11 @@ public: SinkLogCtx(mLogCtx) << "UIDMAX: " << *maxUid << folder.path(); if (*maxUid > 0) { syncStore().writeValue(folderRemoteId, "uidnext", QByteArray::number(*maxUid)); + } else { + if (serverUidNext) { + //If we don't receive a mail we should still record the updated uidnext value. + syncStore().writeValue(folderRemoteId, "uidnext", QByteArray::number(serverUidNext)); + } } syncStore().writeValue(folderRemoteId, "fullsetLowerbound", QByteArray::number(lowerBoundUid)); commit(); @@ -555,8 +562,21 @@ public: return imap->fetchFolders([folderList](const Folder &folder) { *folderList << folder; }) - .then([this, folderList]() { + .then([=]() { synchronizeFolders(*folderList); + return *folderList; + }) + .each([=](const Imap::Folder &folder) { + //TODO examine instead + return imap->select(folder) + .then([=](const SelectResult &result) { + const auto folderRemoteId = folderRid(folder); + auto localUidNext = syncStore().readValue(folderRemoteId, "uidnext").toLongLong(); + if (result.uidNext > localUidNext) { + const auto folderLocalId = syncStore().resolveRemoteId(ENTITY_TYPE_FOLDER, folderRemoteId); + emitNotification(Notification::Info, ApplicationDomain::NewContentAvailable, {}, {}, {{folderLocalId}}); + } + }); }); }) .then([=] (const KAsync::Error &error) { diff --git a/examples/imapresource/tests/imapmailsynctest.cpp b/examples/imapresource/tests/imapmailsynctest.cpp index 3e975b8..e40aec8 100644 --- a/examples/imapresource/tests/imapmailsynctest.cpp +++ b/examples/imapresource/tests/imapmailsynctest.cpp @@ -26,6 +26,9 @@ #include "common/test.h" #include "common/domain/applicationdomaintype.h" #include "common/secretstore.h" +#include "common/store.h" +#include "common/resourcecontrol.h" +#include "common/notifier.h" using namespace Sink; using namespace Sink::ApplicationDomain; @@ -115,6 +118,64 @@ protected: VERIFYEXEC(imap.select("INBOX." + folderPath.join('.'))); VERIFYEXEC(imap.addFlags(KIMAP2::ImapSet::fromImapSequenceSet(messageIdentifier), QByteArrayList() << Imap::Flags::Flagged)); } + + static QByteArray newMessage(const QString &subject) + { + auto msg = KMime::Message::Ptr::create(); + msg->subject(true)->fromUnicodeString(subject, "utf8"); + msg->date(true)->setDateTime(QDateTime::currentDateTimeUtc()); + msg->assemble(); + return msg->encodedContent(true); + } + +private slots: + void testNewMailNotification() + { + const auto syncFolders = Sink::SyncScope{ApplicationDomain::getTypeName()}.resourceFilter(mResourceInstanceIdentifier); + //Fetch folders initially + VERIFYEXEC(Store::synchronize(syncFolders)); + VERIFYEXEC(ResourceControl::flushMessageQueue(mResourceInstanceIdentifier)); + + auto folder = Store::readOne(Sink::Query{}.resourceFilter(mResourceInstanceIdentifier).filter("test")); + Q_ASSERT(!folder.identifier().isEmpty()); + + const auto syncTestMails = Sink::SyncScope{ApplicationDomain::getTypeName()}.resourceFilter(mResourceInstanceIdentifier).filter(QVariant::fromValue(folder.identifier())); + + bool notificationReceived = false; + auto notifier = QSharedPointer::create(mResourceInstanceIdentifier); + notifier->registerHandler([&](const Notification ¬ification) { + if (notification.type == Sink::Notification::Info && notification.code == ApplicationDomain::NewContentAvailable && notification.entities.contains(folder.identifier())) { + notificationReceived = true; + } + }); + + //Should result in a change notification for test + VERIFYEXEC(Store::synchronize(syncFolders)); + VERIFYEXEC(ResourceControl::flushMessageQueue(mResourceInstanceIdentifier)); + + QTRY_VERIFY(notificationReceived); + + notificationReceived = false; + + //Fetch test mails to skip change notification + VERIFYEXEC(Store::synchronize(syncTestMails)); + VERIFYEXEC(ResourceControl::flushMessageQueue(mResourceInstanceIdentifier)); + + //Should no longer result in change notifications for test + VERIFYEXEC(Store::synchronize(syncFolders)); + VERIFYEXEC(ResourceControl::flushMessageQueue(mResourceInstanceIdentifier)); + + QVERIFY(!notificationReceived); + + //Create message and retry + createMessage(QStringList() << "test", newMessage("This is a Subject.")); + + //Should result in change notification + VERIFYEXEC(Store::synchronize(syncFolders)); + VERIFYEXEC(ResourceControl::flushMessageQueue(mResourceInstanceIdentifier)); + + QTRY_VERIFY(notificationReceived); + } }; QTEST_MAIN(ImapMailSyncTest) -- cgit v1.2.3