File indexing completed on 2024-05-12 05:11:11

0001 /*
0002   SPDX-FileCopyrightText: 2009 Constantin Berzan <exit3219@gmail.com>
0003 
0004   SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 #include "messagequeuejob.h"
0008 
0009 #include "transportattribute.h"
0010 
0011 #include "akonadi_mime_debug.h"
0012 #include <KLocalizedString>
0013 
0014 #include <Akonadi/Item>
0015 #include <Akonadi/ItemCreateJob>
0016 #include <Akonadi/MessageFlags>
0017 #include <Akonadi/SpecialMailCollections>
0018 #include <Akonadi/SpecialMailCollectionsRequestJob>
0019 
0020 using namespace Akonadi;
0021 using namespace KMime;
0022 
0023 /**
0024   @internal
0025 */
0026 class Akonadi::MessageQueueJobPrivate
0027 {
0028 public:
0029     explicit MessageQueueJobPrivate(MessageQueueJob *qq)
0030         : q(qq)
0031     {
0032     }
0033 
0034     MessageQueueJob *const q;
0035 
0036     Message::Ptr message;
0037     TransportAttribute transportAttribute;
0038     DispatchModeAttribute dispatchModeAttribute;
0039     SentBehaviourAttribute sentBehaviourAttribute;
0040     SentActionAttribute sentActionAttribute;
0041     AddressAttribute addressAttribute;
0042     bool started = false;
0043 
0044     /**
0045       Returns true if this message has everything it needs and is ready to be
0046       sent.
0047     */
0048     [[nodiscard]] bool validate() const;
0049 
0050     // slot
0051     void outboxRequestResult(KJob *job);
0052 };
0053 
0054 bool MessageQueueJobPrivate::validate() const
0055 {
0056     if (!message) {
0057         q->setError(KJob::UserDefinedError);
0058         q->setErrorText(i18n("Empty message."));
0059         q->emitResult();
0060         return false;
0061     }
0062 
0063     if ((addressAttribute.to().count() + addressAttribute.cc().count() + addressAttribute.bcc().count()) == 0) {
0064         q->setError(KJob::UserDefinedError);
0065         q->setErrorText(i18n("Message has no recipients."));
0066         q->emitResult();
0067         return false;
0068     }
0069 
0070     if (sentBehaviourAttribute.sentBehaviour() == SentBehaviourAttribute::MoveToCollection && !(sentBehaviourAttribute.moveToCollection().isValid())) {
0071         q->setError(KJob::UserDefinedError);
0072         q->setErrorText(i18n("Message has invalid sent-mail folder."));
0073         q->emitResult();
0074         return false;
0075     } else if (sentBehaviourAttribute.sentBehaviour() == SentBehaviourAttribute::MoveToDefaultSentCollection) {
0076         // TODO require SpecialMailCollections::SentMail here?
0077     }
0078 
0079     return true; // all ok
0080 }
0081 
0082 void MessageQueueJobPrivate::outboxRequestResult(KJob *job)
0083 {
0084     Q_ASSERT(!started);
0085     started = true;
0086 
0087     if (job->error()) {
0088         qCritical() << "Failed to get the Outbox folder:" << job->error() << job->errorString();
0089         q->setError(job->error());
0090         q->emitResult();
0091         return;
0092     }
0093 
0094     if (!validate()) {
0095         // The error has been set; the result has been emitted.
0096         return;
0097     }
0098 
0099     auto requestJob = qobject_cast<SpecialMailCollectionsRequestJob *>(job);
0100     if (!requestJob) {
0101         return;
0102     }
0103 
0104     // Create item.
0105     Item item;
0106     item.setMimeType(QStringLiteral("message/rfc822"));
0107     item.setPayload<Message::Ptr>(message);
0108 
0109     // Set attributes.
0110     item.addAttribute(addressAttribute.clone());
0111     item.addAttribute(dispatchModeAttribute.clone());
0112     item.addAttribute(sentBehaviourAttribute.clone());
0113     item.addAttribute(sentActionAttribute.clone());
0114     item.addAttribute(transportAttribute.clone());
0115 
0116     Akonadi::MessageFlags::copyMessageFlags(*message, item);
0117     // Set flags.
0118     item.setFlag(Akonadi::MessageFlags::Queued);
0119 
0120     // Store the item in the outbox.
0121     const Collection collection = requestJob->collection();
0122     Q_ASSERT(collection.isValid());
0123     auto cjob = new ItemCreateJob(item, collection); // job autostarts
0124     q->addSubjob(cjob);
0125 }
0126 
0127 MessageQueueJob::MessageQueueJob(QObject *parent)
0128     : KCompositeJob(parent)
0129     , d(new MessageQueueJobPrivate(this))
0130 {
0131 }
0132 
0133 MessageQueueJob::~MessageQueueJob() = default;
0134 
0135 Message::Ptr MessageQueueJob::message() const
0136 {
0137     return d->message;
0138 }
0139 
0140 DispatchModeAttribute &MessageQueueJob::dispatchModeAttribute()
0141 {
0142     return d->dispatchModeAttribute;
0143 }
0144 
0145 AddressAttribute &MessageQueueJob::addressAttribute()
0146 {
0147     return d->addressAttribute;
0148 }
0149 
0150 TransportAttribute &MessageQueueJob::transportAttribute()
0151 {
0152     return d->transportAttribute;
0153 }
0154 
0155 SentBehaviourAttribute &MessageQueueJob::sentBehaviourAttribute()
0156 {
0157     return d->sentBehaviourAttribute;
0158 }
0159 
0160 SentActionAttribute &MessageQueueJob::sentActionAttribute()
0161 {
0162     return d->sentActionAttribute;
0163 }
0164 
0165 void MessageQueueJob::setMessage(const Message::Ptr &message)
0166 {
0167     d->message = message;
0168 }
0169 
0170 void MessageQueueJob::start()
0171 {
0172     auto rjob = new SpecialMailCollectionsRequestJob(this);
0173     rjob->requestDefaultCollection(SpecialMailCollections::Outbox);
0174     connect(rjob, &SpecialMailCollectionsRequestJob::result, this, [this](KJob *job) {
0175         d->outboxRequestResult(job);
0176     });
0177     rjob->start();
0178 }
0179 
0180 void MessageQueueJob::slotResult(KJob *job)
0181 {
0182     // error handling
0183     KCompositeJob::slotResult(job);
0184 
0185     if (!error()) {
0186         emitResult();
0187     }
0188 }
0189 
0190 #include "moc_messagequeuejob.cpp"