summaryrefslogtreecommitdiffstats
path: root/examples/imapresource
diff options
context:
space:
mode:
Diffstat (limited to 'examples/imapresource')
-rw-r--r--examples/imapresource/imapresource.cpp67
-rw-r--r--examples/imapresource/imapserverproxy.cpp50
-rw-r--r--examples/imapresource/imapserverproxy.h14
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
191KAsync::Job<void> ImapServerProxy::select(const QString &mailbox) 192KAsync::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
199KAsync::Job<qint64> ImapServerProxy::append(const QString &mailbox, const QByteArray &content, const QList<QByteArray> &flags, const QDateTime &internalDate) 202KAsync::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
309KAsync::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
306KAsync::Job<void> ImapServerProxy::fetch(const KIMAP::ImapSet &set, KIMAP::FetchJob::FetchScope scope, const std::function<void(const QVector<Message> &)> &callback) 319KAsync::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
336QStringList ImapServerProxy::getCapabilities() const
337{
338 return mCapabilities;
339}
340
323KAsync::Job<QList<qint64>> ImapServerProxy::fetchHeaders(const QString &mailbox) 341KAsync::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
372KAsync::Job<QVector<qint64>> ImapServerProxy::fetchUids(const QString &mailbox)
373{
374 return select(mailbox).then<QVector<qint64>>(search(KIMAP::ImapSet(1, 0)));
375}
376
354KAsync::Job<void> ImapServerProxy::list(KIMAP::ListJob::Option option, const std::function<void(const QList<KIMAP::MailBoxDescriptor> &mailboxes,const QList<QList<QByteArray> > &flags)> &callback) 377KAsync::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
437KAsync::Job<void> ImapServerProxy::fetchMessages(const Folder &folder, std::function<void(const QVector<Message> &)> callback, std::function<void(int, int)> progress) 460KAsync::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
506KAsync::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
511KAsync::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
78struct SelectResult {
79 qint64 uidValidity;
80 qint64 uidNext;
81 quint64 highestModSequence;
82};
83
78class ImapServerProxy { 84class 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
131private: 143private:
132 KAsync::Job<void> ping(); 144 KAsync::Job<void> ping();