diff --git a/resources/imap/removecollectionrecursivetask.cpp b/resources/imap/removecollectionrecursivetask.cpp index 761b1c529..cdd2ea7a7 100644 --- a/resources/imap/removecollectionrecursivetask.cpp +++ b/resources/imap/removecollectionrecursivetask.cpp @@ -1,169 +1,169 @@ /* Copyright (c) 2010 Klarälvdalens Datakonsult AB, a KDAB Group company Author: Tobias Koenig This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "removecollectionrecursivetask.h" #include #include #include #include #include #include #include #include "imapresource_debug.h" Q_DECLARE_METATYPE(KIMAP::DeleteJob *) RemoveCollectionRecursiveTask::RemoveCollectionRecursiveTask(const ResourceStateInterface::Ptr &resource, QObject *parent) - : ResourceTask(CancelIfNoSession, resource, parent) + : ResourceTask(DeferIfNoSession, resource, parent) , mSession(nullptr) , mFolderFound(false) { } RemoveCollectionRecursiveTask::~RemoveCollectionRecursiveTask() { } void RemoveCollectionRecursiveTask::doStart(KIMAP::Session *session) { mSession = session; mFolderFound = false; KIMAP::ListJob *listJob = new KIMAP::ListJob(session); listJob->setIncludeUnsubscribed(!isSubscriptionEnabled()); listJob->setQueriedNamespaces(serverNamespaces()); connect(listJob, &KIMAP::ListJob::mailBoxesReceived, this, &RemoveCollectionRecursiveTask::onMailBoxesReceived); connect(listJob, &KIMAP::ListJob::result, this, &RemoveCollectionRecursiveTask::onJobDone); listJob->start(); } void RemoveCollectionRecursiveTask::onMailBoxesReceived(const QList< KIMAP::MailBoxDescriptor > &descriptors, const QList< QList > &) { const QString mailBox = mailBoxForCollection(collection()); // We have to delete the deepest-nested folders first, so // we use a map here that has the level of nesting as key. QMultiMap foldersToDelete; for (int i = 0; i < descriptors.size(); ++i) { const KIMAP::MailBoxDescriptor descriptor = descriptors[ i ]; if (descriptor.name == mailBox || descriptor.name.startsWith(mailBox + descriptor.separator)) { // a sub folder to delete const QStringList pathParts = descriptor.name.split(descriptor.separator); foldersToDelete.insert(pathParts.count(), descriptor); } } if (foldersToDelete.isEmpty()) { return; } mFolderFound = true; // Now start the actual deletion work mFolderIterator.reset(new QMapIterator(foldersToDelete)); mFolderIterator->toBack(); // we start with largest nesting value first deleteNextMailbox(); } void RemoveCollectionRecursiveTask::deleteNextMailbox() { if (!mFolderIterator->hasPrevious()) { changeProcessed(); // finish the job return; } mFolderIterator->previous(); const KIMAP::MailBoxDescriptor &descriptor = mFolderIterator->value(); qCDebug(IMAPRESOURCE_LOG) << descriptor.name; // first select the mailbox KIMAP::SelectJob *selectJob = new KIMAP::SelectJob(mSession); selectJob->setMailBox(descriptor.name); connect(selectJob, &KIMAP::SelectJob::result, this, &RemoveCollectionRecursiveTask::onJobDone); selectJob->start(); // mark all items as deleted // This step shouldn't be required, but apparently some servers don't allow deleting, non empty mailboxes (although they should). KIMAP::ImapSet allItems; allItems.add(KIMAP::ImapInterval(1, 0)); // means 1:* KIMAP::StoreJob *storeJob = new KIMAP::StoreJob(mSession); storeJob->setSequenceSet(allItems); storeJob->setFlags(KIMAP::MessageFlags() << Akonadi::MessageFlags::Deleted); storeJob->setMode(KIMAP::StoreJob::AppendFlags); // The result is explicitly ignored, since this can fail in the case of an empty folder storeJob->start(); // Some IMAP servers don't allow deleting an opened mailbox, so make sure // it's not opened (https://bugs.kde.org/show_bug.cgi?id=324932). CLOSE will // also trigger EXPUNGE to take care of the messages deleted above KIMAP::CloseJob *closeJob = new KIMAP::CloseJob(mSession); closeJob->setProperty("folderDescriptor", descriptor.name); connect(closeJob, &KIMAP::CloseJob::result, this, &RemoveCollectionRecursiveTask::onCloseJobDone); closeJob->start(); } void RemoveCollectionRecursiveTask::onCloseJobDone(KJob *job) { if (job->error()) { changeProcessed(); qCDebug(IMAPRESOURCE_LOG) << "Failed to close the folder, resync the folder tree"; emitWarning(i18n("Failed to delete the folder, restoring folder list.")); synchronizeCollectionTree(); } else { KIMAP::DeleteJob *deleteJob = new KIMAP::DeleteJob(mSession); deleteJob->setMailBox(job->property("folderDescriptor").toString()); connect(deleteJob, &KIMAP::DeleteJob::result, this, &RemoveCollectionRecursiveTask::onDeleteJobDone); deleteJob->start(); } } void RemoveCollectionRecursiveTask::onDeleteJobDone(KJob *job) { if (job->error()) { changeProcessed(); qCDebug(IMAPRESOURCE_LOG) << "Failed to delete the folder, resync the folder tree"; emitWarning(i18n("Failed to delete the folder, restoring folder list.")); synchronizeCollectionTree(); } else { deleteNextMailbox(); } } void RemoveCollectionRecursiveTask::onJobDone(KJob *job) { if (job->error()) { changeProcessed(); qCDebug(IMAPRESOURCE_LOG) << "Failed to delete the folder, resync the folder tree"; emitWarning(i18n("Failed to delete the folder, restoring folder list.")); synchronizeCollectionTree(); } else if (!mFolderFound) { changeProcessed(); qCDebug(IMAPRESOURCE_LOG) << "Failed to find the folder to be deleted, resync the folder tree"; emitWarning(i18n("Failed to find the folder to be deleted, restoring folder list.")); synchronizeCollectionTree(); } }