summaryrefslogtreecommitdiffstats
path: root/examples/imapresource/imapresource.cpp
diff options
context:
space:
mode:
authorChristian Mollekopf <chrigi_1@fastmail.fm>2016-06-03 09:40:31 +0200
committerChristian Mollekopf <chrigi_1@fastmail.fm>2016-06-03 09:40:31 +0200
commitb5789da647bfdba9e3cc9b0595271b4d8c42bb8c (patch)
tree421bed2f38c9eac1d2d6579bf6a45b95c33cfbbf /examples/imapresource/imapresource.cpp
parentf5b254c87a993988c9cb1fd06b5635f1a6b20f9f (diff)
downloadsink-b5789da647bfdba9e3cc9b0595271b4d8c42bb8c.tar.gz
sink-b5789da647bfdba9e3cc9b0595271b4d8c42bb8c.zip
The imap resource can write-back changes
Diffstat (limited to 'examples/imapresource/imapresource.cpp')
-rw-r--r--examples/imapresource/imapresource.cpp148
1 files changed, 145 insertions, 3 deletions
diff --git a/examples/imapresource/imapresource.cpp b/examples/imapresource/imapresource.cpp
index 4122a69..2dfb2ea 100644
--- a/examples/imapresource/imapresource.cpp
+++ b/examples/imapresource/imapresource.cpp
@@ -330,6 +330,76 @@ public:
330 330
331 KAsync::Job<QByteArray> replay(const ApplicationDomain::Mail &mail, Sink::Operation operation, const QByteArray &oldRemoteId) 331 KAsync::Job<QByteArray> replay(const ApplicationDomain::Mail &mail, Sink::Operation operation, const QByteArray &oldRemoteId)
332 { 332 {
333 auto imap = QSharedPointer<ImapServerProxy>::create(mServer, mPort);
334 auto login = imap->login(mUser, mPassword);
335 if (operation == Sink::Operation_Creation) {
336 auto parentRemoteId = syncStore().resolveLocalId("folder", mail.getFolder());
337 QString mailbox = parentRemoteId;
338 QByteArray content = KMime::LFtoCRLF(mail.getMimeMessage());
339 QByteArrayList flags;
340 if (!mail.getUnread()) {
341 flags << Imap::Flags::Seen;
342 }
343 if (mail.getImportant()) {
344 flags << Imap::Flags::Flagged;
345 }
346 QDateTime internalDate = mail.getDate();
347 auto rid = QSharedPointer<QByteArray>::create();
348 return login.then(imap->append(mailbox, content, flags, internalDate))
349 .then<void, qint64>([imap, mailbox, rid](qint64 uid) {
350 const auto remoteId = mailbox.toUtf8() + "/" + QByteArray::number(uid);
351 //FIXME this get's called after the final error ahndler? WTF?
352 Trace() << "Finished creating a new mail: " << remoteId;
353 *rid = remoteId;
354 }).then<QByteArray>([rid, imap]() { //FIXME fix KJob so we don't need this extra clause
355 return *rid;
356 });
357 } else if (operation == Sink::Operation_Removal) {
358 auto ridParts = oldRemoteId.split('/');
359 auto uid = ridParts.takeLast().toLongLong();
360 //FIXME don't hardcode the separator
361 auto mailbox = ridParts.join('.');
362 Trace() << "Removing a mail: " << oldRemoteId << "in the mailbox: " << mailbox;
363 KIMAP::ImapSet set;
364 set.add(uid);
365 return login.then(imap->remove(mailbox, set))
366 .then<QByteArray>([imap, oldRemoteId]() {
367 Trace() << "Finished removing a mail: " << oldRemoteId;
368 return QByteArray();
369 });
370 } else if (operation == Sink::Operation_Modification) {
371 auto ridParts = oldRemoteId.split('/');
372 auto uid = ridParts.takeLast().toLongLong();
373 //FIXME don't hardcode the separator
374 auto mailbox = ridParts.join('.');
375 Trace() << "Modifying a mail: " << oldRemoteId << " in the mailbox: " << mailbox;
376 //TODO if the message changed, remove old message and create a new one,
377 //otherwise only change flags
378
379 QByteArrayList flags;
380 if (!mail.getUnread()) {
381 flags << Imap::Flags::Seen;
382 }
383 if (mail.getImportant()) {
384 flags << Imap::Flags::Flagged;
385 }
386
387 QByteArray content = KMime::LFtoCRLF(mail.getMimeMessage());
388 QDateTime internalDate = mail.getDate();
389 auto rid = QSharedPointer<QByteArray>::create();
390 KIMAP::ImapSet set;
391 set.add(uid);
392 return login.then(imap->append(mailbox, content, flags, internalDate))
393 .then<void, qint64>([imap, mailbox, rid](qint64 uid) {
394 const auto remoteId = mailbox + "/" + QByteArray::number(uid);
395 Trace() << "Finished creating a modified mail: " << remoteId;
396 *rid = remoteId;
397 })
398 .then(imap->remove(mailbox, set))
399 .then<QByteArray>([rid, imap]() {
400 return *rid;
401 });
402 }
333 return KAsync::null<QByteArray>(); 403 return KAsync::null<QByteArray>();
334 } 404 }
335 405
@@ -439,19 +509,61 @@ KAsync::Job<void> ImapResource::inspect(int inspectionType, const QByteArray &in
439 const auto folderRemoteId = syncStore->resolveLocalId(ENTITY_TYPE_FOLDER, mail.getFolder()); 509 const auto folderRemoteId = syncStore->resolveLocalId(ENTITY_TYPE_FOLDER, mail.getFolder());
440 const auto mailRemoteId = syncStore->resolveLocalId(ENTITY_TYPE_MAIL, mail.identifier()); 510 const auto mailRemoteId = syncStore->resolveLocalId(ENTITY_TYPE_MAIL, mail.identifier());
441 if (mailRemoteId.isEmpty() || folderRemoteId.isEmpty()) { 511 if (mailRemoteId.isEmpty() || folderRemoteId.isEmpty()) {
442 KAsync::error<void>(); 512 Warning() << "Missing remote id for folder or mail. " << mailRemoteId << folderRemoteId;
513 return KAsync::error<void>();
443 } 514 }
515 auto uid = mailRemoteId.split('/').last().toLongLong();
444 Trace() << "Mail remote id: " << folderRemoteId << mailRemoteId << mail.identifier() << folder.identifier(); 516 Trace() << "Mail remote id: " << folderRemoteId << mailRemoteId << mail.identifier() << folder.identifier();
445 517
518 KIMAP::ImapSet set;
519 set.add(uid);
520 if (set.isEmpty()) {
521 return KAsync::error<void>(1, "Couldn't determine uid of mail.");
522 }
523 KIMAP::FetchJob::FetchScope scope;
524 scope.mode = KIMAP::FetchJob::FetchScope::Full;
525 auto imap = QSharedPointer<ImapServerProxy>::create(mServer, mPort);
526 auto messageByUid = QSharedPointer<QHash<qint64, Imap::Message>>::create();
527 auto inspectionJob = imap->login(mUser, mPassword)
528 .then<void>(imap->select(folderRemoteId))
529 .then<void>(imap->fetch(set, scope, [imap, messageByUid](const QVector<Imap::Message> &messages) {
530 for (const auto &m : messages) {
531 messageByUid->insert(m.uid, m);
532 }
533 }));
534
446 if (inspectionType == Sink::ResourceControl::Inspection::PropertyInspectionType) { 535 if (inspectionType == Sink::ResourceControl::Inspection::PropertyInspectionType) {
447 if (property == "unread") { 536 if (property == "unread") {
448 return KAsync::null<void>(); 537 return inspectionJob.then<void, KAsync::Job<void>>([=]() {
538 auto msg = messageByUid->value(uid);
539 if (expectedValue.toBool() && msg.flags.contains(Imap::Flags::Seen)) {
540 return KAsync::error<void>(1, "Expected unread but couldn't find it.");
541 }
542 if (!expectedValue.toBool() && !msg.flags.contains(Imap::Flags::Seen)) {
543 return KAsync::error<void>(1, "Expected read but couldn't find it.");
544 }
545 return KAsync::null<void>();
546 });
449 } 547 }
450 if (property == "subject") { 548 if (property == "subject") {
451 return KAsync::null<void>(); 549 return inspectionJob.then<void, KAsync::Job<void>>([=]() {
550 auto msg = messageByUid->value(uid);
551 if (msg.msg->subject(true)->asUnicodeString() != expectedValue.toString()) {
552 return KAsync::error<void>(1, "Subject not as expected: " + msg.msg->subject(true)->asUnicodeString());
553 }
554 return KAsync::null<void>();
555 });
452 } 556 }
453 } 557 }
454 if (inspectionType == Sink::ResourceControl::Inspection::ExistenceInspectionType) { 558 if (inspectionType == Sink::ResourceControl::Inspection::ExistenceInspectionType) {
559 return inspectionJob.then<void, KAsync::Job<void>>([=]() {
560 if (!messageByUid->contains(uid)) {
561 Warning() << "Existing messages are: " << messageByUid->keys();
562 Warning() << "We're looking for: " << uid;
563 return KAsync::error<void>(1, "Couldn't find message: " + mailRemoteId);
564 }
565 return KAsync::null<void>();
566 });
455 } 567 }
456 } 568 }
457 if (domainType == ENTITY_TYPE_FOLDER) { 569 if (domainType == ENTITY_TYPE_FOLDER) {
@@ -459,6 +571,36 @@ KAsync::Job<void> ImapResource::inspect(int inspectionType, const QByteArray &in
459 const auto folder = entityStore->read<Sink::ApplicationDomain::Folder>(entityId); 571 const auto folder = entityStore->read<Sink::ApplicationDomain::Folder>(entityId);
460 572
461 if (inspectionType == Sink::ResourceControl::Inspection::CacheIntegrityInspectionType) { 573 if (inspectionType == Sink::ResourceControl::Inspection::CacheIntegrityInspectionType) {
574 Warning() << "Inspecting cache integrity" << remoteId;
575
576 int expectedCount = 0;
577 Index index("mail.index.folder", transaction);
578 index.lookup(entityId, [&](const QByteArray &sinkId) {
579 expectedCount++;
580 },
581 [&](const Index::Error &error) {
582 Warning() << "Error in index: " << error.message << property;
583 });
584
585 auto set = KIMAP::ImapSet::fromImapSequenceSet("1:*");
586 KIMAP::FetchJob::FetchScope scope;
587 scope.mode = KIMAP::FetchJob::FetchScope::Headers;
588 auto imap = QSharedPointer<ImapServerProxy>::create(mServer, mPort);
589 auto messageByUid = QSharedPointer<QHash<qint64, Imap::Message>>::create();
590 auto inspectionJob = imap->login(mUser, mPassword)
591 .then<void>(imap->select(remoteId))
592 .then<void>(imap->fetch(set, scope, [=](const QVector<Imap::Message> &messages) {
593 for (const auto &m : messages) {
594 messageByUid->insert(m.uid, m);
595 }
596 }))
597 .then<void, KAsync::Job<void>>([imap, messageByUid, expectedCount]() {
598 if (messageByUid->size() != expectedCount) {
599 return KAsync::error<void>(1, QString("Wrong number of files; found %1 instead of %2.").arg(messageByUid->size()).arg(expectedCount));
600 }
601 return KAsync::null<void>();
602 });
603 return inspectionJob;
462 } 604 }
463 if (inspectionType == Sink::ResourceControl::Inspection::ExistenceInspectionType) { 605 if (inspectionType == Sink::ResourceControl::Inspection::ExistenceInspectionType) {
464 auto folderByPath = QSharedPointer<QSet<QString>>::create(); 606 auto folderByPath = QSharedPointer<QSet<QString>>::create();