1 /* 2 SPDX-FileCopyrightText: 2010 Klaralvdalens Datakonsult AB, a KDAB Group company, info@kdab.com 3 SPDX-FileCopyrightText: 2010 Leo Franchi <lfranchi@kde.org> 4 5 SPDX-License-Identifier: LGPL-2.0-or-later 6 */ 7 8 #pragma once 9 10 #include "MessageComposer/Recipient" 11 #include "messagecomposer/messagesender.h" 12 #include "messagecomposer_export.h" 13 #include <Akonadi/Collection> 14 #include <Akonadi/Item> 15 #include <KMime/Message> 16 17 #include <Libkleo/Enum> 18 #include <QObject> 19 #include <QUrl> 20 #include <QVector> 21 22 class QTimer; 23 class KJob; 24 class QWidget; 25 26 class ComposerViewBaseTest; 27 28 namespace Sonnet 29 { 30 class DictionaryComboBox; 31 } 32 33 namespace Akonadi 34 { 35 class CollectionComboBox; 36 } 37 38 namespace MailTransport 39 { 40 class TransportComboBox; 41 } 42 43 namespace KIdentityManagement 44 { 45 class IdentityCombo; 46 class Identity; 47 class IdentityManager; 48 } 49 50 namespace Kleo 51 { 52 class KeyResolver; 53 } 54 55 namespace MessageComposer 56 { 57 class RecipientsEditor; 58 class RichTextComposerNg; 59 class InfoPart; 60 class GlobalPart; 61 class Composer; 62 class AttachmentControllerBase; 63 class AttachmentModel; 64 class SignatureController; 65 class SendLaterInfo; 66 /** 67 * @brief The ComposerViewBase class 68 */ 69 class MESSAGECOMPOSER_EXPORT ComposerViewBase : public QObject 70 { 71 Q_OBJECT 72 public: 73 explicit ComposerViewBase(QObject *parent = nullptr, QWidget *widget = nullptr); 74 ~ComposerViewBase() override; 75 76 enum Confirmation { LetUserConfirm, NoConfirmationNeeded }; 77 enum MissingAttachment { 78 NoMissingAttachmentFound, 79 FoundMissingAttachmentAndSending, 80 FoundMissingAttachmentAndAddedAttachment, 81 FoundMissingAttachmentAndCancel 82 }; 83 84 enum FailedType { 85 Sending, 86 AutoSave, 87 }; 88 89 /** 90 * Set the message to be opened in the composer window, and set the internal data structures to 91 * keep track of it. 92 */ 93 void setMessage(const KMime::Message::Ptr &newMsg, bool allowDecryption); 94 95 void updateTemplate(const KMime::Message::Ptr &msg); 96 97 /** 98 * Send the message with the specified method, saving it in the specified folder. 99 */ 100 void send(MessageComposer::MessageSender::SendMethod method, MessageComposer::MessageSender::SaveIn saveIn, bool checkMailDispatcher = true); 101 102 /** 103 * Returns true if there is at least one composer job running. 104 */ 105 Q_REQUIRED_RESULT bool isComposing() const; 106 107 /** 108 * Add the given attachment to the message. 109 */ 110 void addAttachment(const QUrl &url, const QString &comment, bool sync); 111 void addAttachment(const QString &name, const QString &filename, const QString &charset, const QByteArray &data, const QByteArray &mimeType); 112 void addAttachmentPart(KMime::Content *part); 113 114 void fillComposer(MessageComposer::Composer *composer); 115 116 /** 117 * Header fields in recipients editor. 118 */ 119 Q_REQUIRED_RESULT QString to() const; 120 Q_REQUIRED_RESULT QString cc() const; 121 Q_REQUIRED_RESULT QString bcc() const; 122 Q_REQUIRED_RESULT QString from() const; 123 Q_REQUIRED_RESULT QString replyTo() const; 124 Q_REQUIRED_RESULT QString subject() const; 125 126 /** 127 * The following are for setting the various options and widgets in the 128 * composer. 129 */ 130 void setAttachmentModel(MessageComposer::AttachmentModel *model); 131 Q_REQUIRED_RESULT MessageComposer::AttachmentModel *attachmentModel(); 132 133 void setAttachmentController(MessageComposer::AttachmentControllerBase *controller); 134 Q_REQUIRED_RESULT MessageComposer::AttachmentControllerBase *attachmentController(); 135 136 void setRecipientsEditor(MessageComposer::RecipientsEditor *recEditor); 137 Q_REQUIRED_RESULT MessageComposer::RecipientsEditor *recipientsEditor(); 138 139 void setSignatureController(MessageComposer::SignatureController *sigController); 140 Q_REQUIRED_RESULT MessageComposer::SignatureController *signatureController(); 141 142 void setIdentityCombo(KIdentityManagement::IdentityCombo *identCombo); 143 Q_REQUIRED_RESULT KIdentityManagement::IdentityCombo *identityCombo(); 144 145 void setIdentityManager(KIdentityManagement::IdentityManager *identMan); 146 Q_REQUIRED_RESULT KIdentityManagement::IdentityManager *identityManager(); 147 148 void setEditor(MessageComposer::RichTextComposerNg *editor); 149 Q_REQUIRED_RESULT MessageComposer::RichTextComposerNg *editor() const; 150 151 void setTransportCombo(MailTransport::TransportComboBox *transpCombo); 152 Q_REQUIRED_RESULT MailTransport::TransportComboBox *transportComboBox() const; 153 154 void setFccCombo(Akonadi::CollectionComboBox *fcc); 155 Q_REQUIRED_RESULT Akonadi::CollectionComboBox *fccCombo() const; 156 void setFcc(const Akonadi::Collection &id); 157 158 Q_REQUIRED_RESULT Sonnet::DictionaryComboBox *dictionary() const; 159 void setDictionary(Sonnet::DictionaryComboBox *dictionary); 160 161 /** 162 * Widgets for editing differ in client classes, so 163 * values are set before sending. 164 */ 165 void setFrom(const QString &from); 166 void setSubject(const QString &subject); 167 168 /** 169 * The following are various settings the user can modify when composing a message. If they are not set, 170 * the default values will be used. 171 */ 172 void setCryptoOptions(bool sign, bool encrypt, Kleo::CryptoMessageFormat format, bool neverEncryptDrafts = false); 173 void setCharsets(const QVector<QByteArray> &charsets); 174 void setMDNRequested(bool mdnRequested); 175 void setUrgent(bool urgent); 176 177 void setAutoSaveInterval(int interval); 178 void setCustomHeader(const QMap<QByteArray, QString> &customHeader); 179 180 /** 181 * Enables/disables autosaving depending on the value of the autosave 182 * interval. 183 */ 184 void updateAutoSave(); 185 186 /** 187 * Sets the filename to use when autosaving something. This is used when the client recovers 188 * the autosave files: It calls this method, so that the composer uses the same filename again. 189 * That way, the recovered autosave file is properly cleaned up in cleanupAutoSave(): 190 */ 191 void setAutoSaveFileName(const QString &fileName); 192 193 /** 194 * Stop autosaving and delete the autosaved message. 195 */ 196 void cleanupAutoSave(); 197 198 void setParentWidgetForGui(QWidget *); 199 200 /** 201 * Check if the mail has references to attachments, but no attachments are added to it. 202 * If missing attachments are found, a dialog to add new attachments is shown. 203 * @param attachmentKeywords a list with the keywords that indicate an attachment should be present 204 * @return NoMissingAttachmentFound, if there is attachment in email 205 * FoundMissingAttachmentAndCancelSending, if mail might miss attachment but sending 206 * FoundMissingAttachmentAndAddedAttachment, if mail might miss attachment and we added an attachment 207 * FoundMissingAttachmentAndCancel, if mail might miss attachment and cancel sending 208 */ 209 Q_REQUIRED_RESULT ComposerViewBase::MissingAttachment checkForMissingAttachments(const QStringList &attachmentKeywords); 210 211 Q_REQUIRED_RESULT bool hasMissingAttachments(const QStringList &attachmentKeywords); 212 213 void setSendLaterInfo(SendLaterInfo *info); 214 Q_REQUIRED_RESULT SendLaterInfo *sendLaterInfo() const; 215 void saveMailSettings(); 216 217 Q_REQUIRED_RESULT QDate followUpDate() const; 218 void setFollowUpDate(const QDate &followUpDate); 219 220 void clearFollowUp(); 221 222 Q_REQUIRED_RESULT Akonadi::Collection followUpCollection() const; 223 void setFollowUpCollection(const Akonadi::Collection &followUpCollection); 224 225 Q_REQUIRED_RESULT KMime::Message::Ptr msg() const; 226 227 Q_REQUIRED_RESULT bool requestDeleveryConfirmation() const; 228 void setRequestDeleveryConfirmation(bool requestDeleveryConfirmation); 229 230 public Q_SLOTS: 231 void identityChanged(const KIdentityManagement::Identity &ident, const KIdentityManagement::Identity &oldIdent, bool msgCleared = false); 232 233 /** 234 * Save the message. 235 */ 236 void autoSaveMessage(); 237 238 Q_SIGNALS: 239 /** 240 * Message sending completed successfully. 241 */ 242 void sentSuccessfully(Akonadi::Item::Id id); 243 /** 244 * Message sending failed with given error message. 245 */ 246 void failed(const QString &errorMessage, MessageComposer::ComposerViewBase::FailedType type = Sending); 247 248 /** 249 * The composer was modified. This can happen behind the users' back 250 * when, for example, and autosaved message was recovered. 251 */ 252 void modified(bool isModified); 253 254 /** 255 * Enabling or disabling HTML in the editor is affected 256 * by various client options, so when that would otherwise happen, 257 * hand it off to the client to enact it for real. 258 */ 259 void disableHtml(MessageComposer::ComposerViewBase::Confirmation); 260 void enableHtml(); 261 void tooManyRecipient(bool); 262 263 private Q_SLOTS: 264 void slotEmailAddressResolved(KJob *); 265 void slotSendComposeResult(KJob *); 266 void slotQueueResult(KJob *job); 267 void slotCreateItemResult(KJob *); 268 void slotAutoSaveComposeResult(KJob *job); 269 void slotFccCollectionCheckResult(KJob *job); 270 void slotSaveMessage(KJob *job); 271 272 private: 273 Q_REQUIRED_RESULT Akonadi::Collection defaultSpecialTarget() const; 274 /** 275 * Searches the mime tree, where root is the root node, for embedded images, 276 * extracts them froom the body and adds them to the editor. 277 */ 278 void collectImages(KMime::Content *root); 279 Q_REQUIRED_RESULT bool inlineSigningEncryptionSelected() const; 280 /** 281 * Applies the user changes to the message object of the composer 282 * and signs/encrypts the message if activated. 283 * Disables the controls of the composer window. 284 */ 285 void readyForSending(); 286 287 enum RecipientExpansion { 288 UseExpandedRecipients, 289 UseUnExpandedRecipients, 290 }; 291 void fillComposer(MessageComposer::Composer *composer, ComposerViewBase::RecipientExpansion expansion, bool autoresize); 292 Q_REQUIRED_RESULT QVector<MessageComposer::Composer *> generateCryptoMessages(bool &wasCanceled); 293 void fillGlobalPart(MessageComposer::GlobalPart *globalPart); 294 void fillInfoPart(MessageComposer::InfoPart *part, RecipientExpansion expansion); 295 void queueMessage(const KMime::Message::Ptr &message, MessageComposer::Composer *composer); 296 void saveMessage(const KMime::Message::Ptr &message, MessageComposer::MessageSender::SaveIn saveIn); 297 void saveRecentAddresses(const KMime::Message::Ptr &ptr); 298 void updateRecipients(const KIdentityManagement::Identity &ident, const KIdentityManagement::Identity &oldIdent, MessageComposer::Recipient::Type type); 299 300 void markAllAttachmentsForSigning(bool sign); 301 void markAllAttachmentsForEncryption(bool encrypt); 302 bool determineWhetherToSign(bool doSignCompletely, Kleo::KeyResolver *keyResolver, bool signSomething, bool &result, bool &canceled); 303 bool determineWhetherToEncrypt(bool doEncryptCompletely, 304 Kleo::KeyResolver *keyResolver, 305 bool encryptSomething, 306 bool signSomething, 307 bool &result, 308 bool &canceled); 309 310 /** 311 * Writes out autosave data to the disk from the KMime::Message message. 312 * Also appends the msgNum to the filename as a message can have a number of 313 * KMime::Messages 314 */ 315 void writeAutoSaveToDisk(const KMime::Message::Ptr &message); 316 317 /** 318 * Returns the autosave interval in milliseconds (as needed for QTimer). 319 */ 320 int autoSaveInterval() const; 321 322 /** 323 * Initialize autosaving (timer and filename). 324 */ 325 void initAutoSave(); 326 void addFollowupReminder(const QString &messageId); 327 void addSendLaterItem(const Akonadi::Item &item); 328 329 bool addKeysToContext(const QString &gnupgHome, 330 const QVector<QPair<QStringList, std::vector<GpgME::Key>>> &data, 331 const std::map<QByteArray, QString> &autocryptMap); 332 333 KMime::Message::Ptr m_msg; 334 MessageComposer::AttachmentControllerBase *m_attachmentController = nullptr; 335 MessageComposer::AttachmentModel *m_attachmentModel = nullptr; 336 MessageComposer::SignatureController *m_signatureController = nullptr; 337 MessageComposer::RecipientsEditor *m_recipientsEditor = nullptr; 338 KIdentityManagement::IdentityCombo *m_identityCombo = nullptr; 339 KIdentityManagement::IdentityManager *m_identMan = nullptr; 340 MessageComposer::RichTextComposerNg *m_editor = nullptr; 341 MailTransport::TransportComboBox *m_transport = nullptr; 342 Sonnet::DictionaryComboBox *m_dictionary = nullptr; 343 Akonadi::CollectionComboBox *m_fccCombo = nullptr; 344 Akonadi::Collection m_fccCollection; 345 QWidget *m_parentWidget = nullptr; 346 347 // List of active composer jobs. For example, saving as draft, autosaving and printing 348 // all create a composer, which is added to this list as long as it is active. 349 // Used mainly to prevent closing the window if a composer is active 350 QVector<MessageComposer::Composer *> m_composers; 351 352 bool m_sign = false; 353 bool m_encrypt = false; 354 bool m_neverEncrypt = false; 355 bool m_mdnRequested = false; 356 bool m_urgent = false; 357 bool m_requestDeleveryConfirmation = false; 358 Kleo::CryptoMessageFormat m_cryptoMessageFormat; 359 QString mExpandedFrom; 360 QString m_from; 361 QString m_subject; 362 QStringList mExpandedTo, mExpandedCc, mExpandedBcc, mExpandedReplyTo; 363 QVector<QByteArray> m_charsets; 364 QMap<QByteArray, QString> m_customHeader; 365 366 int m_pendingQueueJobs = 0; 367 368 QTimer *m_autoSaveTimer = nullptr; 369 QString m_autoSaveUUID; 370 bool m_autoSaveErrorShown = false; // Stops an error message being shown every time autosave is executed. 371 int m_autoSaveInterval; 372 373 MessageComposer::MessageSender::SendMethod mSendMethod; 374 MessageComposer::MessageSender::SaveIn mSaveIn; 375 376 QDate mFollowUpDate; 377 Akonadi::Collection mFollowUpCollection; 378 379 std::unique_ptr<SendLaterInfo> mSendLaterInfo; 380 381 friend ComposerViewBaseTest; 382 }; 383 } // namespace 384 385