File indexing completed on 2024-06-23 05:18:27

0001 /*
0002   SPDX-FileCopyrightText: 2010 Klaralvdalens Datakonsult AB, a KDAB Group company, info@kdab.com
0003   SPDX-FileCopyrightText: 2010 Leo Franchi <lfranchi@kde.org>
0004 
0005   SPDX-License-Identifier: LGPL-2.0-or-later
0006 */
0007 
0008 #pragma once
0009 
0010 #include "MessageComposer/Recipient"
0011 #include "messagecomposer/messagesender.h"
0012 #include "messagecomposer_export.h"
0013 #include <Akonadi/Collection>
0014 #include <Akonadi/Item>
0015 #include <KMime/Message>
0016 
0017 #include <Libkleo/Enum>
0018 #include <QList>
0019 #include <QObject>
0020 #include <QUrl>
0021 
0022 class QTimer;
0023 class KJob;
0024 class QWidget;
0025 
0026 class ComposerViewBaseTest;
0027 
0028 namespace Sonnet
0029 {
0030 class DictionaryComboBox;
0031 }
0032 
0033 namespace Akonadi
0034 {
0035 class CollectionComboBox;
0036 }
0037 
0038 namespace MailTransport
0039 {
0040 class TransportComboBox;
0041 }
0042 namespace KIdentityManagementWidgets
0043 {
0044 class IdentityCombo;
0045 }
0046 namespace KIdentityManagementCore
0047 {
0048 class Identity;
0049 class IdentityManager;
0050 }
0051 
0052 namespace Kleo
0053 {
0054 class ExpiryChecker;
0055 class KeyResolver;
0056 }
0057 
0058 namespace MessageComposer
0059 {
0060 class RecipientsEditor;
0061 class RichTextComposerNg;
0062 class InfoPart;
0063 class GlobalPart;
0064 class Composer;
0065 class AttachmentControllerBase;
0066 class AttachmentModel;
0067 class SignatureController;
0068 class SendLaterInfo;
0069 /**
0070  * @brief The ComposerViewBase class
0071  */
0072 class MESSAGECOMPOSER_EXPORT ComposerViewBase : public QObject
0073 {
0074     Q_OBJECT
0075 public:
0076     explicit ComposerViewBase(QObject *parent = nullptr, QWidget *widget = nullptr);
0077     ~ComposerViewBase() override;
0078 
0079     enum Confirmation {
0080         LetUserConfirm,
0081         NoConfirmationNeeded,
0082     };
0083     enum MissingAttachment {
0084         NoMissingAttachmentFound,
0085         FoundMissingAttachmentAndSending,
0086         FoundMissingAttachmentAndAddedAttachment,
0087         FoundMissingAttachmentAndCancel,
0088     };
0089 
0090     enum FailedType {
0091         Sending,
0092         AutoSave,
0093     };
0094 
0095     /**
0096      * Set the message to be opened in the composer window, and set the internal data structures to
0097      *  keep track of it.
0098      */
0099     void setMessage(const KMime::Message::Ptr &newMsg, bool allowDecryption);
0100 
0101     void updateTemplate(const KMime::Message::Ptr &msg);
0102 
0103     /**
0104      * Send the message with the specified method, saving it in the specified folder.
0105      */
0106     void send(MessageComposer::MessageSender::SendMethod method, MessageComposer::MessageSender::SaveIn saveIn, bool checkMailDispatcher = true);
0107 
0108     /**
0109      * Returns true if there is at least one composer job running.
0110      */
0111     [[nodiscard]] bool isComposing() const;
0112 
0113     /**
0114      * Add the given attachment to the message.
0115      */
0116     void addAttachment(const QUrl &url, const QString &comment, bool sync);
0117     void addAttachment(const QString &name, const QString &filename, const QString &charset, const QByteArray &data, const QByteArray &mimeType);
0118     void addAttachmentPart(KMime::Content *part);
0119 
0120     void fillComposer(MessageComposer::Composer *composer);
0121 
0122     /**
0123      * Header fields in recipients editor.
0124      */
0125     [[nodiscard]] QString to() const;
0126     [[nodiscard]] QString cc() const;
0127     [[nodiscard]] QString bcc() const;
0128     [[nodiscard]] QString from() const;
0129     [[nodiscard]] QString replyTo() const;
0130     [[nodiscard]] QString subject() const;
0131 
0132     [[nodiscard]] const KIdentityManagementCore::Identity &currentIdentity() const;
0133     [[nodiscard]] bool autocryptEnabled() const;
0134 
0135     /**
0136      * The following are for setting the various options and widgets in the
0137      *  composer.
0138      */
0139     void setAttachmentModel(MessageComposer::AttachmentModel *model);
0140     [[nodiscard]] MessageComposer::AttachmentModel *attachmentModel();
0141 
0142     void setAttachmentController(MessageComposer::AttachmentControllerBase *controller);
0143     [[nodiscard]] MessageComposer::AttachmentControllerBase *attachmentController();
0144 
0145     void setRecipientsEditor(MessageComposer::RecipientsEditor *recEditor);
0146     [[nodiscard]] MessageComposer::RecipientsEditor *recipientsEditor();
0147 
0148     void setSignatureController(MessageComposer::SignatureController *sigController);
0149     [[nodiscard]] MessageComposer::SignatureController *signatureController();
0150 
0151     void setIdentityCombo(KIdentityManagementWidgets::IdentityCombo *identCombo);
0152     [[nodiscard]] KIdentityManagementWidgets::IdentityCombo *identityCombo();
0153 
0154     void setIdentityManager(KIdentityManagementCore::IdentityManager *identMan);
0155     [[nodiscard]] KIdentityManagementCore::IdentityManager *identityManager();
0156 
0157     void setEditor(MessageComposer::RichTextComposerNg *editor);
0158     [[nodiscard]] MessageComposer::RichTextComposerNg *editor() const;
0159 
0160     void setTransportCombo(MailTransport::TransportComboBox *transpCombo);
0161     [[nodiscard]] MailTransport::TransportComboBox *transportComboBox() const;
0162 
0163     void setFccCombo(Akonadi::CollectionComboBox *fcc);
0164     [[nodiscard]] Akonadi::CollectionComboBox *fccCombo() const;
0165     void setFcc(const Akonadi::Collection &id);
0166 
0167     [[nodiscard]] Sonnet::DictionaryComboBox *dictionary() const;
0168     void setDictionary(Sonnet::DictionaryComboBox *dictionary);
0169 
0170     /**
0171      * Widgets for editing differ in client classes, so
0172      *  values are set before sending.
0173      */
0174     void setFrom(const QString &from);
0175     void setSubject(const QString &subject);
0176 
0177     /**
0178      * The following are various settings the user can modify when composing a message. If they are not set,
0179      *  the default values will be used.
0180      */
0181     void setCryptoOptions(bool sign, bool encrypt, Kleo::CryptoMessageFormat format, bool neverEncryptDrafts = false);
0182     void setCharsets(const QList<QByteArray> &charsets);
0183     void setMDNRequested(bool mdnRequested);
0184     void setUrgent(bool urgent);
0185 
0186     void setAutoSaveInterval(int interval);
0187     void setCustomHeader(const QMap<QByteArray, QString> &customHeader);
0188 
0189     /**
0190      * Enables/disables autosaving depending on the value of the autosave
0191      * interval.
0192      */
0193     void updateAutoSave();
0194 
0195     /**
0196      * Sets the filename to use when autosaving something. This is used when the client recovers
0197      * the autosave files: It calls this method, so that the composer uses the same filename again.
0198      * That way, the recovered autosave file is properly cleaned up in cleanupAutoSave():
0199      */
0200     void setAutoSaveFileName(const QString &fileName);
0201 
0202     /**
0203      * Stop autosaving and delete the autosaved message.
0204      */
0205     void cleanupAutoSave();
0206 
0207     void setParentWidgetForGui(QWidget *);
0208 
0209     /**
0210      * Check if the mail has references to attachments, but no attachments are added to it.
0211      * If missing attachments are found, a dialog to add new attachments is shown.
0212      * @param attachmentKeywords a list with the keywords that indicate an attachment should be present
0213      * @return NoMissingAttachmentFound, if there is attachment in email
0214      *         FoundMissingAttachmentAndCancelSending, if mail might miss attachment but sending
0215      *         FoundMissingAttachmentAndAddedAttachment, if mail might miss attachment and we added an attachment
0216      *         FoundMissingAttachmentAndCancel, if mail might miss attachment and cancel sending
0217      */
0218     [[nodiscard]] ComposerViewBase::MissingAttachment checkForMissingAttachments(const QStringList &attachmentKeywords);
0219 
0220     [[nodiscard]] bool hasMissingAttachments(const QStringList &attachmentKeywords);
0221 
0222     void setSendLaterInfo(SendLaterInfo *info);
0223     [[nodiscard]] SendLaterInfo *sendLaterInfo() const;
0224     void saveMailSettings();
0225 
0226     [[nodiscard]] QDate followUpDate() const;
0227     void setFollowUpDate(const QDate &followUpDate);
0228 
0229     void clearFollowUp();
0230 
0231     [[nodiscard]] Akonadi::Collection followUpCollection() const;
0232     void setFollowUpCollection(const Akonadi::Collection &followUpCollection);
0233 
0234     [[nodiscard]] KMime::Message::Ptr msg() const;
0235 
0236     [[nodiscard]] bool requestDeleveryConfirmation() const;
0237     void setRequestDeleveryConfirmation(bool requestDeleveryConfirmation);
0238 
0239     [[nodiscard]] std::shared_ptr<Kleo::ExpiryChecker> expiryChecker();
0240 
0241 public Q_SLOTS:
0242     void identityChanged(const KIdentityManagementCore::Identity &ident, const KIdentityManagementCore::Identity &oldIdent, bool msgCleared = false);
0243 
0244     /**
0245      * Save the message.
0246      */
0247     void autoSaveMessage();
0248 
0249 Q_SIGNALS:
0250     /**
0251      * Message sending completed successfully.
0252      */
0253     void sentSuccessfully(Akonadi::Item::Id id);
0254     /**
0255      * Message sending failed with given error message.
0256      */
0257     void failed(const QString &errorMessage, MessageComposer::ComposerViewBase::FailedType type = Sending);
0258 
0259     /**
0260      * The composer was modified. This can happen behind the users' back
0261      *  when, for example, and autosaved message was recovered.
0262      */
0263     void modified(bool isModified);
0264 
0265     /**
0266      * Enabling or disabling HTML in the editor is affected
0267      *  by various client options, so when that would otherwise happen,
0268      *  hand it off to the client to enact it for real.
0269      */
0270     void disableHtml(MessageComposer::ComposerViewBase::Confirmation);
0271     void enableHtml();
0272     void tooManyRecipient(bool);
0273 
0274 private Q_SLOTS:
0275     void slotEmailAddressResolved(KJob *);
0276     void slotSendComposeResult(KJob *);
0277     void slotQueueResult(KJob *job);
0278     void slotCreateItemResult(KJob *);
0279     void slotAutoSaveComposeResult(KJob *job);
0280     void slotFccCollectionCheckResult(KJob *job);
0281     void slotSaveMessage(KJob *job);
0282 
0283 private:
0284     [[nodiscard]] Akonadi::Collection defaultSpecialTarget() const;
0285     /**
0286      * Searches the mime tree, where root is the root node, for embedded images,
0287      * extracts them froom the body and adds them to the editor.
0288      */
0289     void collectImages(KMime::Content *root);
0290     [[nodiscard]] bool inlineSigningEncryptionSelected() const;
0291     /**
0292      * Applies the user changes to the message object of the composer
0293      * and signs/encrypts the message if activated.
0294      * Disables the controls of the composer window.
0295      */
0296     void readyForSending();
0297 
0298     enum RecipientExpansion {
0299         UseExpandedRecipients,
0300         UseUnExpandedRecipients,
0301     };
0302     void fillComposer(MessageComposer::Composer *composer, ComposerViewBase::RecipientExpansion expansion, bool autoresize);
0303     [[nodiscard]] QList<MessageComposer::Composer *> generateCryptoMessages(bool &wasCanceled);
0304     void fillGlobalPart(MessageComposer::GlobalPart *globalPart);
0305     void fillInfoPart(MessageComposer::InfoPart *part, RecipientExpansion expansion);
0306     void queueMessage(const KMime::Message::Ptr &message, MessageComposer::Composer *composer);
0307     void saveMessage(const KMime::Message::Ptr &message, MessageComposer::MessageSender::SaveIn saveIn);
0308     void saveRecentAddresses(const KMime::Message::Ptr &ptr);
0309     void
0310     updateRecipients(const KIdentityManagementCore::Identity &ident, const KIdentityManagementCore::Identity &oldIdent, MessageComposer::Recipient::Type type);
0311 
0312     void markAllAttachmentsForSigning(bool sign);
0313     void markAllAttachmentsForEncryption(bool encrypt);
0314     bool determineWhetherToSign(bool doSignCompletely, Kleo::KeyResolver *keyResolver, bool signSomething, bool &result, bool &canceled);
0315     bool determineWhetherToEncrypt(bool doEncryptCompletely,
0316                                    Kleo::KeyResolver *keyResolver,
0317                                    bool encryptSomething,
0318                                    bool signSomething,
0319                                    bool &result,
0320                                    bool &canceled);
0321 
0322     /**
0323      * Writes out autosave data to the disk from the KMime::Message message.
0324      * Also appends the msgNum to the filename as a message can have a number of
0325      * KMime::Messages
0326      */
0327     void writeAutoSaveToDisk(const KMime::Message::Ptr &message);
0328 
0329     /**
0330      * Returns the autosave interval in milliseconds (as needed for QTimer).
0331      */
0332     int autoSaveInterval() const;
0333 
0334     /**
0335      * Initialize autosaving (timer and filename).
0336      */
0337     void initAutoSave();
0338     void addFollowupReminder(const QString &messageId);
0339     void addSendLaterItem(const Akonadi::Item &item);
0340 
0341     bool addKeysToContext(const QString &gnupgHome,
0342                           const QList<QPair<QStringList, std::vector<GpgME::Key>>> &data,
0343                           const std::map<QByteArray, QString> &autocryptMap);
0344 
0345     void setAkonadiLookupEnabled(bool akonadiLookupEnabled);
0346 
0347     KMime::Message::Ptr m_msg;
0348     MessageComposer::AttachmentControllerBase *m_attachmentController = nullptr;
0349     MessageComposer::AttachmentModel *m_attachmentModel = nullptr;
0350     MessageComposer::SignatureController *m_signatureController = nullptr;
0351     MessageComposer::RecipientsEditor *m_recipientsEditor = nullptr;
0352     KIdentityManagementWidgets::IdentityCombo *m_identityCombo = nullptr;
0353     KIdentityManagementCore::IdentityManager *m_identMan = nullptr;
0354     MessageComposer::RichTextComposerNg *m_editor = nullptr;
0355     MailTransport::TransportComboBox *m_transport = nullptr;
0356     Sonnet::DictionaryComboBox *m_dictionary = nullptr;
0357     Akonadi::CollectionComboBox *m_fccCombo = nullptr;
0358     Akonadi::Collection m_fccCollection;
0359     QWidget *m_parentWidget = nullptr;
0360 
0361     // List of active composer jobs. For example, saving as draft, autosaving and printing
0362     // all create a composer, which is added to this list as long as it is active.
0363     // Used mainly to prevent closing the window if a composer is active
0364     QList<MessageComposer::Composer *> m_composers;
0365 
0366     bool m_sign = false;
0367     bool m_encrypt = false;
0368     bool m_neverEncrypt = false;
0369     bool m_mdnRequested = false;
0370     bool m_urgent = false;
0371     bool m_requestDeleveryConfirmation = false;
0372     bool m_akonadiLookupEnabled = true;
0373     Kleo::CryptoMessageFormat m_cryptoMessageFormat;
0374     QString mExpandedFrom;
0375     QString m_from;
0376     QString m_subject;
0377     QStringList mExpandedTo, mExpandedCc, mExpandedBcc, mExpandedReplyTo;
0378     QList<QByteArray> m_charsets;
0379     QMap<QByteArray, QString> m_customHeader;
0380 
0381     int m_pendingQueueJobs = 0;
0382 
0383     QTimer *m_autoSaveTimer = nullptr;
0384     QString m_autoSaveUUID;
0385     bool m_autoSaveErrorShown = false; // Stops an error message being shown every time autosave is executed.
0386     int m_autoSaveInterval;
0387 
0388     MessageComposer::MessageSender::SendMethod mSendMethod;
0389     MessageComposer::MessageSender::SaveIn mSaveIn;
0390 
0391     std::shared_ptr<Kleo::ExpiryChecker> mExpiryChecker;
0392 
0393     QDate mFollowUpDate;
0394     Akonadi::Collection mFollowUpCollection;
0395 
0396     std::unique_ptr<SendLaterInfo> mSendLaterInfo;
0397 
0398     friend ComposerViewBaseTest;
0399 };
0400 } // namespace