File indexing completed on 2024-05-12 05:17:13
0001 /* 0002 SPDX-FileCopyrightText: 2009 Kevin Ottens <ervin@kde.org> 0003 0004 SPDX-License-Identifier: LGPL-2.0-or-later 0005 */ 0006 0007 #pragma once 0008 0009 #include "kimap_export.h" 0010 0011 #include "imapset.h" 0012 #include "job.h" 0013 0014 #include <KMime/Content> 0015 #include <KMime/KMimeMessage> 0016 0017 #include <tuple> 0018 0019 namespace KIMAP 0020 { 0021 class Session; 0022 struct Response; 0023 class FetchJobPrivate; 0024 0025 using ContentPtr = QSharedPointer<KMime::Content>; 0026 using MessageParts = QMap<QByteArray, ContentPtr>; 0027 0028 using MessagePtr = QSharedPointer<KMime::Message>; 0029 using MessageFlags = QList<QByteArray>; 0030 0031 using MessageAttribute = QPair<QByteArray, QVariant>; 0032 0033 struct Message { 0034 inline bool operator==(const Message &other) const 0035 { 0036 return std::tie(uid, size, flags, attributes, parts, message) 0037 == std::tie(other.uid, other.size, other.flags, other.attributes, other.parts, other.message); 0038 } 0039 0040 qint64 uid = -1; 0041 qint64 size = 0; 0042 MessageFlags flags; 0043 QMap<QByteArray, QVariant> attributes; 0044 MessageParts parts; 0045 MessagePtr message; 0046 }; 0047 0048 /** 0049 * Fetch message data from the server 0050 * 0051 * All data is returned using the signals, so you need to connect to 0052 * the relevant signal (or all of them) before starting the job. 0053 * 0054 * This job will always use BODY.PEEK rather than BODY to fetch message 0055 * content, so it will not set the \Seen flag. 0056 * 0057 * This job can only be run when the session is in the selected state. 0058 */ 0059 class KIMAP_EXPORT FetchJob : public Job 0060 { 0061 Q_OBJECT 0062 Q_DECLARE_PRIVATE(FetchJob) 0063 0064 friend class SessionPrivate; 0065 0066 public: 0067 /** 0068 * Used to indicate what message data should be fetched. 0069 * 0070 * This doesn't provide the same fine-grained control over 0071 * what is fetched that the IMAP FETCH command normally 0072 * does, but the common cases are catered for. 0073 */ 0074 class KIMAP_EXPORT FetchScope 0075 { 0076 public: 0077 FetchScope(); 0078 0079 /** 0080 * Used to indicate what part of the message should be fetched. 0081 */ 0082 enum Mode { 0083 /** 0084 * Fetch RFC-2822 or MIME message headers. 0085 * 0086 * To fetch MIME headers for a MIME part, populate the @p parts field. 0087 * 0088 * If the RFC-2822 headers are requested (so @p parts is empty), the 0089 * returned information is: 0090 * - To, From, Message-id, References In-Reply-To, Subject and Date headers 0091 * - The message size (in octets) 0092 * - The internal date of the message 0093 * - The message flags 0094 * - The message UID 0095 */ 0096 Headers, 0097 /** 0098 * Fetch the message flags (the UID is also fetched) 0099 */ 0100 Flags, 0101 /** 0102 * Fetch the MIME message body structure (the UID is also fetched) 0103 */ 0104 Structure, 0105 /** 0106 * Fetch the message content (the UID is also fetched) 0107 * 0108 * To fetch only certain MIME parts (see Structure), populate the 0109 * @p parts field. 0110 */ 0111 Content, 0112 /** 0113 * Fetch the complete message. 0114 */ 0115 Full, 0116 /** 0117 * Fetch the message MIME headers and the content of parts specified in the @p parts 0118 * field. 0119 * 0120 * If @p parts is empty, this mode will return the full message, just like 0121 * FetchScope::Content 0122 * 0123 * Use case: 0124 * -# Start a FetchJob with the FetchScope::Structure mode to retrieve the structure 0125 * of the message. 0126 * -# Parse the structure to identify the parts that are interesting (ie: probably 0127 * everything but attachments). 0128 * -# Start another FetchJob with FetchScope::HeaderAndContent to fetch those parts. 0129 * -# At the request of the user, you can repeat the step above to fetch the attachments. 0130 * 0131 * @since 4.7 0132 */ 0133 HeaderAndContent, 0134 0135 /** 0136 * Fetch message size (in octets), internal date of the message, flags, UID 0137 * and all RFC822 headers. 0138 * 0139 * The @p parts field is ignored when using this scope 0140 * 0141 * @since 4.12 0142 */ 0143 FullHeaders 0144 }; 0145 0146 /** 0147 * Specify which message parts to operate on. 0148 * 0149 * This refers to multipart-MIME message parts or MIME-IMB encapsulated 0150 * message parts. 0151 * 0152 * Note that this is ignored unless @p mode is Headers or Content. 0153 * 0154 * If @p mode is Headers, this sets the parts to get the MIME headers 0155 * for. If this list is empty, the headers for the whole message 0156 * (the RFC-2822 headers) are fetched. 0157 * 0158 * If @p mode is Content, this sets the parts to fetch. Parts are 0159 * fetched wholesale. If this list is empty, the whole message body 0160 * is fetched (all MIME parts together). 0161 */ 0162 QList<QByteArray> parts; 0163 /** 0164 * Specify what message data should be fetched. 0165 */ 0166 Mode mode = Content; 0167 0168 /** 0169 * Specify to fetch only items with mod-sequence higher then @p changedSince. 0170 * 0171 * The server must have CONDSTORE capability (RFC4551). 0172 * 0173 * Default value is 0 (ignored). 0174 * 0175 * @since 4.12 0176 */ 0177 quint64 changedSince = 0; 0178 0179 /** 0180 * Specify whether QRESYNC is supported and should be used. 0181 * 0182 * When enabled, the @p changedSince parameter must be specified as 0183 * well. The server will then also return list of messages that have 0184 * been deleted from the mailbox since the specified modification sequence. 0185 * 0186 * The server must have QRESYNC capability (RFC5162) and it must have 0187 * explicitly been enabled via ENABLE command (see @EnableJob). 0188 * 0189 * QRESYNC can only be used in UID FETCH (@see setUidBased()) 0190 * 0191 * @since 5.16 0192 */ 0193 bool qresync = false; 0194 }; 0195 0196 explicit FetchJob(Session *session); 0197 ~FetchJob() override = default; 0198 0199 /** 0200 * Set which messages to fetch data for. 0201 * 0202 * If sequence numbers are given, isUidBased() should be false. If UIDs 0203 * are given, isUidBased() should be true. 0204 * 0205 * @param set the sequence numbers or UIDs of the messages to fetch data for 0206 */ 0207 void setSequenceSet(const ImapSet &set); 0208 /** 0209 * The messages that will be fetched. 0210 */ 0211 ImapSet sequenceSet() const; 0212 0213 /** 0214 * Set how the sequence set should be interpreted. 0215 * 0216 * @param uidBased if @c true the argument to setSequenceSet will be 0217 * interpreted as UIDs, if @c false it will be interpreted 0218 * as sequence numbers 0219 */ 0220 void setUidBased(bool uidBased); 0221 /** 0222 * How to interpret the sequence set. 0223 * 0224 * @return if @c true the result of sequenceSet() should be 0225 * interpreted as UIDs, if @c false it should be interpreted 0226 * as sequence numbers 0227 */ 0228 [[nodiscard]] bool isUidBased() const; 0229 0230 /** 0231 * Sets what data should be fetched. 0232 * 0233 * The default scope is FetchScope::Content (all content parts). 0234 * 0235 * @param scope a FetchScope object describing what data 0236 * should be fetched 0237 */ 0238 void setScope(const FetchScope &scope); 0239 /** 0240 * Specifies what data will be fetched. 0241 */ 0242 [[nodiscard]] FetchScope scope() const; 0243 0244 // TODO: KF6: Move this to FetchScope 0245 /** 0246 * Enables retrieving of Gmail-specific extensions 0247 * 0248 * The FETCH response will contain X-GM-MSGID, X-GM-THRID and X-GM-LABELS 0249 * 0250 * Do NOT enable this, unless talking to Gmail servers, otherwise the 0251 * request may fail. 0252 * 0253 * @param enabled Whether the Gmail support should be enabled 0254 * @since 4.14 0255 */ 0256 void setGmailExtensionsEnabled(bool enabled); 0257 0258 /** 0259 * Returns whether Gmail support is enabled 0260 * 0261 * @since 4.14 0262 * @see setGmailExtensionsEnabled() 0263 */ 0264 bool setGmailExtensionsEnabled() const; 0265 0266 /** 0267 * Returns the name of the mailbox the fetch job is executed on. 0268 * 0269 * Can only be accessed after the job is actually started, before that 0270 * returns an empty string. 0271 * 0272 * @since 5.6 0273 */ 0274 [[nodiscard]] QString mailBox() const; 0275 0276 Q_SIGNALS: 0277 /** 0278 * Provides header and message results. 0279 * 0280 * This signal will be emitted if the requested scope mode 0281 * was FetchScope::Full, FetchScope::Flags or 0282 * FetchScope::Headers with no parts specified 0283 * 0284 * This signal may be emitted any number of times before 0285 * the result() signal is emitted. The result() signal will 0286 * only be emitted once all results have been reported via 0287 * one of the signals. 0288 * 0289 * Note that, depending on the scope, some of the parameters 0290 * of this signal may be empty maps. 0291 * 0292 * @param mailBox the name of the mailbox the fetch job was 0293 * executed on 0294 * @param uids a map from message sequence numbers to message UIDs; 0295 * this will always be populated 0296 * @param sizes a map from message sequence numbers to message sizes 0297 * (sizes are in octets and refer to the transfer encoding of 0298 * the message); populated if the scope is FetchScope::Full or 0299 * FetchScope::Headers 0300 * @param flags a map from message sequence numbers to message flags; 0301 * populated if the scope is FetchScope::Flags, FetchScope::Full 0302 * of FetchScope::Headers 0303 * @param messages a map from message sequence numbers to message contents (including 0304 * headers); populated if the scope is FetchScope::Full, 0305 * FetchScope::Headers or FetchScope::Structure 0306 * 0307 * @deprecated Use messagesAvailable() instead. 0308 */ 0309 KIMAP_DEPRECATED 0310 void headersReceived(const QString &mailBox, 0311 const QMap<qint64, qint64> &uids, 0312 const QMap<qint64, qint64> &sizes, 0313 const QMap<qint64, KIMAP::MessageFlags> &flags, 0314 const QMap<qint64, KIMAP::MessagePtr> &messages); 0315 0316 /** 0317 * An overloaded version of headersReceived(), which includes additional attribute 0318 * specified in the FETCH response, but that don't belong to actual content of the 0319 * message. 0320 * 0321 * @param mailBox the name of the mailbox the fetch job was 0322 * executed on 0323 * @param uids a map from message sequence numbers to message UIDs; 0324 * this will always be populated 0325 * @param attrs a map from message sequence numbers to a pair of attribute 0326 * name and value 0327 * @param sizes a map from message sequence numbers to message sizes 0328 * (sizes are in octets and refer to the transfer encoding of 0329 * the message); populated if the scope is FetchScope::Full or 0330 * FetchScope::Headers 0331 * @param flags a map from message sequence numbers to message flags; 0332 * populated if the scope is FetchScope::Flags, FetchScope::Full 0333 * of FetchScope::Headers 0334 * @param messages a map from message sequence numbers to message contents (including 0335 * headers); populated if the scope is FetchScope::Full, 0336 * FetchScope::Headers or FetchScope::Structure 0337 * 0338 * @overload 0339 * @since 4.14 0340 * @deprecated Use messagesAvailable() instead. 0341 */ 0342 KIMAP_DEPRECATED 0343 void headersReceived(const QString &mailBox, 0344 const QMap<qint64, qint64> &uids, 0345 const QMap<qint64, qint64> &sizes, 0346 const QMap<qint64, KIMAP::MessageAttribute> &attrs, 0347 const QMap<qint64, KIMAP::MessageFlags> &flags, 0348 const QMap<qint64, KIMAP::MessagePtr> &messages); 0349 0350 /** 0351 * Provides header and message results. 0352 * 0353 * This signal will be emitted if the requested scope mode 0354 * was FetchScope::Content or FetchScope::Headers with no 0355 * parts specified or FetchScope::Structure. 0356 * 0357 * This signal may be emitted any number of times before 0358 * the result() signal is emitted. The result() signal will 0359 * only be emitted once all results have been reported via 0360 * one of the signals. 0361 * 0362 * 0363 * @param mailBox the name of the mailbox the fetch job was 0364 * executed on 0365 * @param uids a map from message sequence numbers to message UIDs 0366 * @param messages a map from message sequence numbers to message contents 0367 * 0368 * @deprecated Use messagesAvailable() instead. 0369 */ 0370 KIMAP_DEPRECATED 0371 void messagesReceived(const QString &mailBox, const QMap<qint64, qint64> &uids, const QMap<qint64, KIMAP::MessagePtr> &messages); 0372 0373 /** 0374 * An overloaded version of messagesReceived(), which includes additional attribute 0375 * specified in the FETCH response, but that don't belong to actual content of the 0376 * message. 0377 * 0378 * @param mailBox the name of the mailbox the fetch job was 0379 * executed on 0380 * @param uids a map from message sequence numbers to message UIDs 0381 * @param attrs a map from message sequence numbers to pair of attribute 0382 * name and it's value 0383 * @param messages a map from message sequence numbers to message contents 0384 * 0385 * @overload 0386 * @since 4.14 0387 * 0388 * @deprecated Use messagesAvailable() instead. 0389 */ 0390 KIMAP_DEPRECATED 0391 void messagesReceived(const QString &mailBox, 0392 const QMap<qint64, qint64> &uids, 0393 const QMap<qint64, KIMAP::MessageAttribute> &attrs, 0394 const QMap<qint64, KIMAP::MessagePtr> &messages); 0395 /** 0396 * Provides header and message results. 0397 * 0398 * This signal will be emitted if the requested scope mode 0399 * was FetchScope::Content or FetchScope::Headers with 0400 * specified parts. 0401 * 0402 * This signal may be emitted any number of times before 0403 * the result() signal is emitted. The result() signal will 0404 * only be emitted once all results have been reported via 0405 * one of the signals. 0406 * 0407 * @param mailBox the name of the mailbox the fetch job was 0408 * executed on 0409 * @param uids a map from message sequence numbers to message UIDs 0410 * @param parts a map from message sequence numbers to message part collections 0411 * 0412 * @deprecated Use messagesAvailable() instead. 0413 */ 0414 KIMAP_DEPRECATED 0415 void partsReceived(const QString &mailBox, const QMap<qint64, qint64> &uids, const QMap<qint64, KIMAP::MessageParts> &parts); 0416 0417 /** 0418 * An overloaded version of partsReceived(), which includes additional attribute 0419 * specified in the FETCH response, but that don't belong to actual content of the 0420 * message. 0421 * 0422 * @param mailBox the name of the mailbox the fetch job was 0423 * executed on 0424 * @param uids a map from message sequence numbers to message UIDs 0425 * @param attrs a map from message sequence numbers to pair of attribute 0426 * @param parts a map from message sequence numbers to message part collections 0427 * 0428 * @overload 0429 * @since 4.14 0430 * 0431 * @deprecated Use messagesAvailable() instead. 0432 */ 0433 KIMAP_DEPRECATED 0434 void partsReceived(const QString &mailBox, 0435 const QMap<qint64, qint64> &uids, 0436 const QMap<qint64, KIMAP::MessageAttribute> &attrs, 0437 const QMap<qint64, KIMAP::MessageParts> &parts); 0438 0439 /** 0440 * Provides received messages. 0441 * 0442 * This signal is emitted when some data are received. The signal can be 0443 * emitted multiple times as the messages are being received. 0444 * 0445 * @param messages A map from message sequence number to message. Not all 0446 * fields may be populated, depending on the fetch scope. 0447 * 0448 * @since 5.6 0449 */ 0450 void messagesAvailable(const QMap<qint64, KIMAP::Message> &messages); 0451 0452 /** 0453 * Provides vanished messages. 0454 * 0455 * This signal is emitted when QRESYNC capability (RFC5162) is available and has 0456 * bee enabled on the server, and @p FetchScope::qresync has been set to @p true. 0457 * It contains a list of messages that have vanished from the mailbox since the 0458 * last modification sequence specified in @p FetchScope::changedSince. 0459 * 0460 * @param uids UIDs of messages that have been removed from the mailbox since 0461 * the specified modification sequence. 0462 * 0463 * @since 5.16 0464 */ 0465 void messagesVanished(const KIMAP::ImapSet &uids); 0466 0467 protected: 0468 void doStart() override; 0469 void handleResponse(const Response &response) override; 0470 0471 private: 0472 Q_PRIVATE_SLOT(d_func(), void emitPendings()) 0473 }; 0474 0475 }