diff options
Diffstat (limited to 'examples/imapresource')
-rw-r--r-- | examples/imapresource/imapresource.cpp | 67 | ||||
-rw-r--r-- | examples/imapresource/imapserverproxy.cpp | 50 | ||||
-rw-r--r-- | examples/imapresource/imapserverproxy.h | 14 |
3 files changed, 99 insertions, 32 deletions
diff --git a/examples/imapresource/imapresource.cpp b/examples/imapresource/imapresource.cpp index 24fd426..3ad80f9 100644 --- a/examples/imapresource/imapresource.cpp +++ b/examples/imapresource/imapresource.cpp | |||
@@ -211,14 +211,49 @@ public: | |||
211 | SinkLog() << "Removed " << count << " mails in " << path << Sink::Log::TraceTime(elapsed) << " " << elapsed/qMax(count, 1) << " [ms/mail]"; | 211 | SinkLog() << "Removed " << count << " mails in " << path << Sink::Log::TraceTime(elapsed) << " " << elapsed/qMax(count, 1) << " [ms/mail]"; |
212 | } | 212 | } |
213 | 213 | ||
214 | KAsync::Job<void> synchronizeFolder(QSharedPointer<ImapServerProxy> imap, const Imap::Folder &folder) | ||
215 | { | ||
216 | QSet<qint64> uids; | ||
217 | SinkLog() << "Synchronizing mails" << folder.normalizedPath(); | ||
218 | auto capabilities = imap->getCapabilities(); | ||
219 | bool canDoIncrementalRemovals = false; | ||
220 | return KAsync::start<void>([=]() { | ||
221 | //TODO update flags | ||
222 | }) | ||
223 | .then<void, KAsync::Job<void>>([=]() { | ||
224 | //TODO Remove what's no longer existing | ||
225 | if (canDoIncrementalRemovals) { | ||
226 | } else { | ||
227 | return imap->fetchUids(folder).then<void, QVector<qint64>>([this, folder](const QVector<qint64> &uids) { | ||
228 | SinkTrace() << "Syncing removals"; | ||
229 | synchronizeRemovals(folder.normalizedPath(), uids.toList().toSet()); | ||
230 | commit(); | ||
231 | }).then<void>([](){}); | ||
232 | } | ||
233 | return KAsync::null<void>(); | ||
234 | }) | ||
235 | .then<void, KAsync::Job<void>>([this, folder, imap]() { | ||
236 | auto uidNext = 0; | ||
237 | return imap->fetchMessages(folder, uidNext, [this, folder](const QVector<Message> &messages) { | ||
238 | SinkTrace() << "Got mail"; | ||
239 | synchronizeMails(folder.normalizedPath(), messages); | ||
240 | }, | ||
241 | [](int progress, int total) { | ||
242 | SinkTrace() << "Progress: " << progress << " out of " << total; | ||
243 | }); | ||
244 | }); | ||
245 | |||
246 | |||
247 | } | ||
248 | |||
214 | KAsync::Job<void> synchronizeWithSource() Q_DECL_OVERRIDE | 249 | KAsync::Job<void> synchronizeWithSource() Q_DECL_OVERRIDE |
215 | { | 250 | { |
216 | SinkLog() << " Synchronizing"; | 251 | SinkLog() << " Synchronizing"; |
217 | return KAsync::start<void>([this](KAsync::Future<void> future) { | 252 | return KAsync::start<void>([this](KAsync::Future<void> future) { |
218 | SinkTrace() << "Connecting to:" << mServer << mPort; | 253 | SinkTrace() << "Connecting to:" << mServer << mPort; |
219 | SinkTrace() << "as:" << mUser; | 254 | SinkTrace() << "as:" << mUser; |
220 | ImapServerProxy imap(mServer, mPort); | 255 | auto imap = QSharedPointer<ImapServerProxy>::create(mServer, mPort); |
221 | auto loginFuture = imap.login(mUser, mPassword).exec(); | 256 | auto loginFuture = imap->login(mUser, mPassword).exec(); |
222 | loginFuture.waitForFinished(); | 257 | loginFuture.waitForFinished(); |
223 | if (loginFuture.errorCode()) { | 258 | if (loginFuture.errorCode()) { |
224 | SinkWarning() << "Login failed."; | 259 | SinkWarning() << "Login failed."; |
@@ -229,7 +264,7 @@ public: | |||
229 | } | 264 | } |
230 | 265 | ||
231 | QVector<Folder> folderList; | 266 | QVector<Folder> folderList; |
232 | auto folderFuture = imap.fetchFolders([this, &imap, &folderList](const QVector<Folder> &folders) { | 267 | auto folderFuture = imap->fetchFolders([this, &imap, &folderList](const QVector<Folder> &folders) { |
233 | synchronizeFolders(folders); | 268 | synchronizeFolders(folders); |
234 | commit(); | 269 | commit(); |
235 | folderList << folders; | 270 | folderList << folders; |
@@ -248,27 +283,7 @@ public: | |||
248 | if (folder.noselect) { | 283 | if (folder.noselect) { |
249 | continue; | 284 | continue; |
250 | } | 285 | } |
251 | QSet<qint64> uids; | 286 | synchronizeFolder(imap, folder).exec().waitForFinished(); |
252 | SinkLog() << "Synchronizing mails" << folder.normalizedPath(); | ||
253 | auto messagesFuture = imap.fetchMessages(folder, [this, folder, &uids](const QVector<Message> &messages) { | ||
254 | for (const auto &msg : messages) { | ||
255 | uids << msg.uid; | ||
256 | } | ||
257 | synchronizeMails(folder.normalizedPath(), messages); | ||
258 | }, | ||
259 | [](int progress, int total) { | ||
260 | SinkTrace() << "Progress: " << progress << " out of " << total; | ||
261 | }).exec(); | ||
262 | messagesFuture.waitForFinished(); | ||
263 | commit(); | ||
264 | if (messagesFuture.errorCode()) { | ||
265 | SinkWarning() << "Folder sync failed: " << folder.normalizedPath(); | ||
266 | continue; | ||
267 | } | ||
268 | //Remove what there is to remove | ||
269 | synchronizeRemovals(folder.normalizedPath(), uids); | ||
270 | commit(); | ||
271 | SinkTrace() << "Folder synchronized: " << folder.normalizedPath(); | ||
272 | } | 287 | } |
273 | future.setFinished(); | 288 | future.setFinished(); |
274 | }); | 289 | }); |
@@ -541,7 +556,7 @@ KAsync::Job<void> ImapResource::inspect(int inspectionType, const QByteArray &in | |||
541 | SinkTrace() << "Connecting to:" << mServer << mPort; | 556 | SinkTrace() << "Connecting to:" << mServer << mPort; |
542 | SinkTrace() << "as:" << mUser; | 557 | SinkTrace() << "as:" << mUser; |
543 | auto inspectionJob = imap->login(mUser, mPassword) | 558 | auto inspectionJob = imap->login(mUser, mPassword) |
544 | .then<void>(imap->select(folderRemoteId)) | 559 | .then<void>(imap->select(folderRemoteId).then<void>([](){})) |
545 | .then<void>(imap->fetch(set, scope, [imap, messageByUid](const QVector<Imap::Message> &messages) { | 560 | .then<void>(imap->fetch(set, scope, [imap, messageByUid](const QVector<Imap::Message> &messages) { |
546 | for (const auto &m : messages) { | 561 | for (const auto &m : messages) { |
547 | messageByUid->insert(m.uid, m); | 562 | messageByUid->insert(m.uid, m); |
@@ -604,7 +619,7 @@ KAsync::Job<void> ImapResource::inspect(int inspectionType, const QByteArray &in | |||
604 | auto imap = QSharedPointer<ImapServerProxy>::create(mServer, mPort); | 619 | auto imap = QSharedPointer<ImapServerProxy>::create(mServer, mPort); |
605 | auto messageByUid = QSharedPointer<QHash<qint64, Imap::Message>>::create(); | 620 | auto messageByUid = QSharedPointer<QHash<qint64, Imap::Message>>::create(); |
606 | auto inspectionJob = imap->login(mUser, mPassword) | 621 | auto inspectionJob = imap->login(mUser, mPassword) |
607 | .then<void>(imap->select(remoteId)) | 622 | .then<void>(imap->select(remoteId).then<void>([](){})) |
608 | .then<void>(imap->fetch(set, scope, [=](const QVector<Imap::Message> &messages) { | 623 | .then<void>(imap->fetch(set, scope, [=](const QVector<Imap::Message> &messages) { |
609 | for (const auto &m : messages) { | 624 | for (const auto &m : messages) { |
610 | messageByUid->insert(m.uid, m); | 625 | messageByUid->insert(m.uid, m); |
diff --git a/examples/imapresource/imapserverproxy.cpp b/examples/imapresource/imapserverproxy.cpp index 3406315..5fffb36 100644 --- a/examples/imapresource/imapserverproxy.cpp +++ b/examples/imapresource/imapserverproxy.cpp | |||
@@ -33,6 +33,7 @@ | |||
33 | #include <KIMAP/KIMAP/StoreJob> | 33 | #include <KIMAP/KIMAP/StoreJob> |
34 | #include <KIMAP/KIMAP/ExpungeJob> | 34 | #include <KIMAP/KIMAP/ExpungeJob> |
35 | #include <KIMAP/KIMAP/CapabilitiesJob> | 35 | #include <KIMAP/KIMAP/CapabilitiesJob> |
36 | #include <KIMAP/KIMAP/SearchJob> | ||
36 | 37 | ||
37 | #include <KIMAP/KIMAP/SessionUiProxy> | 38 | #include <KIMAP/KIMAP/SessionUiProxy> |
38 | #include <KCoreAddons/KJob> | 39 | #include <KCoreAddons/KJob> |
@@ -188,12 +189,14 @@ KAsync::Job<void> ImapServerProxy::login(const QString &username, const QString | |||
188 | }); | 189 | }); |
189 | } | 190 | } |
190 | 191 | ||
191 | KAsync::Job<void> ImapServerProxy::select(const QString &mailbox) | 192 | KAsync::Job<SelectResult> ImapServerProxy::select(const QString &mailbox) |
192 | { | 193 | { |
193 | auto select = new KIMAP::SelectJob(mSession); | 194 | auto select = new KIMAP::SelectJob(mSession); |
194 | select->setMailBox(mailbox); | 195 | select->setMailBox(mailbox); |
195 | // select->setCondstoreEnabled(serverSupportsCondstore()); | 196 | select->setCondstoreEnabled(mCapabilities.contains("CONDSTORE")); |
196 | return runJob(select); | 197 | return runJob<SelectResult>(select, [select](KJob* job) -> SelectResult { |
198 | return {select->uidValidity(), select->nextUid(), select->highestModSequence()}; | ||
199 | }); | ||
197 | } | 200 | } |
198 | 201 | ||
199 | KAsync::Job<qint64> ImapServerProxy::append(const QString &mailbox, const QByteArray &content, const QList<QByteArray> &flags, const QDateTime &internalDate) | 202 | KAsync::Job<qint64> ImapServerProxy::append(const QString &mailbox, const QByteArray &content, const QList<QByteArray> &flags, const QDateTime &internalDate) |
@@ -303,6 +306,16 @@ KAsync::Job<void> ImapServerProxy::fetch(const KIMAP::ImapSet &set, KIMAP::Fetch | |||
303 | return runJob(fetch); | 306 | return runJob(fetch); |
304 | } | 307 | } |
305 | 308 | ||
309 | KAsync::Job<QVector<qint64>> ImapServerProxy::search(const KIMAP::ImapSet &set) | ||
310 | { | ||
311 | auto search = new KIMAP::SearchJob(mSession); | ||
312 | search->setTerm(KIMAP::Term(KIMAP::Term::Uid, set)); | ||
313 | search->setUidBased(true); | ||
314 | return runJob<QVector<qint64>>(search, [](KJob *job) -> QVector<qint64> { | ||
315 | return static_cast<KIMAP::SearchJob*>(job)->results(); | ||
316 | }); | ||
317 | } | ||
318 | |||
306 | KAsync::Job<void> ImapServerProxy::fetch(const KIMAP::ImapSet &set, KIMAP::FetchJob::FetchScope scope, const std::function<void(const QVector<Message> &)> &callback) | 319 | KAsync::Job<void> ImapServerProxy::fetch(const KIMAP::ImapSet &set, KIMAP::FetchJob::FetchScope scope, const std::function<void(const QVector<Message> &)> &callback) |
307 | { | 320 | { |
308 | return fetch(set, scope, | 321 | return fetch(set, scope, |
@@ -320,6 +333,11 @@ KAsync::Job<void> ImapServerProxy::fetch(const KIMAP::ImapSet &set, KIMAP::Fetch | |||
320 | }); | 333 | }); |
321 | } | 334 | } |
322 | 335 | ||
336 | QStringList ImapServerProxy::getCapabilities() const | ||
337 | { | ||
338 | return mCapabilities; | ||
339 | } | ||
340 | |||
323 | KAsync::Job<QList<qint64>> ImapServerProxy::fetchHeaders(const QString &mailbox) | 341 | KAsync::Job<QList<qint64>> ImapServerProxy::fetchHeaders(const QString &mailbox) |
324 | { | 342 | { |
325 | auto list = QSharedPointer<QList<qint64>>::create(); | 343 | auto list = QSharedPointer<QList<qint64>>::create(); |
@@ -351,6 +369,11 @@ KAsync::Job<QList<qint64>> ImapServerProxy::fetchHeaders(const QString &mailbox) | |||
351 | }); | 369 | }); |
352 | } | 370 | } |
353 | 371 | ||
372 | KAsync::Job<QVector<qint64>> ImapServerProxy::fetchUids(const QString &mailbox) | ||
373 | { | ||
374 | return select(mailbox).then<QVector<qint64>>(search(KIMAP::ImapSet(1, 0))); | ||
375 | } | ||
376 | |||
354 | KAsync::Job<void> ImapServerProxy::list(KIMAP::ListJob::Option option, const std::function<void(const QList<KIMAP::MailBoxDescriptor> &mailboxes,const QList<QList<QByteArray> > &flags)> &callback) | 377 | KAsync::Job<void> ImapServerProxy::list(KIMAP::ListJob::Option option, const std::function<void(const QList<KIMAP::MailBoxDescriptor> &mailboxes,const QList<QList<QByteArray> > &flags)> &callback) |
355 | { | 378 | { |
356 | auto listJob = new KIMAP::ListJob(mSession); | 379 | auto listJob = new KIMAP::ListJob(mSession); |
@@ -434,12 +457,19 @@ QString ImapServerProxy::mailboxFromFolder(const Folder &folder) const | |||
434 | return folder.pathParts.join(mPersonalNamespaceSeparator); | 457 | return folder.pathParts.join(mPersonalNamespaceSeparator); |
435 | } | 458 | } |
436 | 459 | ||
437 | KAsync::Job<void> ImapServerProxy::fetchMessages(const Folder &folder, std::function<void(const QVector<Message> &)> callback, std::function<void(int, int)> progress) | 460 | KAsync::Job<void> ImapServerProxy::fetchMessages(const Folder &folder, qint64 uidNext, std::function<void(const QVector<Message> &)> callback, std::function<void(int, int)> progress) |
438 | { | 461 | { |
462 | Q_UNUSED(uidNext); | ||
439 | auto time = QSharedPointer<QTime>::create(); | 463 | auto time = QSharedPointer<QTime>::create(); |
440 | time->start(); | 464 | time->start(); |
441 | Q_ASSERT(!mPersonalNamespaceSeparator.isNull()); | 465 | Q_ASSERT(!mPersonalNamespaceSeparator.isNull()); |
442 | return select(mailboxFromFolder(folder)).then<void, KAsync::Job<void>>([this, callback, folder, time, progress]() -> KAsync::Job<void> { | 466 | return select(mailboxFromFolder(folder)).then<void, KAsync::Job<void>, SelectResult>([this, callback, folder, time, progress, uidNext](const SelectResult &selectResult) -> KAsync::Job<void> { |
467 | |||
468 | if (selectResult.uidNext == uidNext) { | ||
469 | SinkTrace() << "Uidnext didn't change, nothing to do."; | ||
470 | return KAsync::null<void>(); | ||
471 | } | ||
472 | |||
443 | return fetchHeaders(mailboxFromFolder(folder)).then<void, KAsync::Job<void>, QList<qint64>>([this, callback, time, progress](const QList<qint64> &uidsToFetch){ | 473 | return fetchHeaders(mailboxFromFolder(folder)).then<void, KAsync::Job<void>, QList<qint64>>([this, callback, time, progress](const QList<qint64> &uidsToFetch){ |
444 | SinkTrace() << "Fetched headers"; | 474 | SinkTrace() << "Fetched headers"; |
445 | SinkTrace() << " Total: " << uidsToFetch.size(); | 475 | SinkTrace() << " Total: " << uidsToFetch.size(); |
@@ -472,3 +502,13 @@ KAsync::Job<void> ImapServerProxy::fetchMessages(const Folder &folder, std::func | |||
472 | 502 | ||
473 | }); | 503 | }); |
474 | } | 504 | } |
505 | |||
506 | KAsync::Job<void> ImapServerProxy::fetchMessages(const Folder &folder, std::function<void(const QVector<Message> &)> callback, std::function<void(int, int)> progress) | ||
507 | { | ||
508 | return fetchMessages(folder, 0, callback, progress); | ||
509 | } | ||
510 | |||
511 | KAsync::Job<QVector<qint64>> ImapServerProxy::fetchUids(const Folder &folder) | ||
512 | { | ||
513 | return fetchUids(mailboxFromFolder(folder)); | ||
514 | } | ||
diff --git a/examples/imapresource/imapserverproxy.h b/examples/imapresource/imapserverproxy.h index f3e1794..9baa52c 100644 --- a/examples/imapresource/imapserverproxy.h +++ b/examples/imapresource/imapserverproxy.h | |||
@@ -75,6 +75,12 @@ struct Folder { | |||
75 | bool noselect; | 75 | bool noselect; |
76 | }; | 76 | }; |
77 | 77 | ||
78 | struct SelectResult { | ||
79 | qint64 uidValidity; | ||
80 | qint64 uidNext; | ||
81 | quint64 highestModSequence; | ||
82 | }; | ||
83 | |||
78 | class ImapServerProxy { | 84 | class ImapServerProxy { |
79 | KIMAP::Session *mSession; | 85 | KIMAP::Session *mSession; |
80 | QStringList mCapabilities; | 86 | QStringList mCapabilities; |
@@ -91,7 +97,7 @@ public: | |||
91 | 97 | ||
92 | //Standard IMAP calls | 98 | //Standard IMAP calls |
93 | KAsync::Job<void> login(const QString &username, const QString &password); | 99 | KAsync::Job<void> login(const QString &username, const QString &password); |
94 | KAsync::Job<void> select(const QString &mailbox); | 100 | KAsync::Job<SelectResult> select(const QString &mailbox); |
95 | KAsync::Job<qint64> append(const QString &mailbox, const QByteArray &content, const QList<QByteArray> &flags = QList<QByteArray>(), const QDateTime &internalDate = QDateTime()); | 101 | KAsync::Job<qint64> append(const QString &mailbox, const QByteArray &content, const QList<QByteArray> &flags = QList<QByteArray>(), const QDateTime &internalDate = QDateTime()); |
96 | KAsync::Job<void> store(const KIMAP::ImapSet &set, const QList<QByteArray> &flags); | 102 | KAsync::Job<void> store(const KIMAP::ImapSet &set, const QList<QByteArray> &flags); |
97 | KAsync::Job<void> storeFlags(const KIMAP::ImapSet &set, const QList<QByteArray> &flags); | 103 | KAsync::Job<void> storeFlags(const KIMAP::ImapSet &set, const QList<QByteArray> &flags); |
@@ -103,6 +109,7 @@ public: | |||
103 | KAsync::Job<void> expunge(); | 109 | KAsync::Job<void> expunge(); |
104 | KAsync::Job<void> expunge(const KIMAP::ImapSet &set); | 110 | KAsync::Job<void> expunge(const KIMAP::ImapSet &set); |
105 | KAsync::Job<void> copy(const KIMAP::ImapSet &set, const QString &newMailbox); | 111 | KAsync::Job<void> copy(const KIMAP::ImapSet &set, const QString &newMailbox); |
112 | KAsync::Job<QVector<qint64>> search(const KIMAP::ImapSet &set); | ||
106 | 113 | ||
107 | typedef std::function<void(const QString &, | 114 | typedef std::function<void(const QString &, |
108 | const QMap<qint64,qint64> &, | 115 | const QMap<qint64,qint64> &, |
@@ -115,6 +122,8 @@ public: | |||
115 | KAsync::Job<void> fetch(const KIMAP::ImapSet &set, KIMAP::FetchJob::FetchScope scope, const std::function<void(const QVector<Message> &)> &callback); | 122 | KAsync::Job<void> fetch(const KIMAP::ImapSet &set, KIMAP::FetchJob::FetchScope scope, const std::function<void(const QVector<Message> &)> &callback); |
116 | KAsync::Job<void> list(KIMAP::ListJob::Option option, const std::function<void(const QList<KIMAP::MailBoxDescriptor> &mailboxes,const QList<QList<QByteArray> > &flags)> &callback); | 123 | KAsync::Job<void> list(KIMAP::ListJob::Option option, const std::function<void(const QList<KIMAP::MailBoxDescriptor> &mailboxes,const QList<QList<QByteArray> > &flags)> &callback); |
117 | 124 | ||
125 | QStringList getCapabilities() const; | ||
126 | |||
118 | //Composed calls that do login etc. | 127 | //Composed calls that do login etc. |
119 | KAsync::Job<QList<qint64>> fetchHeaders(const QString &mailbox); | 128 | KAsync::Job<QList<qint64>> fetchHeaders(const QString &mailbox); |
120 | KAsync::Job<void> remove(const QString &mailbox, const KIMAP::ImapSet &set); | 129 | KAsync::Job<void> remove(const QString &mailbox, const KIMAP::ImapSet &set); |
@@ -122,11 +131,14 @@ public: | |||
122 | KAsync::Job<void> move(const QString &mailbox, const KIMAP::ImapSet &set, const QString &newMailbox); | 131 | KAsync::Job<void> move(const QString &mailbox, const KIMAP::ImapSet &set, const QString &newMailbox); |
123 | KAsync::Job<QString> createSubfolder(const QString &parentMailbox, const QString &folderName); | 132 | KAsync::Job<QString> createSubfolder(const QString &parentMailbox, const QString &folderName); |
124 | KAsync::Job<QString> renameSubfolder(const QString &mailbox, const QString &newName); | 133 | KAsync::Job<QString> renameSubfolder(const QString &mailbox, const QString &newName); |
134 | KAsync::Job<QVector<qint64>> fetchUids(const QString &mailbox); | ||
125 | 135 | ||
126 | QString mailboxFromFolder(const Folder &) const; | 136 | QString mailboxFromFolder(const Folder &) const; |
127 | 137 | ||
128 | KAsync::Job<void> fetchFolders(std::function<void(const QVector<Folder> &)> callback); | 138 | KAsync::Job<void> fetchFolders(std::function<void(const QVector<Folder> &)> callback); |
129 | KAsync::Job<void> fetchMessages(const Folder &folder, std::function<void(const QVector<Message> &)> callback, std::function<void(int, int)> progress = std::function<void(int, int)>()); | 139 | KAsync::Job<void> fetchMessages(const Folder &folder, std::function<void(const QVector<Message> &)> callback, std::function<void(int, int)> progress = std::function<void(int, int)>()); |
140 | KAsync::Job<void> fetchMessages(const Folder &folder, qint64 uidNext, std::function<void(const QVector<Message> &)> callback, std::function<void(int, int)> progress = std::function<void(int, int)>()); | ||
141 | KAsync::Job<QVector<qint64>> fetchUids(const Folder &folder); | ||
130 | 142 | ||
131 | private: | 143 | private: |
132 | KAsync::Job<void> ping(); | 144 | KAsync::Job<void> ping(); |