File indexing completed on 2024-11-17 04:45:07
0001 /* 0002 SPDX-FileCopyrightText: 2014 Christian Mollekopf <mollekopf@kolabsys.com> 0003 0004 SPDX-License-Identifier: LGPL-2.0-or-later 0005 */ 0006 0007 #include "replacemessagejob.h" 0008 0009 #include "imapresource_debug.h" 0010 #include <KIMAP/AppendJob> 0011 #include <KIMAP/SearchJob> 0012 #include <KIMAP/SelectJob> 0013 #include <KIMAP/StoreJob> 0014 0015 #include "imapflags.h" 0016 0017 ReplaceMessageJob::ReplaceMessageJob(const KMime::Message::Ptr &msg, 0018 KIMAP::Session *session, 0019 const QString &mailbox, 0020 qint64 uidNext, 0021 const KIMAP::ImapSet &oldUids, 0022 QObject *parent) 0023 : KJob(parent) 0024 , mSession(session) 0025 , mMessage(msg) 0026 , mMailbox(mailbox) 0027 , mUidNext(uidNext) 0028 , mOldUids(oldUids) 0029 , mMessageId(msg->messageID()->asUnicodeString().toUtf8()) 0030 { 0031 } 0032 0033 void ReplaceMessageJob::start() 0034 { 0035 auto job = new KIMAP::AppendJob(mSession); 0036 job->setMailBox(mMailbox); 0037 job->setContent(mMessage->encodedContent(true)); 0038 job->setInternalDate(mMessage->date()->dateTime()); 0039 connect(job, &KJob::result, this, &ReplaceMessageJob::onAppendMessageDone); 0040 job->start(); 0041 } 0042 0043 void ReplaceMessageJob::onAppendMessageDone(KJob *job) 0044 { 0045 auto append = qobject_cast<KIMAP::AppendJob *>(job); 0046 0047 if (append->error()) { 0048 qCWarning(IMAPRESOURCE_LOG) << append->errorString(); 0049 setError(KJob::UserDefinedError); 0050 emitResult(); 0051 return; 0052 } 0053 0054 // We get it directly if UIDPLUS is supported... 0055 mNewUid = append->uid(); 0056 0057 if (mNewUid > 0 && mOldUids.isEmpty()) { 0058 // We have the uid an no message to delete, we're done 0059 emitResult(); 0060 return; 0061 } 0062 0063 if (mSession->selectedMailBox() != mMailbox) { 0064 // For search and delete we need to select the right mailbox first 0065 auto select = new KIMAP::SelectJob(mSession); 0066 select->setMailBox(mMailbox); 0067 connect(select, &KJob::result, this, &ReplaceMessageJob::onSelectDone); 0068 select->start(); 0069 } else { 0070 if (mNewUid > 0) { 0071 triggerDeleteJobIfNecessary(); 0072 } else { 0073 triggerSearchJob(); 0074 } 0075 } 0076 } 0077 0078 void ReplaceMessageJob::onSelectDone(KJob *job) 0079 { 0080 if (job->error()) { 0081 qCWarning(IMAPRESOURCE_LOG) << job->errorString(); 0082 setError(KJob::UserDefinedError); 0083 emitResult(); 0084 } else { 0085 if (mNewUid > 0) { 0086 triggerDeleteJobIfNecessary(); 0087 } else { 0088 triggerSearchJob(); 0089 } 0090 } 0091 } 0092 0093 void ReplaceMessageJob::triggerSearchJob() 0094 { 0095 auto search = new KIMAP::SearchJob(mSession); 0096 0097 search->setUidBased(true); 0098 0099 if (!mMessageId.isEmpty()) { 0100 search->setTerm(KIMAP::Term(QStringLiteral("Message-ID"), QString::fromLatin1(mMessageId))); 0101 } else { 0102 if (mUidNext < 0) { 0103 qCWarning(IMAPRESOURCE_LOG) << "Could not determine the UID for the newly created message on the server"; 0104 search->deleteLater(); 0105 setError(KJob::UserDefinedError); 0106 emitResult(); 0107 return; 0108 } 0109 search->setTerm(KIMAP::Term(KIMAP::Term::And, {KIMAP::Term(KIMAP::Term::New), KIMAP::Term(KIMAP::Term::Uid, KIMAP::ImapSet(mUidNext, 0))})); 0110 } 0111 0112 connect(search, &KJob::result, this, &ReplaceMessageJob::onSearchDone); 0113 0114 search->start(); 0115 } 0116 0117 void ReplaceMessageJob::onSearchDone(KJob *job) 0118 { 0119 if (job->error()) { 0120 qCWarning(IMAPRESOURCE_LOG) << job->errorString(); 0121 setError(KJob::UserDefinedError); 0122 emitResult(); 0123 return; 0124 } 0125 0126 auto search = static_cast<KIMAP::SearchJob *>(job); 0127 0128 if (search->results().count() == 1) { 0129 mNewUid = search->results().at(0); 0130 } else { 0131 qCWarning(IMAPRESOURCE_LOG) << "Failed to find uid for message. Got 0 or too many results: " << search->results().count(); 0132 setError(KJob::UserDefinedError); 0133 emitResult(); 0134 return; 0135 } 0136 triggerDeleteJobIfNecessary(); 0137 } 0138 0139 void ReplaceMessageJob::triggerDeleteJobIfNecessary() 0140 { 0141 if (mOldUids.isEmpty()) { 0142 // Nothing to do, we're done 0143 emitResult(); 0144 } else { 0145 auto store = new KIMAP::StoreJob(mSession); 0146 store->setUidBased(true); 0147 store->setSequenceSet(mOldUids); 0148 store->setFlags(QList<QByteArray>() << ImapFlags::Deleted); 0149 store->setMode(KIMAP::StoreJob::AppendFlags); 0150 connect(store, &KJob::result, this, &ReplaceMessageJob::onDeleteDone); 0151 store->start(); 0152 } 0153 } 0154 0155 void ReplaceMessageJob::onDeleteDone(KJob *job) 0156 { 0157 if (job->error()) { 0158 qCWarning(IMAPRESOURCE_LOG) << job->errorString(); 0159 } 0160 emitResult(); 0161 } 0162 0163 qint64 ReplaceMessageJob::newUid() const 0164 { 0165 return mNewUid; 0166 } 0167 0168 #include "moc_replacemessagejob.cpp"