1 /* 2 SPDX-FileCopyrightText: 2010 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com 3 SPDX-FileCopyrightText: 2010 Leo Franchi <lfranchi@kde.org> 4 SPDX-FileCopyrightText: 2017-2021 Laurent Montel <montel@kde.org> 5 6 SPDX-License-Identifier: GPL-2.0-or-later 7 */ 8 9 #pragma once 10 11 #include "messagecomposer_export.h" 12 #include <KMime/KMimeMessage> 13 #include <KMime/MDN> 14 15 #include <Akonadi/Collection> 16 #include <Akonadi/Item> 17 #include <Akonadi/KMime/MessageStatus> 18 #include <QVector> 19 20 namespace KIdentityManagement 21 { 22 class IdentityManager; 23 } 24 25 namespace MessageComposer 26 { 27 /** 28 * Enumeration that defines the available reply "modes" 29 */ 30 enum ReplyStrategy { 31 ReplySmart = 0, //< Attempt to automatically guess the best recipient for the reply 32 ReplyAuthor, //< Reply to the author of the message (possibly NOT the mailing list, if any) 33 ReplyList, //< Reply to the mailing list (and not the author of the message) 34 ReplyAll, //< Reply to author and all the recipients in CC 35 ReplyNone //< Don't set reply addresses: they will be set manually 36 }; 37 38 enum MDNAdvice { MDNIgnore, MDNSendDenied, MDNSend }; 39 /** 40 * Contains various factory methods for creating new messages such as replies, MDNs, forwards, etc. 41 */ 42 class MESSAGECOMPOSER_EXPORT MessageFactoryNG : public QObject 43 { 44 Q_OBJECT 45 public: 46 /// Small helper structure which encapsulates the KMime::Message created when creating a reply, and 47 /// the reply mode 48 struct MessageReply { 49 KMime::Message::Ptr msg = nullptr; ///< The actual reply message 50 bool replyAll = false; ///< If true, the "reply all" template was used, otherwise the normal reply 51 /// template 52 }; 53 54 explicit MessageFactoryNG(const KMime::Message::Ptr &origMsg, 55 Akonadi::Item::Id id, 56 const Akonadi::Collection &col = Akonadi::Collection(), 57 QObject *parent = nullptr); 58 ~MessageFactoryNG() override; 59 60 /** 61 * Create a new message that is a reply to this message, filling all 62 * required header fields with the proper values. The returned message 63 * is not stored in any folder. Marks this message as replied. 64 * 65 */ 66 void createReplyAsync(); 67 68 /** Create a new message that is a forward of this message, filling all 69 required header fields with the proper values. The returned message 70 is not stored in any folder. Marks this message as forwarded. */ 71 void createForwardAsync(); 72 73 /** 74 * Create a forward from the given list of messages, attaching each 75 * message to be forwarded to the new forwarded message. 76 * 77 * If no list is passed, use the original message passed in the MessageFactoryNG 78 * constructor. 79 */ 80 Q_REQUIRED_RESULT QPair<KMime::Message::Ptr, QVector<KMime::Content *>> createAttachedForward(const Akonadi::Item::List &items = Akonadi::Item::List()); 81 82 /** Create a new message that is a redirect to this message, filling all 83 required header fields with the proper values. The returned message 84 is not stored in any folder. Marks this message as replied. 85 Redirects differ from forwards so they are forwarded to some other 86 user, mail is not changed and the reply-to field is set to 87 the email address of the original sender. 88 */ 89 Q_REQUIRED_RESULT KMime::Message::Ptr createRedirect(const QString &toStr, 90 const QString &ccStr = QString(), 91 const QString &bccStr = QString(), 92 int transportId = -1, 93 const QString &fcc = QString(), 94 int identity = -1); 95 96 Q_REQUIRED_RESULT KMime::Message::Ptr createResend(); 97 98 /** Create a new message that is a delivery receipt of this message, 99 filling required header fields with the proper values. The 100 returned message is not stored in any folder. */ 101 Q_REQUIRED_RESULT KMime::Message::Ptr createDeliveryReceipt(); 102 103 /** Create a new message that is a MDN for this message, filling all 104 required fields with proper values. The returned message is not 105 stored in any folder. 106 107 @param a Use AutomaticAction for filtering and ManualAction for 108 user-induced events. 109 @param d See docs for KMime::MDN::DispositionType 110 @param s See docs for KMime::MDN::SendingMode (in KMail, use MDNAdvideDialog to ask the user for this parameter) 111 @param m See docs for KMime::MDN::DispositionModifier 112 113 @return The notification message or 0, if none should be sent, as well as the state of the MDN operation. 114 **/ 115 Q_REQUIRED_RESULT KMime::Message::Ptr createMDN(KMime::MDN::ActionMode a, 116 KMime::MDN::DispositionType d, 117 KMime::MDN::SendingMode s, 118 int mdnQuoteOriginal = 0, 119 const QVector<KMime::MDN::DispositionModifier> &m = QVector<KMime::MDN::DispositionModifier>()); 120 121 /** 122 * Create a new forwarded MIME digest. If the user is trying to forward multiple messages 123 * at once all inline, they can choose to have them be compiled into a single digest 124 * message. 125 * 126 * This will return a header message and individual message parts to be set as 127 * attachments. 128 * 129 * @param msgs List of messages to be composed into a digest 130 */ 131 Q_REQUIRED_RESULT QPair<KMime::Message::Ptr, KMime::Content *> createForwardDigestMIME(const Akonadi::Item::List &items); 132 133 /** 134 * Set the identity manager to be used when creating messages. 135 * Required to be set before create* is called, otherwise the created messages 136 * might have the wrong identity data. 137 */ 138 void setIdentityManager(KIdentityManagement::IdentityManager *ident); 139 140 /** 141 * Set the reply strategy to use. Default is ReplySmart. 142 */ 143 void setReplyStrategy(MessageComposer::ReplyStrategy replyStrategy); 144 145 /** 146 * Set the selection to be used to base the reply on. 147 */ 148 void setSelection(const QString &selection); 149 150 /** 151 * Whether to quote the original message in the reply. 152 * Default is to quote. 153 */ 154 void setQuote(bool quote); 155 156 /** 157 * Set the template to be used when creating the reply. Default is to not 158 * use any template at all. 159 */ 160 void setTemplate(const QString &templ); 161 162 /** 163 * Set extra mailinglist addresses to send the created message to. 164 * Any mailing-list addresses specified in the original message 165 * itself will be added by MessageFactoryNG, so no need to add those manually. 166 */ 167 void setMailingListAddresses(const KMime::Types::Mailbox::List &listAddresses); 168 169 /** 170 * Set the identity that is set for the folder in which the given message is. 171 * It is used as a fallback when finding the identity if it can't be found in 172 * any other way. 173 * @param folderIdentityId an uoid of KIdentityManagement::Identity 174 */ 175 void setFolderIdentity(uint folderIdentityId); 176 177 /** 178 * Whether or not to put the reply to a message in the same folder as the message itself. 179 * If so, specify the folder id in which to put them. Default is -1, which means to not put 180 * replies in the same folder at all. 181 */ 182 void putRepliesInSameFolder(Akonadi::Item::Id parentColId = -1); 183 184 /** 185 * When creating MDNs, the user needs to be asked for confirmation in specific 186 * cases according to RFC 2298. 187 */ 188 Q_REQUIRED_RESULT static bool MDNRequested(const KMime::Message::Ptr &msg); 189 190 /** 191 * If sending an MDN requires confirmation due to multiple addresses. 192 * 193 * RFC 2298: [ Confirmation from the user SHOULD be obtained (or no 194 * MDN sent) ] if there is more than one distinct address in the 195 * Disposition-Notification-To header. 196 */ 197 Q_REQUIRED_RESULT static bool MDNConfirmMultipleRecipients(const KMime::Message::Ptr &msg); 198 199 /** 200 * 201 * If sending an MDN requires confirmation due to discrepancy between MDN 202 * header and Return-Path header. 203 * 204 * RFC 2298: MDNs SHOULD NOT be sent automatically if the address in 205 * the Disposition-Notification-To header differs from the address 206 * in the Return-Path header. [...] Confirmation from the user 207 * SHOULD be obtained (or no MDN sent) if there is no Return-Path 208 * header in the message [...] 209 */ 210 Q_REQUIRED_RESULT static bool MDNReturnPathEmpty(const KMime::Message::Ptr &msg); 211 Q_REQUIRED_RESULT static bool MDNReturnPathNotInRecieptTo(const KMime::Message::Ptr &msg); 212 213 /** 214 * If the MDN headers contain options that KMail can't parse 215 */ 216 Q_REQUIRED_RESULT static bool MDNMDNUnknownOption(const KMime::Message::Ptr &msg); 217 218 Q_REQUIRED_RESULT bool replyAsHtml() const; 219 void setReplyAsHtml(bool replyAsHtml); 220 221 Q_SIGNALS: 222 void createReplyDone(const MessageComposer::MessageFactoryNG::MessageReply &reply); 223 void createForwardDone(const KMime::Message::Ptr &msg); 224 225 private Q_SLOTS: 226 void slotCreateReplyDone(const KMime::Message::Ptr &msg, bool replyAll); 227 void slotCreateForwardDone(const KMime::Message::Ptr &msg); 228 229 private: 230 /** @return the UOID of the identity for this message. 231 Searches the "x-kmail-identity" header and if that fails, 232 searches with KIdentityManagement::IdentityManager::identityForAddress() 233 **/ 234 Q_REQUIRED_RESULT uint identityUoid(const KMime::Message::Ptr &msg); 235 236 Q_REQUIRED_RESULT QString replaceHeadersInString(const KMime::Message::Ptr &msg, const QString &s); 237 238 /* 239 * If force charset option is enabled, try to set the original charset 240 * in the newly created message. If unable to encode, fall back to 241 * preferred charsets, and if all fail, use UTF-8. 242 */ 243 void applyCharset(const KMime::Message::Ptr msg); 244 245 Q_REQUIRED_RESULT QByteArray getRefStr(const KMime::Message::Ptr &msg); 246 KMime::Content *createForwardAttachmentMessage(const KMime::Message::Ptr &fwdMsg); 247 248 KIdentityManagement::IdentityManager *mIdentityManager = nullptr; 249 // Required parts to create messages 250 KMime::Message::Ptr mOrigMsg; 251 uint mFolderId; 252 Akonadi::Item::Id mParentFolderId; 253 254 Akonadi::Collection mCollection; 255 256 // Optional settings the calling class may set 257 MessageComposer::ReplyStrategy mReplyStrategy; 258 QString mSelection; 259 QString mTemplate; 260 bool mQuote = true; 261 bool mReplyAsHtml = false; 262 KMime::Types::Mailbox::List mMailingListAddresses; 263 Akonadi::Item::Id mId; 264 }; 265 } 266 267 Q_DECLARE_METATYPE(MessageComposer::ReplyStrategy) 268 Q_DECLARE_METATYPE(MessageComposer::MessageFactoryNG::MessageReply) 269 270