summaryrefslogtreecommitdiffstats
path: root/examples/imapresource/imapresource.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'examples/imapresource/imapresource.cpp')
-rw-r--r--examples/imapresource/imapresource.cpp139
1 files changed, 98 insertions, 41 deletions
diff --git a/examples/imapresource/imapresource.cpp b/examples/imapresource/imapresource.cpp
index 09f57d5..0579dae 100644
--- a/examples/imapresource/imapresource.cpp
+++ b/examples/imapresource/imapresource.cpp
@@ -100,7 +100,7 @@ public:
100 QByteArray createFolder(const Imap::Folder &f) 100 QByteArray createFolder(const Imap::Folder &f)
101 { 101 {
102 const auto parentFolderRid = parentRid(f); 102 const auto parentFolderRid = parentRid(f);
103 SinkTrace() << "Creating folder: " << f.name() << parentFolderRid; 103 SinkTraceCtx(mLogCtx) << "Creating folder: " << f.name() << parentFolderRid;
104 104
105 const auto remoteId = folderRid(f); 105 const auto remoteId = folderRid(f);
106 Sink::ApplicationDomain::Folder folder; 106 Sink::ApplicationDomain::Folder folder;
@@ -123,7 +123,7 @@ public:
123 123
124 void synchronizeFolders(const QVector<Folder> &folderList) 124 void synchronizeFolders(const QVector<Folder> &folderList)
125 { 125 {
126 SinkTrace() << "Found folders " << folderList.size(); 126 SinkTraceCtx(mLogCtx) << "Found folders " << folderList.size();
127 127
128 scanForRemovals(ENTITY_TYPE_FOLDER, 128 scanForRemovals(ENTITY_TYPE_FOLDER,
129 [&folderList](const QByteArray &remoteId) -> bool { 129 [&folderList](const QByteArray &remoteId) -> bool {
@@ -164,14 +164,14 @@ public:
164 { 164 {
165 auto time = QSharedPointer<QTime>::create(); 165 auto time = QSharedPointer<QTime>::create();
166 time->start(); 166 time->start();
167 SinkTrace() << "Importing new mail." << folderRid; 167 SinkTraceCtx(mLogCtx) << "Importing new mail." << folderRid;
168 168
169 const auto folderLocalId = syncStore().resolveRemoteId(ENTITY_TYPE_FOLDER, folderRid); 169 const auto folderLocalId = syncStore().resolveRemoteId(ENTITY_TYPE_FOLDER, folderRid);
170 170
171 const auto remoteId = assembleMailRid(folderLocalId, message.uid); 171 const auto remoteId = assembleMailRid(folderLocalId, message.uid);
172 172
173 Q_ASSERT(message.msg); 173 Q_ASSERT(message.msg);
174 SinkTrace() << "Found a mail " << remoteId << message.msg->subject(true)->asUnicodeString() << message.flags; 174 SinkTraceCtx(mLogCtx) << "Found a mail " << remoteId << message.msg->subject(true)->asUnicodeString() << message.flags;
175 175
176 auto mail = Sink::ApplicationDomain::Mail::create(mResourceInstanceIdentifier); 176 auto mail = Sink::ApplicationDomain::Mail::create(mResourceInstanceIdentifier);
177 mail.setFolder(folderLocalId); 177 mail.setFolder(folderLocalId);
@@ -181,7 +181,7 @@ public:
181 181
182 createOrModify(ENTITY_TYPE_MAIL, remoteId, mail); 182 createOrModify(ENTITY_TYPE_MAIL, remoteId, mail);
183 // const auto elapsed = time->elapsed(); 183 // const auto elapsed = time->elapsed();
184 // SinkTrace() << "Synchronized " << count << " mails in " << folderRid << Sink::Log::TraceTime(elapsed) << " " << elapsed/qMax(count, 1) << " [ms/mail]"; 184 // SinkTraceCtx(mLogCtx) << "Synchronized " << count << " mails in " << folderRid << Sink::Log::TraceTime(elapsed) << " " << elapsed/qMax(count, 1) << " [ms/mail]";
185 } 185 }
186 186
187 void synchronizeRemovals(const QByteArray &folderRid, const QSet<qint64> &messages) 187 void synchronizeRemovals(const QByteArray &folderRid, const QSet<qint64> &messages)
@@ -194,7 +194,7 @@ public:
194 return; 194 return;
195 } 195 }
196 196
197 SinkTrace() << "Finding removed mail: " << folderLocalId << " remoteId: " << folderRid; 197 SinkTraceCtx(mLogCtx) << "Finding removed mail: " << folderLocalId << " remoteId: " << folderRid;
198 198
199 int count = 0; 199 int count = 0;
200 200
@@ -370,7 +370,7 @@ public:
370 370
371 Sink::QueryBase applyMailDefaults(const Sink::QueryBase &query) 371 Sink::QueryBase applyMailDefaults(const Sink::QueryBase &query)
372 { 372 {
373 auto defaultDateFilter = QDate::currentDate().addDays(-14); 373 auto defaultDateFilter = QDate::currentDate().addDays(0 - mDaysToSync);
374 auto queryWithDefaults = query; 374 auto queryWithDefaults = query;
375 if (!queryWithDefaults.hasFilter<ApplicationDomain::Mail::Date>()) { 375 if (!queryWithDefaults.hasFilter<ApplicationDomain::Mail::Date>()) {
376 queryWithDefaults.filter(ApplicationDomain::Mail::Date::name, QVariant::fromValue(defaultDateFilter)); 376 queryWithDefaults.filter(ApplicationDomain::Mail::Date::name, QVariant::fromValue(defaultDateFilter));
@@ -382,7 +382,11 @@ public:
382 { 382 {
383 QList<Synchronizer::SyncRequest> list; 383 QList<Synchronizer::SyncRequest> list;
384 if (query.type() == ApplicationDomain::getTypeName<ApplicationDomain::Mail>()) { 384 if (query.type() == ApplicationDomain::getTypeName<ApplicationDomain::Mail>()) {
385 list << Synchronizer::SyncRequest{applyMailDefaults(query)}; 385 auto request = Synchronizer::SyncRequest{applyMailDefaults(query)};
386 if (query.hasFilter(ApplicationDomain::Mail::Folder::name)) {
387 request.applicableEntities << query.getFilter(ApplicationDomain::Mail::Folder::name).value.toByteArray();
388 }
389 list << request;
386 } else if (query.type() == ApplicationDomain::getTypeName<ApplicationDomain::Folder>()) { 390 } else if (query.type() == ApplicationDomain::getTypeName<ApplicationDomain::Folder>()) {
387 list << Synchronizer::SyncRequest{query}; 391 list << Synchronizer::SyncRequest{query};
388 } else { 392 } else {
@@ -393,15 +397,57 @@ public:
393 return list; 397 return list;
394 } 398 }
395 399
400 QByteArray getFolderFromLocalId(const QByteArray &id)
401 {
402 auto mailRemoteId = syncStore().resolveLocalId(ApplicationDomain::getTypeName<ApplicationDomain::Mail>(), id);
403 if (mailRemoteId.isEmpty()) {
404 return {};
405 }
406 return folderIdFromMailRid(mailRemoteId);
407 }
408
409 void mergeIntoQueue(const Synchronizer::SyncRequest &request, QList<Synchronizer::SyncRequest> &queue) Q_DECL_OVERRIDE
410 {
411 auto isIndividualMailSync = [](const Synchronizer::SyncRequest &request) {
412 if (request.requestType == SyncRequest::Synchronization) {
413 const auto query = request.query;
414 if (query.type() == ApplicationDomain::getTypeName<ApplicationDomain::Mail>()) {
415 return !query.ids().isEmpty();
416 }
417 }
418 return false;
419
420 };
421
422 if (isIndividualMailSync(request)) {
423 auto newId = request.query.ids().first();
424 auto requestFolder = getFolderFromLocalId(newId);
425 if (requestFolder.isEmpty()) {
426 SinkWarningCtx(mLogCtx) << "Failed to find folder for local id. Ignoring request: " << request.query;
427 return;
428 }
429 for (auto &r : queue) {
430 if (isIndividualMailSync(r)) {
431 auto queueFolder = getFolderFromLocalId(r.query.ids().first());
432 if (requestFolder == queueFolder) {
433 //Merge
434 r.query.filter(newId);
435 SinkTrace() << "Merging request " << request.query;
436 SinkTrace() << " to " << r.query;
437 return;
438 }
439 }
440 }
441 }
442 queue << request;
443 }
444
396 KAsync::Job<void> login(QSharedPointer<ImapServerProxy> imap) 445 KAsync::Job<void> login(QSharedPointer<ImapServerProxy> imap)
397 { 446 {
398 SinkTrace() << "Connecting to:" << mServer << mPort; 447 SinkTrace() << "Connecting to:" << mServer << mPort;
399 SinkTrace() << "as:" << mUser; 448 SinkTrace() << "as:" << mUser;
400 return imap->login(mUser, mPassword) 449 return imap->login(mUser, mPassword)
401 .addToContext(imap) 450 .addToContext(imap);
402 .onError([](const KAsync::Error &error) {
403 SinkWarning() << "Login failed.";
404 });
405 } 451 }
406 452
407 KAsync::Job<QVector<Folder>> getFolderList(QSharedPointer<ImapServerProxy> imap, const Sink::QueryBase &query) 453 KAsync::Job<QVector<Folder>> getFolderList(QSharedPointer<ImapServerProxy> imap, const Sink::QueryBase &query)
@@ -431,6 +477,19 @@ public:
431 } 477 }
432 } 478 }
433 479
480 KAsync::Error getError(const KAsync::Error &error)
481 {
482 if (error) {
483 if (error.errorCode == Imap::CouldNotConnectError) {
484 return {ApplicationDomain::ConnectionError, error.errorMessage};
485 } else if (error.errorCode == Imap::SslHandshakeError) {
486 return {ApplicationDomain::LoginError, error.errorMessage};
487 }
488 return {ApplicationDomain::UnknownError, error.errorMessage};
489 }
490 return {};
491 }
492
434 KAsync::Job<void> synchronizeWithSource(const Sink::QueryBase &query) Q_DECL_OVERRIDE 493 KAsync::Job<void> synchronizeWithSource(const Sink::QueryBase &query) Q_DECL_OVERRIDE
435 { 494 {
436 auto imap = QSharedPointer<ImapServerProxy>::create(mServer, mPort, &mSessionCache); 495 auto imap = QSharedPointer<ImapServerProxy>::create(mServer, mPort, &mSessionCache);
@@ -446,11 +505,8 @@ public:
446 }); 505 });
447 }) 506 })
448 .then([=] (const KAsync::Error &error) { 507 .then([=] (const KAsync::Error &error) {
449 if (error) {
450 SinkWarning() << "Error during folder sync: " << error.errorMessage;
451 }
452 return imap->logout() 508 return imap->logout()
453 .then(KAsync::error(error)); 509 .then(KAsync::error(getError(error)));
454 }); 510 });
455 } else if (query.type() == ApplicationDomain::getTypeName<ApplicationDomain::Mail>()) { 511 } else if (query.type() == ApplicationDomain::getTypeName<ApplicationDomain::Mail>()) {
456 //TODO 512 //TODO
@@ -487,7 +543,7 @@ public:
487 synchronizeMails(folderRemoteId, m); 543 synchronizeMails(folderRemoteId, m);
488 }, 544 },
489 [=](int progress, int total) { 545 [=](int progress, int total) {
490 SinkLogCtx(mLogCtx) << "Progress: " << progress << " out of " << total; 546 reportProgress(progress, total);
491 //commit every 100 messages 547 //commit every 100 messages
492 if ((progress % 100) == 0) { 548 if ((progress % 100) == 0) {
493 commit(); 549 commit();
@@ -503,6 +559,8 @@ public:
503 return KAsync::value(folders) 559 return KAsync::value(folders)
504 .serialEach<void>([=](const Folder &folder) { 560 .serialEach<void>([=](const Folder &folder) {
505 SinkLog() << "Syncing folder " << folder.path(); 561 SinkLog() << "Syncing folder " << folder.path();
562 //Emit notification that the folder is being synced.
563 //The synchronizer can't do that because it has no concept of the folder filter on a mail sync scope meaning that the folder is being synchronized.
506 QDate dateFilter; 564 QDate dateFilter;
507 auto filter = query.getFilter<ApplicationDomain::Mail::Date>(); 565 auto filter = query.getFilter<ApplicationDomain::Mail::Date>();
508 if (filter.value.canConvert<QDate>()) { 566 if (filter.value.canConvert<QDate>()) {
@@ -510,7 +568,7 @@ public:
510 SinkLog() << " with date-range " << dateFilter; 568 SinkLog() << " with date-range " << dateFilter;
511 } 569 }
512 return synchronizeFolder(imap, folder, dateFilter, syncHeaders) 570 return synchronizeFolder(imap, folder, dateFilter, syncHeaders)
513 .onError([folder](const KAsync::Error &error) { 571 .onError([=](const KAsync::Error &error) {
514 SinkWarning() << "Failed to sync folder: " << folder.path() << "Error: " << error.errorMessage; 572 SinkWarning() << "Failed to sync folder: " << folder.path() << "Error: " << error.errorMessage;
515 }); 573 });
516 }); 574 });
@@ -518,11 +576,8 @@ public:
518 } 576 }
519 }) 577 })
520 .then([=] (const KAsync::Error &error) { 578 .then([=] (const KAsync::Error &error) {
521 if (error) {
522 SinkWarning() << "Error during sync: " << error.errorMessage;
523 }
524 return imap->logout() 579 return imap->logout()
525 .then(KAsync::error(error)); 580 .then(KAsync::error(getError(error)));
526 }); 581 });
527 } 582 }
528 return KAsync::error<void>("Nothing to do"); 583 return KAsync::error<void>("Nothing to do");
@@ -616,11 +671,11 @@ public:
616 if (!folder.getParent().isEmpty()) { 671 if (!folder.getParent().isEmpty()) {
617 parentFolder = syncStore().resolveLocalId(ENTITY_TYPE_FOLDER, folder.getParent()); 672 parentFolder = syncStore().resolveLocalId(ENTITY_TYPE_FOLDER, folder.getParent());
618 } 673 }
619 SinkTrace() << "Creating a new folder: " << parentFolder << folder.getName(); 674 SinkTraceCtx(mLogCtx) << "Creating a new folder: " << parentFolder << folder.getName();
620 auto rid = QSharedPointer<QByteArray>::create(); 675 auto rid = QSharedPointer<QByteArray>::create();
621 auto createFolder = login.then(imap->createSubfolder(parentFolder, folder.getName())) 676 auto createFolder = login.then(imap->createSubfolder(parentFolder, folder.getName()))
622 .then([imap, rid](const QString &createdFolder) { 677 .then([this, imap, rid](const QString &createdFolder) {
623 SinkTrace() << "Finished creating a new folder: " << createdFolder; 678 SinkTraceCtx(mLogCtx) << "Finished creating a new folder: " << createdFolder;
624 *rid = createdFolder.toUtf8(); 679 *rid = createdFolder.toUtf8();
625 }); 680 });
626 if (folder.getSpecialPurpose().isEmpty()) { 681 if (folder.getSpecialPurpose().isEmpty()) {
@@ -636,19 +691,19 @@ public:
636 specialPurposeFolders->insert(SpecialPurpose::getSpecialPurposeType(folder.name()), folder.path()); 691 specialPurposeFolders->insert(SpecialPurpose::getSpecialPurposeType(folder.name()), folder.path());
637 }; 692 };
638 })) 693 }))
639 .then([specialPurposeFolders, folder, imap, parentFolder, rid]() -> KAsync::Job<void> { 694 .then([this, specialPurposeFolders, folder, imap, parentFolder, rid]() -> KAsync::Job<void> {
640 for (const auto &purpose : folder.getSpecialPurpose()) { 695 for (const auto &purpose : folder.getSpecialPurpose()) {
641 if (specialPurposeFolders->contains(purpose)) { 696 if (specialPurposeFolders->contains(purpose)) {
642 auto f = specialPurposeFolders->value(purpose); 697 auto f = specialPurposeFolders->value(purpose);
643 SinkTrace() << "Merging specialpurpose folder with: " << f << " with purpose: " << purpose; 698 SinkTraceCtx(mLogCtx) << "Merging specialpurpose folder with: " << f << " with purpose: " << purpose;
644 *rid = f.toUtf8(); 699 *rid = f.toUtf8();
645 return KAsync::null<void>(); 700 return KAsync::null<void>();
646 } 701 }
647 } 702 }
648 SinkTrace() << "No match found for merging, creating a new folder"; 703 SinkTraceCtx(mLogCtx) << "No match found for merging, creating a new folder";
649 return imap->createSubfolder(parentFolder, folder.getName()) 704 return imap->createSubfolder(parentFolder, folder.getName())
650 .then([imap, rid](const QString &createdFolder) { 705 .then([this, imap, rid](const QString &createdFolder) {
651 SinkTrace() << "Finished creating a new folder: " << createdFolder; 706 SinkTraceCtx(mLogCtx) << "Finished creating a new folder: " << createdFolder;
652 *rid = createdFolder.toUtf8(); 707 *rid = createdFolder.toUtf8();
653 }); 708 });
654 709
@@ -659,18 +714,18 @@ public:
659 return mergeJob; 714 return mergeJob;
660 } 715 }
661 } else if (operation == Sink::Operation_Removal) { 716 } else if (operation == Sink::Operation_Removal) {
662 SinkTrace() << "Removing a folder: " << oldRemoteId; 717 SinkTraceCtx(mLogCtx) << "Removing a folder: " << oldRemoteId;
663 return login.then(imap->remove(oldRemoteId)) 718 return login.then(imap->remove(oldRemoteId))
664 .then([oldRemoteId, imap] { 719 .then([this, oldRemoteId, imap] {
665 SinkTrace() << "Finished removing a folder: " << oldRemoteId; 720 SinkTraceCtx(mLogCtx) << "Finished removing a folder: " << oldRemoteId;
666 return QByteArray(); 721 return QByteArray();
667 }); 722 });
668 } else if (operation == Sink::Operation_Modification) { 723 } else if (operation == Sink::Operation_Modification) {
669 SinkTrace() << "Renaming a folder: " << oldRemoteId << folder.getName(); 724 SinkTraceCtx(mLogCtx) << "Renaming a folder: " << oldRemoteId << folder.getName();
670 auto rid = QSharedPointer<QByteArray>::create(); 725 auto rid = QSharedPointer<QByteArray>::create();
671 return login.then(imap->renameSubfolder(oldRemoteId, folder.getName())) 726 return login.then(imap->renameSubfolder(oldRemoteId, folder.getName()))
672 .then([imap, rid](const QString &createdFolder) { 727 .then([this, imap, rid](const QString &createdFolder) {
673 SinkTrace() << "Finished renaming a folder: " << createdFolder; 728 SinkTraceCtx(mLogCtx) << "Finished renaming a folder: " << createdFolder;
674 *rid = createdFolder.toUtf8(); 729 *rid = createdFolder.toUtf8();
675 }) 730 })
676 .then([rid] { 731 .then([rid] {
@@ -685,6 +740,7 @@ public:
685 int mPort; 740 int mPort;
686 QString mUser; 741 QString mUser;
687 QString mPassword; 742 QString mPassword;
743 int mDaysToSync = 0;
688 QByteArray mResourceInstanceIdentifier; 744 QByteArray mResourceInstanceIdentifier;
689 Imap::SessionCache mSessionCache; 745 Imap::SessionCache mSessionCache;
690}; 746};
@@ -864,6 +920,7 @@ ImapResource::ImapResource(const ResourceContext &resourceContext)
864 synchronizer->mPort = port; 920 synchronizer->mPort = port;
865 synchronizer->mUser = user; 921 synchronizer->mUser = user;
866 synchronizer->mPassword = password; 922 synchronizer->mPassword = password;
923 synchronizer->mDaysToSync = 14;
867 setupSynchronizer(synchronizer); 924 setupSynchronizer(synchronizer);
868 925
869 auto inspector = QSharedPointer<ImapInspector>::create(resourceContext); 926 auto inspector = QSharedPointer<ImapInspector>::create(resourceContext);
@@ -873,7 +930,7 @@ ImapResource::ImapResource(const ResourceContext &resourceContext)
873 inspector->mPassword = password; 930 inspector->mPassword = password;
874 setupInspector(inspector); 931 setupInspector(inspector);
875 932
876 setupPreprocessors(ENTITY_TYPE_MAIL, QVector<Sink::Preprocessor*>() << new SpecialPurposeProcessor(resourceContext.resourceType, resourceContext.instanceId()) << new MailPropertyExtractor); 933 setupPreprocessors(ENTITY_TYPE_MAIL, QVector<Sink::Preprocessor*>() << new SpecialPurposeProcessor << new MailPropertyExtractor);
877 setupPreprocessors(ENTITY_TYPE_FOLDER, QVector<Sink::Preprocessor*>()); 934 setupPreprocessors(ENTITY_TYPE_FOLDER, QVector<Sink::Preprocessor*>());
878} 935}
879 936
@@ -898,14 +955,14 @@ Sink::Resource *ImapResourceFactory::createResource(const ResourceContext &conte
898 955
899void ImapResourceFactory::registerFacades(const QByteArray &name, Sink::FacadeFactory &factory) 956void ImapResourceFactory::registerFacades(const QByteArray &name, Sink::FacadeFactory &factory)
900{ 957{
901 factory.registerFacade<Sink::ApplicationDomain::Mail, ImapResourceMailFacade>(name); 958 factory.registerFacade<ApplicationDomain::Mail, DefaultFacade<ApplicationDomain::Mail>>(name);
902 factory.registerFacade<Sink::ApplicationDomain::Folder, ImapResourceFolderFacade>(name); 959 factory.registerFacade<ApplicationDomain::Folder, DefaultFacade<ApplicationDomain::Folder>>(name);
903} 960}
904 961
905void ImapResourceFactory::registerAdaptorFactories(const QByteArray &name, Sink::AdaptorFactoryRegistry &registry) 962void ImapResourceFactory::registerAdaptorFactories(const QByteArray &name, Sink::AdaptorFactoryRegistry &registry)
906{ 963{
907 registry.registerFactory<Sink::ApplicationDomain::Mail, ImapMailAdaptorFactory>(name); 964 registry.registerFactory<ApplicationDomain::Mail, DefaultAdaptorFactory<ApplicationDomain::Mail>>(name);
908 registry.registerFactory<Sink::ApplicationDomain::Folder, ImapFolderAdaptorFactory>(name); 965 registry.registerFactory<ApplicationDomain::Folder, DefaultAdaptorFactory<ApplicationDomain::Folder>>(name);
909} 966}
910 967
911void ImapResourceFactory::removeDataFromDisk(const QByteArray &instanceIdentifier) 968void ImapResourceFactory::removeDataFromDisk(const QByteArray &instanceIdentifier)