summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--examples/imapresource/imapresource.cpp19
-rw-r--r--examples/imapresource/imapserverproxy.cpp11
-rw-r--r--examples/imapresource/imapserverproxy.h1
-rw-r--r--tests/mailsynctest.cpp65
-rw-r--r--tests/mailsynctest.h1
5 files changed, 84 insertions, 13 deletions
diff --git a/examples/imapresource/imapresource.cpp b/examples/imapresource/imapresource.cpp
index 6607578..e8bc903 100644
--- a/examples/imapresource/imapresource.cpp
+++ b/examples/imapresource/imapresource.cpp
@@ -246,10 +246,23 @@ public:
246 SinkWarningCtx(mLogCtx) << "Invalid folder " << folderRemoteId << folder.path(); 246 SinkWarningCtx(mLogCtx) << "Invalid folder " << folderRemoteId << folder.path();
247 return KAsync::error<void>("Invalid folder"); 247 return KAsync::error<void>("Invalid folder");
248 } 248 }
249 // auto capabilities = imap->getCapabilities();
250 249
251 //First we fetch flag changes for all messages. Since we don't know which messages are locally available we just get everything and only apply to what we have. 250 //Start by checking if UIDVALIDITY is still correct
252 return KAsync::start<void>([=]() { 251 return KAsync::start([=] {
252 bool ok = false;
253 const auto uidvalidity = syncStore().readValue(folderRemoteId, "uidvalidity").toLongLong(&ok);
254 return imap->select(folder)
255 .then([=](const SelectResult &selectResult) {
256 SinkLogCtx(mLogCtx) << "Checking UIDVALIDITY. Local" << uidvalidity << "remote " << selectResult.uidValidity;
257 if (ok && selectResult.uidValidity != uidvalidity) {
258 SinkWarningCtx(mLogCtx) << "UIDVALIDITY changed " << selectResult.uidValidity << uidvalidity;
259 syncStore().removePrefix(folderRemoteId);
260 }
261 syncStore().writeValue(folderRemoteId, "uidvalidity", QByteArray::number(selectResult.uidValidity));
262 });
263 })
264 // //First we fetch flag changes for all messages. Since we don't know which messages are locally available we just get everything and only apply to what we have.
265 .then([=] {
253 auto uidNext = syncStore().readValue(folderRemoteId, "uidnext").toLongLong(); 266 auto uidNext = syncStore().readValue(folderRemoteId, "uidnext").toLongLong();
254 bool ok = false; 267 bool ok = false;
255 const auto changedsince = syncStore().readValue(folderRemoteId, "changedsince").toLongLong(&ok); 268 const auto changedsince = syncStore().readValue(folderRemoteId, "changedsince").toLongLong(&ok);
diff --git a/examples/imapresource/imapserverproxy.cpp b/examples/imapresource/imapserverproxy.cpp
index b27ffb0..a5a64db 100644
--- a/examples/imapresource/imapserverproxy.cpp
+++ b/examples/imapresource/imapserverproxy.cpp
@@ -244,6 +244,11 @@ KAsync::Job<SelectResult> ImapServerProxy::select(const QString &mailbox)
244 }); 244 });
245} 245}
246 246
247KAsync::Job<SelectResult> ImapServerProxy::select(const Folder &folder)
248{
249 return select(mailboxFromFolder(folder));
250}
251
247KAsync::Job<qint64> ImapServerProxy::append(const QString &mailbox, const QByteArray &content, const QList<QByteArray> &flags, const QDateTime &internalDate) 252KAsync::Job<qint64> ImapServerProxy::append(const QString &mailbox, const QByteArray &content, const QList<QByteArray> &flags, const QDateTime &internalDate)
248{ 253{
249 auto append = new KIMAP2::AppendJob(mSession); 254 auto append = new KIMAP2::AppendJob(mSession);
@@ -577,7 +582,7 @@ QString ImapServerProxy::mailboxFromFolder(const Folder &folder) const
577KAsync::Job<SelectResult> ImapServerProxy::fetchFlags(const Folder &folder, const KIMAP2::ImapSet &set, qint64 changedsince, std::function<void(const Message &)> callback) 582KAsync::Job<SelectResult> ImapServerProxy::fetchFlags(const Folder &folder, const KIMAP2::ImapSet &set, qint64 changedsince, std::function<void(const Message &)> callback)
578{ 583{
579 SinkTrace() << "Fetching flags " << folder.path(); 584 SinkTrace() << "Fetching flags " << folder.path();
580 return select(mailboxFromFolder(folder)).then<SelectResult, SelectResult>([=](const SelectResult &selectResult) -> KAsync::Job<SelectResult> { 585 return select(folder).then<SelectResult, SelectResult>([=](const SelectResult &selectResult) -> KAsync::Job<SelectResult> {
581 SinkTrace() << "Modeseq " << folder.path() << selectResult.highestModSequence << changedsince; 586 SinkTrace() << "Modeseq " << folder.path() << selectResult.highestModSequence << changedsince;
582 587
583 if (selectResult.highestModSequence == static_cast<quint64>(changedsince)) { 588 if (selectResult.highestModSequence == static_cast<quint64>(changedsince)) {
@@ -601,7 +606,7 @@ KAsync::Job<void> ImapServerProxy::fetchMessages(const Folder &folder, qint64 ui
601{ 606{
602 auto time = QSharedPointer<QTime>::create(); 607 auto time = QSharedPointer<QTime>::create();
603 time->start(); 608 time->start();
604 return select(mailboxFromFolder(folder)).then<void, SelectResult>([this, callback, folder, time, progress, uidNext](const SelectResult &selectResult) -> KAsync::Job<void> { 609 return select(folder).then<void, SelectResult>([this, callback, folder, time, progress, uidNext](const SelectResult &selectResult) -> KAsync::Job<void> {
605 SinkTrace() << "UIDNEXT " << folder.path() << selectResult.uidNext << uidNext; 610 SinkTrace() << "UIDNEXT " << folder.path() << selectResult.uidNext << uidNext;
606 if (selectResult.uidNext == (uidNext + 1)) { 611 if (selectResult.uidNext == (uidNext + 1)) {
607 SinkTrace()<< folder.path() << "Uidnext didn't change, nothing to do."; 612 SinkTrace()<< folder.path() << "Uidnext didn't change, nothing to do.";
@@ -624,7 +629,7 @@ KAsync::Job<void> ImapServerProxy::fetchMessages(const Folder &folder, const QVe
624{ 629{
625 auto time = QSharedPointer<QTime>::create(); 630 auto time = QSharedPointer<QTime>::create();
626 time->start(); 631 time->start();
627 return select(mailboxFromFolder(folder)).then<void, SelectResult>([this, callback, folder, time, progress, uidsToFetch, headersOnly](const SelectResult &selectResult) -> KAsync::Job<void> { 632 return select(folder).then<void, SelectResult>([this, callback, folder, time, progress, uidsToFetch, headersOnly](const SelectResult &selectResult) -> KAsync::Job<void> {
628 633
629 SinkTrace() << "Fetching messages" << folder.path(); 634 SinkTrace() << "Fetching messages" << folder.path();
630 SinkTrace() << " Total: " << uidsToFetch.size(); 635 SinkTrace() << " Total: " << uidsToFetch.size();
diff --git a/examples/imapresource/imapserverproxy.h b/examples/imapresource/imapserverproxy.h
index 57b252d..c69fe67 100644
--- a/examples/imapresource/imapserverproxy.h
+++ b/examples/imapresource/imapserverproxy.h
@@ -261,6 +261,7 @@ public:
261 KAsync::Job<void> login(const QString &username, const QString &password); 261 KAsync::Job<void> login(const QString &username, const QString &password);
262 KAsync::Job<void> logout(); 262 KAsync::Job<void> logout();
263 KAsync::Job<SelectResult> select(const QString &mailbox); 263 KAsync::Job<SelectResult> select(const QString &mailbox);
264 KAsync::Job<SelectResult> select(const Folder &mailbox);
264 KAsync::Job<qint64> append(const QString &mailbox, const QByteArray &content, const QList<QByteArray> &flags = QList<QByteArray>(), const QDateTime &internalDate = QDateTime()); 265 KAsync::Job<qint64> append(const QString &mailbox, const QByteArray &content, const QList<QByteArray> &flags = QList<QByteArray>(), const QDateTime &internalDate = QDateTime());
265 KAsync::Job<void> store(const KIMAP2::ImapSet &set, const QList<QByteArray> &flags); 266 KAsync::Job<void> store(const KIMAP2::ImapSet &set, const QList<QByteArray> &flags);
266 KAsync::Job<void> storeFlags(const KIMAP2::ImapSet &set, const QList<QByteArray> &flags); 267 KAsync::Job<void> storeFlags(const KIMAP2::ImapSet &set, const QList<QByteArray> &flags);
diff --git a/tests/mailsynctest.cpp b/tests/mailsynctest.cpp
index 058cae4..69541e1 100644
--- a/tests/mailsynctest.cpp
+++ b/tests/mailsynctest.cpp
@@ -33,6 +33,16 @@
33using namespace Sink; 33using namespace Sink;
34using namespace Sink::ApplicationDomain; 34using namespace Sink::ApplicationDomain;
35 35
36static QByteArray newMessage(const QString &subject)
37{
38 auto msg = KMime::Message::Ptr::create();
39 msg->subject(true)->fromUnicodeString(subject, "utf8");
40 msg->date(true)->setDateTime(QDateTime::currentDateTimeUtc());
41 msg->assemble();
42 return msg->encodedContent(true);
43}
44
45
36void MailSyncTest::initTestCase() 46void MailSyncTest::initTestCase()
37{ 47{
38 Test::initTest(); 48 Test::initTest();
@@ -261,11 +271,7 @@ void MailSyncTest::testListRemovedSubFolder()
261 271
262void MailSyncTest::testListMails() 272void MailSyncTest::testListMails()
263{ 273{
264 auto msg = KMime::Message::Ptr::create(); 274 createMessage(QStringList() << "test", newMessage("This is a Subject."));
265 msg->subject(true)->fromUnicodeString("This is a Subject.", "utf8");
266 msg->date(true)->setDateTime(QDateTime::currentDateTimeUtc());
267 msg->assemble();
268 createMessage(QStringList() << "test", msg->encodedContent(true));
269 275
270 Sink::Query query; 276 Sink::Query query;
271 query.resourceFilter(mResourceInstanceIdentifier); 277 query.resourceFilter(mResourceInstanceIdentifier);
@@ -420,8 +426,6 @@ void MailSyncTest::testSyncSingleFolder()
420 // Ensure all local data is processed 426 // Ensure all local data is processed
421 VERIFYEXEC(Store::synchronize(syncScope)); 427 VERIFYEXEC(Store::synchronize(syncScope));
422 VERIFYEXEC(ResourceControl::flushMessageQueue(mResourceInstanceIdentifier)); 428 VERIFYEXEC(ResourceControl::flushMessageQueue(mResourceInstanceIdentifier));
423
424
425} 429}
426 430
427void MailSyncTest::testSyncSingleMail() 431void MailSyncTest::testSyncSingleMail()
@@ -490,3 +494,50 @@ void MailSyncTest::testFailingSync()
490 // Ensure sync fails if resource is misconfigured 494 // Ensure sync fails if resource is misconfigured
491 QTRY_VERIFY(errorReceived); 495 QTRY_VERIFY(errorReceived);
492} 496}
497
498void MailSyncTest::testSyncUidvalidity()
499{
500 createFolder({"uidvalidity"});
501 createMessage({"uidvalidity"}, newMessage("old"));
502
503 VERIFYEXEC(Store::synchronize(SyncScope{ApplicationDomain::getTypeName<Folder>()}.resourceFilter(mResourceInstanceIdentifier)));
504 VERIFYEXEC(ResourceControl::flushMessageQueue(mResourceInstanceIdentifier));
505
506 auto folder = Store::readOne<Folder>(Query{}.resourceFilter(mResourceInstanceIdentifier).filter<Folder::Name>("uidvalidity"));
507
508 auto folderSyncScope = SyncScope{ApplicationDomain::getTypeName<Mail>()};
509 folderSyncScope.resourceFilter(mResourceInstanceIdentifier);
510 folderSyncScope.filter<Mail::Folder>(QVariant::fromValue(folder.identifier()));
511 VERIFYEXEC(Store::synchronize(folderSyncScope));
512 VERIFYEXEC(ResourceControl::flushMessageQueue(mResourceInstanceIdentifier));
513
514
515 {
516 Sink::Query query;
517 query.resourceFilter(mResourceInstanceIdentifier);
518 query.request<Mail::Subject>().request<Mail::MimeMessage>().request<Mail::Folder>().request<Mail::Date>();
519 query.filter<Mail::Folder>(folder);
520 auto mails = Store::read<Mail>(query);
521 QCOMPARE(mails.size(), 1);
522 }
523
524 resetTestEnvironment();
525
526 createFolder({"uidvalidity"});
527 createMessage({"uidvalidity"}, newMessage("new"));
528
529 // Ensure all local data is processed
530 VERIFYEXEC(Store::synchronize(folderSyncScope));
531 VERIFYEXEC(ResourceControl::flushMessageQueue(mResourceInstanceIdentifier));
532
533 //Now we should have one message
534 auto folder2 = Store::readOne<Folder>(Query{}.resourceFilter(mResourceInstanceIdentifier).filter<Folder::Name>("uidvalidity"));
535 Sink::Query query;
536 query.resourceFilter(mResourceInstanceIdentifier);
537 query.request<Mail::Subject>().request<Mail::MimeMessage>().request<Mail::Folder>().request<Mail::Date>();
538 query.filter<Mail::Folder>(folder2);
539 auto mails = Store::read<Mail>(query);
540 QCOMPARE(mails.size(), 1);
541 QCOMPARE(mails.first().getSubject(), {"new"});
542}
543
diff --git a/tests/mailsynctest.h b/tests/mailsynctest.h
index 0decf00..f197833 100644
--- a/tests/mailsynctest.h
+++ b/tests/mailsynctest.h
@@ -74,6 +74,7 @@ private slots:
74 void testSyncSingleMailWithBogusId(); 74 void testSyncSingleMailWithBogusId();
75 75
76 void testFailingSync(); 76 void testFailingSync();
77 void testSyncUidvalidity();
77}; 78};
78 79
79} 80}