diff options
Diffstat (limited to 'examples/imapresource/imapserverproxy.cpp')
-rw-r--r-- | examples/imapresource/imapserverproxy.cpp | 209 |
1 files changed, 209 insertions, 0 deletions
diff --git a/examples/imapresource/imapserverproxy.cpp b/examples/imapresource/imapserverproxy.cpp new file mode 100644 index 0000000..9630096 --- /dev/null +++ b/examples/imapresource/imapserverproxy.cpp | |||
@@ -0,0 +1,209 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2015 Christian Mollekopf <chrigi_1@fastmail.fm> | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License as published by | ||
6 | * the Free Software Foundation; either version 2 of the License, or | ||
7 | * (at your option) any later version. | ||
8 | * | ||
9 | * This program is distributed in the hope that it will be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, write to the | ||
16 | * Free Software Foundation, Inc., | ||
17 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||
18 | */ | ||
19 | #include "imapserverproxy.h" | ||
20 | |||
21 | #include <QDir> | ||
22 | #include <QFile> | ||
23 | #include <KIMAP/KIMAP/LoginJob> | ||
24 | #include <KIMAP/KIMAP/SelectJob> | ||
25 | #include <KIMAP/KIMAP/AppendJob> | ||
26 | |||
27 | #include <KIMAP/KIMAP/SessionUiProxy> | ||
28 | #include <KCoreAddons/KJob> | ||
29 | |||
30 | #include "log.h" | ||
31 | |||
32 | static KAsync::Job<void> runJob(KJob *job) | ||
33 | { | ||
34 | return KAsync::start<void>([job](KAsync::Future<void> &future) { | ||
35 | QObject::connect(job, &KJob::result, job, [&future](KJob *job) { | ||
36 | if (job->error()) { | ||
37 | Warning() << "Job failed: " << job->errorString(); | ||
38 | future.setError(job->error(), job->errorString()); | ||
39 | } else { | ||
40 | future.setFinished(); | ||
41 | } | ||
42 | }); | ||
43 | job->start(); | ||
44 | }); | ||
45 | } | ||
46 | |||
47 | class SessionUiProxy : public KIMAP::SessionUiProxy { | ||
48 | public: | ||
49 | bool ignoreSslError( const KSslErrorUiData &errorData ) { | ||
50 | return true; | ||
51 | } | ||
52 | }; | ||
53 | |||
54 | ImapServerProxy::ImapServerProxy(const QString &serverUrl, int port) : mSession(new KIMAP::Session(serverUrl, port)) | ||
55 | { | ||
56 | mSession->setUiProxy(SessionUiProxy::Ptr(new SessionUiProxy)); | ||
57 | mSession->setTimeout(10); | ||
58 | } | ||
59 | |||
60 | KAsync::Job<void> ImapServerProxy::login(const QString &username, const QString &password) | ||
61 | { | ||
62 | if (mSession->state() == KIMAP::Session::State::Authenticated || mSession->state() == KIMAP::Session::State::Selected) { | ||
63 | return KAsync::null<void>(); | ||
64 | } | ||
65 | auto loginJob = new KIMAP::LoginJob(mSession); | ||
66 | loginJob->setUserName(username); | ||
67 | loginJob->setPassword(password); | ||
68 | loginJob->setAuthenticationMode(KIMAP::LoginJob::Plain); | ||
69 | loginJob->setEncryptionMode(KIMAP::LoginJob::EncryptionMode::AnySslVersion); | ||
70 | return runJob(loginJob); | ||
71 | } | ||
72 | |||
73 | KAsync::Job<void> ImapServerProxy::select(const QString &mailbox) | ||
74 | { | ||
75 | if (mSession->state() == KIMAP::Session::State::Disconnected) { | ||
76 | return KAsync::error<void>(1, "Not connected"); | ||
77 | } | ||
78 | auto select = new KIMAP::SelectJob(mSession); | ||
79 | select->setMailBox(mailbox); | ||
80 | // select->setCondstoreEnabled(serverSupportsCondstore()); | ||
81 | return runJob(select); | ||
82 | } | ||
83 | |||
84 | KAsync::Job<void> ImapServerProxy::append(const QString &mailbox, const QByteArray &content, const QList<QByteArray> &flags, const QDateTime &internalDate) | ||
85 | { | ||
86 | if (mSession->state() == KIMAP::Session::State::Disconnected) { | ||
87 | return KAsync::error<void>(1, "Not connected"); | ||
88 | } | ||
89 | auto append = new KIMAP::AppendJob(mSession); | ||
90 | append->setMailBox(mailbox); | ||
91 | append->setContent(content); | ||
92 | append->setFlags(flags); | ||
93 | append->setInternalDate(internalDate); | ||
94 | return runJob(append); | ||
95 | } | ||
96 | |||
97 | KAsync::Job<void> ImapServerProxy::fetch(const KIMAP::ImapSet &set, KIMAP::FetchJob::FetchScope scope, FetchCallback callback) | ||
98 | { | ||
99 | if (mSession->state() == KIMAP::Session::State::Disconnected) { | ||
100 | return KAsync::error<void>(1, "Not connected"); | ||
101 | } | ||
102 | auto fetch = new KIMAP::FetchJob(mSession); | ||
103 | fetch->setSequenceSet(set); | ||
104 | fetch->setUidBased(true); | ||
105 | fetch->setScope(scope); | ||
106 | QObject::connect(fetch, static_cast<void(KIMAP::FetchJob::*)(const QString &, | ||
107 | const QMap<qint64,qint64> &, | ||
108 | const QMap<qint64,qint64> &, | ||
109 | const QMap<qint64,KIMAP::MessageAttribute> &, | ||
110 | const QMap<qint64,KIMAP::MessageFlags> &, | ||
111 | const QMap<qint64,KIMAP::MessagePtr> &)>(&KIMAP::FetchJob::headersReceived), | ||
112 | callback); | ||
113 | return runJob(fetch); | ||
114 | } | ||
115 | |||
116 | KAsync::Job<QList<qint64>> ImapServerProxy::fetchHeaders(const QString &mailbox) | ||
117 | { | ||
118 | auto list = QSharedPointer<QList<qint64>>::create(); | ||
119 | KIMAP::FetchJob::FetchScope scope; | ||
120 | scope.parts.clear(); | ||
121 | scope.mode = KIMAP::FetchJob::FetchScope::Headers; | ||
122 | |||
123 | //Fetch headers of all messages | ||
124 | return fetch(KIMAP::ImapSet(1, 0), scope, | ||
125 | [list](const QString &mailbox, | ||
126 | const QMap<qint64,qint64> &uids, | ||
127 | const QMap<qint64,qint64> &sizes, | ||
128 | const QMap<qint64,KIMAP::MessageAttribute> &attrs, | ||
129 | const QMap<qint64,KIMAP::MessageFlags> &flags, | ||
130 | const QMap<qint64,KIMAP::MessagePtr> &messages) { | ||
131 | Trace() << "Received " << uids.size() << " headers from " << mailbox; | ||
132 | Trace() << uids.size() << sizes.size() << attrs.size() << flags.size() << messages.size(); | ||
133 | |||
134 | //TODO based on the data available here, figure out which messages to actually fetch | ||
135 | //(we only fetched headers and structure so far) | ||
136 | //We could i.e. build chunks to fetch based on the size | ||
137 | |||
138 | for (const auto &id : uids.keys()) { | ||
139 | list->append(uids.value(id)); | ||
140 | } | ||
141 | }) | ||
142 | .then<QList<qint64>>([list](){ | ||
143 | return *list; | ||
144 | }); | ||
145 | } | ||
146 | |||
147 | KAsync::Job<void> ImapServerProxy::list(KIMAP::ListJob::Option option, const std::function<void(const QList<KIMAP::MailBoxDescriptor> &mailboxes,const QList<QList<QByteArray> > &flags)> &callback) | ||
148 | { | ||
149 | auto listJob = new KIMAP::ListJob(mSession); | ||
150 | listJob->setOption(option); | ||
151 | // listJob->setQueriedNamespaces(serverNamespaces()); | ||
152 | QObject::connect(listJob, &KIMAP::ListJob::mailBoxesReceived, | ||
153 | listJob, callback); | ||
154 | return runJob(listJob); | ||
155 | } | ||
156 | |||
157 | KAsync::Future<void> ImapServerProxy::fetchFolders(std::function<void(const QStringList &)> callback) | ||
158 | { | ||
159 | Trace() << "Fetching folders"; | ||
160 | auto job = login("doe", "doe").then<void>(list(KIMAP::ListJob::IncludeUnsubscribed, [callback](const QList<KIMAP::MailBoxDescriptor> &mailboxes, const QList<QList<QByteArray> > &flags){ | ||
161 | QStringList list; | ||
162 | for (const auto &mailbox : mailboxes) { | ||
163 | Trace() << "Found mailbox: " << mailbox.name; | ||
164 | list << mailbox.name; | ||
165 | } | ||
166 | callback(list); | ||
167 | }), | ||
168 | [](int errorCode, const QString &errorString) { | ||
169 | Warning() << "Failed to list folders: " << errorCode << errorString; | ||
170 | }); | ||
171 | return job.exec(); | ||
172 | } | ||
173 | |||
174 | KAsync::Future<void> ImapServerProxy::fetchMessages(const QString &folder, std::function<void(const QVector<Message> &)> callback) | ||
175 | { | ||
176 | auto job = login("doe", "doe").then<void>(select(folder)).then<void, KAsync::Job<void>>([this, callback, folder]() -> KAsync::Job<void> { | ||
177 | return fetchHeaders(folder).then<void, KAsync::Job<void>, QList<qint64>>([this, callback](const QList<qint64> &uidsToFetch){ | ||
178 | Trace() << "Uids to fetch: " << uidsToFetch; | ||
179 | if (uidsToFetch.isEmpty()) { | ||
180 | Trace() << "Nothing to fetch"; | ||
181 | return KAsync::null<void>(); | ||
182 | } | ||
183 | KIMAP::FetchJob::FetchScope scope; | ||
184 | scope.parts.clear(); | ||
185 | scope.mode = KIMAP::FetchJob::FetchScope::Full; | ||
186 | |||
187 | KIMAP::ImapSet set; | ||
188 | set.add(uidsToFetch.toVector()); | ||
189 | return fetch(set, scope, | ||
190 | [callback](const QString &mailbox, | ||
191 | const QMap<qint64,qint64> &uids, | ||
192 | const QMap<qint64,qint64> &sizes, | ||
193 | const QMap<qint64,KIMAP::MessageAttribute> &attrs, | ||
194 | const QMap<qint64,KIMAP::MessageFlags> &flags, | ||
195 | const QMap<qint64,KIMAP::MessagePtr> &messages) { | ||
196 | Trace() << "Received " << uids.size() << " messages from " << mailbox; | ||
197 | Trace() << uids.size() << sizes.size() << attrs.size() << flags.size() << messages.size(); | ||
198 | |||
199 | QVector<Message> list; | ||
200 | for (const auto &id : uids.keys()) { | ||
201 | list << Message{uids.value(id), sizes.value(id), attrs.value(id), flags.value(id), messages.value(id)}; | ||
202 | } | ||
203 | callback(list); | ||
204 | }); | ||
205 | }); | ||
206 | |||
207 | }); | ||
208 | return job.exec(); | ||
209 | } | ||