1/*
2 Copyright (c) 2009 Kevin Ottens <ervin@kde.org>
3
4 This library is free software; you can redistribute it and/or modify it
5 under the terms of the GNU Library General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or (at your
7 option) any later version.
8
9 This library is distributed in the hope that it will be useful, but WITHOUT
10 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
12 License for more details.
13
14 You should have received a copy of the GNU Library General Public License
15 along with this library; see the file COPYING.LIB. If not, write to the
16 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17 02110-1301, USA.
18*/
19
20#ifndef KIMAP_FETCHJOB_H
21#define KIMAP_FETCHJOB_H
22
23#include "kimap_export.h"
24
25#include "imapset.h"
26#include "job.h"
27
28#include "kmime/kmime_content.h"
29#include "kmime/kmime_message.h"
30
31#include <boost/shared_ptr.hpp>
32
33namespace KIMAP {
34
35class Session;
36struct Message;
37class FetchJobPrivate;
38
39typedef boost::shared_ptr<KMime::Content> ContentPtr;
40typedef QMap<QByteArray, ContentPtr> MessageParts;
41
42typedef boost::shared_ptr<KMime::Message> MessagePtr;
43typedef QList<QByteArray> MessageFlags;
44
45typedef QPair<QByteArray, QVariant> MessageAttribute;
46
47/**
48 * Fetch message data from the server
49 *
50 * All data is returned using the signals, so you need to connect to
51 * the relevant signal (or all of them) before starting the job.
52 *
53 * This job will always use BODY.PEEK rather than BODY to fetch message
54 * content, so it will not set the \Seen flag.
55 *
56 * This job can only be run when the session is in the selected state.
57 */
58class KIMAP_EXPORT FetchJob : public Job
59{
60 Q_OBJECT
61 Q_DECLARE_PRIVATE( FetchJob )
62
63 friend class SessionPrivate;
64
65 public:
66 /**
67 * Used to indicate what message data should be fetched.
68 *
69 * This doesn't provide the same fine-grained control over
70 * what is fetched that the IMAP FETCH command normally
71 * does, but the common cases are catered for.
72 */
73 class KIMAP_EXPORT FetchScope
74 {
75 public:
76 FetchScope();
77
78 /**
79 * Used to indicate what part of the message should be fetched.
80 */
81 enum Mode {
82 /**
83 * Fetch RFC-2822 or MIME message headers.
84 *
85 * To fetch MIME headers for a MIME part, populate the @p parts field.
86 *
87 * If the RFC-2822 headers are requested (so @p parts is empty), the
88 * returned information is:
89 * - To, From, Message-id, References In-Reply-To, Subject and Date headers
90 * - The message size (in octets)
91 * - The internal date of the message
92 * - The message flags
93 * - The message UID
94 */
95 Headers,
96 /**
97 * Fetch the message flags (the UID is also fetched)
98 */
99 Flags,
100 /**
101 * Fetch the MIME message body structure (the UID is also fetched)
102 */
103 Structure,
104 /**
105 * Fetch the message content (the UID is also fetched)
106 *
107 * To fetch only certain MIME parts (see Structure), populate the
108 * @p parts field.
109 */
110 Content,
111 /**
112 * Fetch the complete message.
113 */
114 Full,
115 /**
116 * Fetch the message MIME headers and the content of parts specified in the @p parts
117 * field.
118 *
119 * If @p parts is empty, this mode will return the full message, just like
120 * FetchScope::Content
121 *
122 * Use case:
123 * -# Start a FetchJob with the FetchScope::Structure mode to retrieve the structure
124 * of the message.
125 * -# Parse the structure to identify the parts that are interesting (ie: probably
126 * everything but attachments).
127 * -# Start another FetchJob with FetchScope::HeaderAndContent to fetch those parts.
128 * -# At the request of the user, you can repeat the step above to fetch the attachments.
129 *
130 * @since 4.7
131 */
132 HeaderAndContent,
133
134 /**
135 * Fetch message size (in octets), internal date of the message, flags, UID
136 * and all RFC822 headers.
137 *
138 * The @p parts field is ignored when using this scope
139 *
140 * @since 4.12
141 */
142 FullHeaders
143 };
144
145 /**
146 * Specify which message parts to operate on.
147 *
148 * This refers to multipart-MIME message parts or MIME-IMB encapsulated
149 * message parts.
150 *
151 * Note that this is ignored unless @p mode is Headers or Content.
152 *
153 * If @p mode is Headers, this sets the parts to get the MIME headers
154 * for. If this list is empty, the headers for the whole message
155 * (the RFC-2822 headers) are fetched.
156 *
157 * If @p mode is Content, this sets the parts to fetch. Parts are
158 * fetched wholesale. If this list is empty, the whole message body
159 * is fetched (all MIME parts together).
160 */
161 QList<QByteArray> parts;
162 /**
163 * Specify what message data should be fetched.
164 */
165 Mode mode;
166
167 /**
168 * Specify to fetch only items with mod-sequence higher then @p changedSince.
169 *
170 * The server must have CONDSTORE capability (RFC4551).
171 *
172 * Default value is 0 (ignored).
173 *
174 * @since 4.12
175 */
176 quint64 changedSince;
177 };
178
179 explicit FetchJob( Session *session );
180 virtual ~FetchJob();
181
182 /**
183 * Set which messages to fetch data for.
184 *
185 * If sequence numbers are given, isUidBased() should be false. If UIDs
186 * are given, isUidBased() should be true.
187 *
188 * @param set the sequence numbers or UIDs of the messages to fetch data for
189 */
190 void setSequenceSet( const ImapSet &set );
191 /**
192 * The messages that will be fetched.
193 */
194 ImapSet sequenceSet() const;
195
196 /**
197 * Set how the sequence set should be interpreted.
198 *
199 * @param uidBased if @c true the argument to setSequenceSet will be
200 * interpreted as UIDs, if @c false it will be interpreted
201 * as sequence numbers
202 */
203 void setUidBased(bool uidBased);
204 /**
205 * How to interpret the sequence set.
206 *
207 * @return if @c true the result of sequenceSet() should be
208 * interpreted as UIDs, if @c false it should be interpreted
209 * as sequence numbers
210 */
211 bool isUidBased() const;
212
213 /**
214 * Sets what data should be fetched.
215 *
216 * The default scope is FetchScope::Content (all content parts).
217 *
218 * @param scope a FetchScope object describing what data
219 * should be fetched
220 */
221 void setScope( const FetchScope &scope );
222 /**
223 * Specifies what data will be fetched.
224 */
225 FetchScope scope() const;
226
227 // TODO: KF5: Move this to FetchScope
228 /**
229 * Enables retrieving of Gmail-specific extensions
230 *
231 * The FETCH response will contain X-GM-MSGID, X-GM-THRID and X-GM-LABELS
232 *
233 * Do NOT enable this, unless talking to Gmail servers, otherwise the
234 * request may fail.
235 *
236 * @param enabled Whether the Gmail support should be enabled
237 * @since 4.14
238 */
239 void setGmailExtensionsEnabled(bool enabled);
240
241 /**
242 * Returns whether Gmail support is enabled
243 *
244 * @since 4.14
245 * @see setGmailExtensionsEnabled()
246 */
247 bool setGmailExtensionsEnabled() const;
248
249 // XXX: [alexmerry, 2010-07-24]: BIC? Behaviour change
250 /** @deprecated returns an empty map; use the signals instead */
251 KIMAP_DEPRECATED QMap<qint64, MessagePtr> messages() const;
252 /** @deprecated returns an empty map; use the signals instead */
253 KIMAP_DEPRECATED QMap<qint64, MessageParts> parts() const;
254 /** @deprecated returns an empty map; use the signals instead */
255 KIMAP_DEPRECATED QMap<qint64, MessageFlags> flags() const;
256 /** @deprecated returns an empty map; use the signals instead */
257 KIMAP_DEPRECATED QMap<qint64, qint64> sizes() const;
258 /** @deprecated returns an empty map; use the signals instead */
259 KIMAP_DEPRECATED QMap<qint64, qint64> uids() const;
260
261 Q_SIGNALS:
262 /**
263 * Provides header and message results.
264 *
265 * This signal will be emitted if the requested scope mode
266 * was FetchScope::Full, FetchScope::Flags or
267 * FetchScope::Headers with no parts specified
268 *
269 * This signal may be emitted any number of times before
270 * the result() signal is emitted. The result() signal will
271 * only be emitted once all results have been reported via
272 * one of the signals.
273 *
274 * Note that, depending on the scope, some of the parameters
275 * of this signal may be empty maps.
276 *
277 * @param mailBox the name of the mailbox the fetch job was
278 * executed on
279 * @param uids a map from message sequence numbers to message UIDs;
280 * this will always be populated
281 * @param sizes a map from message sequence numbers to message sizes
282 * (sizes are in octets and refer to the transfer encoding of
283 * the message); populated if the scope is FetchScope::Full or
284 * FetchScope::Headers
285 * @param flags a map from message sequence numbers to message flags;
286 * populated if the scope is FetchScope::Flags, FetchScope::Full
287 * of FetchScope::Headers
288 * @param messages a map from message sequence numbers to message contents (including
289 * headers); populated if the scope is FetchScope::Full,
290 * FetchScope::Headers or FetchScope::Structure
291 */
292 void headersReceived( const QString &mailBox,
293 const QMap<qint64, qint64> &uids,
294 const QMap<qint64, qint64> &sizes,
295 const QMap<qint64, KIMAP::MessageFlags> &flags,
296 const QMap<qint64, KIMAP::MessagePtr> &messages );
297
298 /**
299 * An overloaded version of headersReceived(), which includes additional attribute
300 * specified in the FETCH response, but that don't belong to actual content of the
301 * message.
302 *
303 * @param mailBox the name of the mailbox the fetch job was
304 * executed on
305 * @param uids a map from message sequence numbers to message UIDs;
306 * this will always be populated
307 * @param attrs a map from message sequence numbers to a pair of attribute
308 * name and value
309 * @param sizes a map from message sequence numbers to message sizes
310 * (sizes are in octets and refer to the transfer encoding of
311 * the message); populated if the scope is FetchScope::Full or
312 * FetchScope::Headers
313 * @param flags a map from message sequence numbers to message flags;
314 * populated if the scope is FetchScope::Flags, FetchScope::Full
315 * of FetchScope::Headers
316 * @param messages a map from message sequence numbers to message contents (including
317 * headers); populated if the scope is FetchScope::Full,
318 * FetchScope::Headers or FetchScope::Structure
319 *
320 * @overload
321 * @since 4.14
322 */
323 void headersReceived( const QString &mailBox,
324 const QMap<qint64, qint64> &uids,
325 const QMap<qint64, qint64> &sizes,
326 const QMap<qint64, KIMAP::MessageAttribute > &attrs,
327 const QMap<qint64, KIMAP::MessageFlags> &flags,
328 const QMap<qint64, KIMAP::MessagePtr> &messages );
329
330 /**
331 * Provides header and message results.
332 *
333 * This signal will be emitted if the requested scope mode
334 * was FetchScope::Content or FetchScope::Headers with no
335 * parts specified or FetchScope::Structure.
336 *
337 * This signal may be emitted any number of times before
338 * the result() signal is emitted. The result() signal will
339 * only be emitted once all results have been reported via
340 * one of the signals.
341 *
342 *
343 * @param mailBox the name of the mailbox the fetch job was
344 * executed on
345 * @param uids a map from message sequence numbers to message UIDs
346 * @param messages a map from message sequence numbers to message contents
347 */
348 void messagesReceived( const QString &mailBox,
349 const QMap<qint64, qint64> &uids,
350 const QMap<qint64, KIMAP::MessagePtr> &messages );
351
352
353 /**
354 * An overloaded version of messagesReceived(), which includes additional attribute
355 * specified in the FETCH response, but that don't belong to actual content of the
356 * message.
357 *
358 * @param mailBox the name of the mailbox the fetch job was
359 * executed on
360 * @param uids a map from message sequence numbers to message UIDs
361 * @param attrs a map from message sequence numbers to pair of attribute
362 * name and it's value
363 * @param messages a map from message sequence numbers to message contents
364 *
365 * @overload
366 * @since 4.14
367 */
368 void messagesReceived( const QString &mailBox,
369 const QMap<qint64, qint64> &uids,
370 const QMap<qint64, KIMAP::MessageAttribute > &attrs,
371 const QMap<qint64, KIMAP::MessagePtr> &messages );
372 /**
373 * Provides header and message results.
374 *
375 * This signal will be emitted if the requested scope mode
376 * was FetchScope::Content or FetchScope::Headers with
377 * specified parts.
378 *
379 * This signal may be emitted any number of times before
380 * the result() signal is emitted. The result() signal will
381 * only be emitted once all results have been reported via
382 * one of the signals.
383 *
384 * @param mailBox the name of the mailbox the fetch job was
385 * executed on
386 * @param uids a map from message sequence numbers to message UIDs
387 * @param parts a map from message sequence numbers to message part collections
388 */
389 void partsReceived( const QString &mailBox,
390 const QMap<qint64, qint64> &uids,
391 const QMap<qint64, KIMAP::MessageParts> &parts );
392
393 /**
394 * An overloaded version of partsReceived(), which includes additional attribute
395 * specified in the FETCH response, but that don't belong to actual content of the
396 * message.
397 *
398 * @param mailBox the name of the mailbox the fetch job was
399 * executed on
400 * @param uids a map from message sequence numbers to message UIDs
401 * @param attrs a map from message sequence numbers to pair of attribute
402 * @param parts a map from message sequence numbers to message part collections
403 *
404 * @overload
405 * @since 4.14
406 */
407 void partsReceived( const QString &mailBox,
408 const QMap<qint64, qint64> &uids,
409 const QMap<qint64, KIMAP::MessageAttribute > &attrs,
410 const QMap<qint64, KIMAP::MessageParts> &parts );
411
412 protected:
413 virtual void doStart();
414 virtual void handleResponse(const Message &response);
415
416 private:
417 Q_PRIVATE_SLOT( d_func(), void emitPendings() )
418};
419
420}
421
422#endif
423