File indexing completed on 2024-06-09 05:18:16

0001 /*
0002   SPDX-FileCopyrightText: 2005 Till Adam <adam@kde.org>
0003 
0004   SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 #include "mailutil.h"
0008 #include "mailutil_p.h"
0009 
0010 #include "calendarinterface.h"
0011 #include "filter/dialog/filteractionmissingfolderdialog.h"
0012 #include "folder/foldersettings.h"
0013 #include "job/expirejob.h"
0014 #include "kernel/mailkernel.h"
0015 #include "mailcommon_debug.h"
0016 #include "pop3settings.h"
0017 
0018 #include <MailImporter/FilterBalsa>
0019 #include <MailImporter/FilterClawsMail>
0020 #include <MailImporter/FilterEvolution>
0021 #include <MailImporter/FilterEvolution_v2>
0022 #include <MailImporter/FilterEvolution_v3>
0023 #include <MailImporter/FilterIcedove>
0024 #include <MailImporter/FilterOpera>
0025 #include <MailImporter/FilterSylpheed>
0026 #include <MailImporter/FilterThunderbird>
0027 #include <MailImporter/OtherMailerUtil>
0028 
0029 #include <MessageCore/StringUtil>
0030 
0031 #include <MessageComposer/MessageHelper>
0032 
0033 #include <Akonadi/AgentManager>
0034 #include <Akonadi/EntityMimeTypeFilterModel>
0035 #include <Akonadi/EntityTreeModel>
0036 #include <Akonadi/ItemFetchJob>
0037 #include <Akonadi/ItemFetchScope>
0038 #include <Akonadi/MessageParts>
0039 #include <Akonadi/NewMailNotifierAttribute>
0040 #include <Akonadi/ServerManager>
0041 
0042 #include <KMime/KMimeMessage>
0043 
0044 #include "collectionpage/attributes/expirecollectionattribute.h"
0045 #include <KIO/Job>
0046 #include <KIO/JobUiDelegate>
0047 #include <KJob>
0048 
0049 OrgKdeAkonadiPOP3SettingsInterface *MailCommon::Util::createPop3SettingsInterface(const QString &ident)
0050 {
0051     const auto service = Akonadi::ServerManager::agentServiceName(Akonadi::ServerManager::Resource, ident);
0052     return new OrgKdeAkonadiPOP3SettingsInterface(service, QStringLiteral("/Settings"), QDBusConnection::sessionBus());
0053 }
0054 
0055 bool MailCommon::Util::isVirtualCollection(const Akonadi::Collection &collection)
0056 {
0057     return collection.isVirtual() || MailCommon::Util::isVirtualCollection(collection.resource());
0058 }
0059 
0060 bool MailCommon::Util::isVirtualCollection(const QString &resource)
0061 {
0062     if (resource == QLatin1StringView("akonadi_search_resource")) {
0063         return true;
0064     }
0065 
0066     const auto type = Akonadi::AgentManager::self()->type(resource);
0067     return type.capabilities().contains(QLatin1StringView("Virtual"));
0068 }
0069 
0070 bool MailCommon::Util::isLocalCollection(const QString &resource)
0071 {
0072     auto type = Akonadi::AgentManager::self()->type(resource);
0073     return type.customProperties().value(QStringLiteral("HasLocalStorage"), false).toBool();
0074 }
0075 
0076 QString MailCommon::Util::fullCollectionPath(const Akonadi::Collection &collection, bool addAccountName)
0077 {
0078     QString fullPath;
0079 
0080     QModelIndex idx = Akonadi::EntityTreeModel::modelIndexForCollection(KernelIf->collectionModel(), collection);
0081     if (!idx.isValid()) {
0082         return fullPath;
0083     }
0084 
0085     fullPath = idx.data().toString();
0086     idx = idx.parent();
0087     while (idx != QModelIndex()) {
0088         const QString tmp = idx.data().toString() + QLatin1Char('/') + fullPath;
0089         idx = idx.parent();
0090         if (idx != QModelIndex()) {
0091             fullPath = tmp;
0092         } else {
0093             if (!addAccountName) {
0094                 break;
0095             } else {
0096                 fullPath = tmp;
0097                 break;
0098             }
0099         }
0100     }
0101     return fullPath;
0102 }
0103 
0104 QString MailCommon::Util::fullCollectionRemoveIdPath(const Akonadi::Collection &collection, bool addAccountName)
0105 {
0106     QString fullPath;
0107 
0108     QModelIndex idx = Akonadi::EntityTreeModel::modelIndexForCollection(KernelIf->collectionModel(), collection);
0109     if (!idx.isValid()) {
0110         return fullPath;
0111     }
0112 
0113     fullPath = idx.data().toString();
0114     idx = idx.parent();
0115     while (idx != QModelIndex()) {
0116         const QString tmp = idx.data(Akonadi::EntityTreeModel::RemoteIdRole).toString() + QLatin1Char('/') + fullPath;
0117         idx = idx.parent();
0118         if (idx != QModelIndex()) {
0119             fullPath = tmp;
0120         } else {
0121             if (!addAccountName) {
0122                 break;
0123             } else {
0124                 fullPath = tmp;
0125                 break;
0126             }
0127         }
0128     }
0129     return fullPath;
0130 }
0131 
0132 bool MailCommon::Util::showJobErrorMessage(KJob *job)
0133 {
0134     if (job->error()) {
0135         if (auto uidelegate = static_cast<KIO::Job *>(job)->uiDelegate()) {
0136             uidelegate->showErrorMessage();
0137         } else {
0138             qCDebug(MAILCOMMON_LOG) << " job->errorString() :" << job->errorString();
0139         }
0140         return true;
0141     }
0142     return false;
0143 }
0144 
0145 Akonadi::AgentInstance::List MailCommon::Util::agentInstances(bool excludeMailDispacher)
0146 {
0147     Akonadi::AgentInstance::List relevantInstances;
0148     const Akonadi::AgentInstance::List agentList = Akonadi::AgentManager::self()->instances();
0149     std::copy_if(agentList.cbegin(), agentList.cend(), std::back_inserter(relevantInstances), [excludeMailDispacher](const Akonadi::AgentInstance &instance) {
0150         return isMailAgent(instance, excludeMailDispacher);
0151     });
0152     return relevantInstances;
0153 }
0154 
0155 bool MailCommon::Util::isMailAgent(const Akonadi::AgentInstance &instance, bool excludeMailTransport)
0156 {
0157     if (!instance.type().mimeTypes().contains(KMime::Message::mimeType())) {
0158         return false;
0159     }
0160 
0161     const QStringList capabilities(instance.type().capabilities());
0162     if (capabilities.contains(QLatin1StringView("Resource")) && !capabilities.contains(QLatin1StringView("Virtual"))
0163         && !capabilities.contains(QLatin1StringView("MailTransport")) && !capabilities.contains(QLatin1StringView("Autostart"))) {
0164         return true;
0165     } else if (!excludeMailTransport && instance.identifier() == QLatin1StringView("akonadi_maildispatcher_agent")) {
0166         return true;
0167     }
0168 
0169     return false;
0170 }
0171 
0172 bool MailCommon::Util::isUnifiedMailboxesAgent(const Akonadi::Collection &col)
0173 {
0174     return col.resource() == QLatin1StringView("akonadi_unifiedmailbox_agent");
0175 }
0176 
0177 uint MailCommon::Util::folderIdentity(const Akonadi::Item &item)
0178 {
0179     uint id = 0;
0180     if (item.isValid() && item.parentCollection().isValid()) {
0181         Akonadi::Collection col = item.parentCollection();
0182         if (col.resource().isEmpty()) {
0183             col = CommonKernel->collectionFromId(col.id());
0184         }
0185         const QSharedPointer<FolderSettings> fd = FolderSettings::forCollection(col, false);
0186 
0187         id = fd->identity();
0188     }
0189     return id;
0190 }
0191 
0192 bool MailCommon::Util::ignoreNewMailInFolder(const Akonadi::Collection &collection)
0193 {
0194     if (collection.hasAttribute<Akonadi::NewMailNotifierAttribute>()) {
0195         if (collection.attribute<Akonadi::NewMailNotifierAttribute>()->ignoreNewMail()) {
0196             return true;
0197         }
0198     }
0199     return false;
0200 }
0201 
0202 QString MailCommon::Util::realFolderPath(const QString &path)
0203 {
0204     QString realPath(path);
0205     realPath.remove(QStringLiteral(".directory"));
0206     realPath.replace(QLatin1StringView("/."), QStringLiteral("/"));
0207     if (!realPath.isEmpty() && (realPath.at(0) == QLatin1Char('.'))) {
0208         realPath.remove(0, 1); // remove first "."
0209     }
0210     return realPath;
0211 }
0212 
0213 void MailCommon::Util::expireOldMessages(const Akonadi::Collection &collection, bool immediate)
0214 {
0215     auto task = new ScheduledExpireTask(collection, immediate);
0216     KernelIf->jobScheduler()->registerTask(task);
0217 }
0218 
0219 Akonadi::Collection::Id MailCommon::Util::convertFolderPathToCollectionId(const QString &folder)
0220 {
0221     Akonadi::Collection::Id newFolderId = -1;
0222     bool exactPath = false;
0223     const Akonadi::Collection::List lst = FilterActionMissingFolderDialog::potentialCorrectFolders(folder, exactPath);
0224     if (lst.count() == 1 && exactPath) {
0225         newFolderId = lst.at(0).id();
0226     } else {
0227         QPointer<FilterActionMissingFolderDialog> dlg = new FilterActionMissingFolderDialog(lst, QString(), folder);
0228         if (dlg->exec()) {
0229             newFolderId = dlg->selectedCollection().id();
0230         }
0231         delete dlg;
0232     }
0233     return newFolderId;
0234 }
0235 
0236 QString MailCommon::Util::convertFolderPathToCollectionStr(const QString &folder)
0237 {
0238     Akonadi::Collection::Id newFolderId = MailCommon::Util::convertFolderPathToCollectionId(folder);
0239     if (newFolderId == -1) {
0240         return {};
0241     }
0242     return QString::number(newFolderId);
0243 }
0244 
0245 void MailCommon::Util::foundMailer(QStringList &lst, const QString &name)
0246 {
0247     if (!name.isEmpty()) {
0248         lst.append(name);
0249     }
0250 }
0251 
0252 QStringList MailCommon::Util::foundMailer()
0253 {
0254     QStringList lst;
0255     MailCommon::Util::foundMailer(lst, MailImporter::FilterEvolution::isMailerFound());
0256     MailCommon::Util::foundMailer(lst, MailImporter::FilterEvolution_v2::isMailerFound());
0257     MailCommon::Util::foundMailer(lst, MailImporter::FilterEvolution_v3::isMailerFound());
0258     MailCommon::Util::foundMailer(lst, MailImporter::FilterBalsa::isMailerFound());
0259     MailCommon::Util::foundMailer(lst, MailImporter::FilterClawsMail::isMailerFound());
0260     MailCommon::Util::foundMailer(lst, MailImporter::FilterOpera::isMailerFound());
0261     MailCommon::Util::foundMailer(lst, MailImporter::FilterSylpheed::isMailerFound());
0262     MailCommon::Util::foundMailer(lst, MailImporter::FilterThunderbird::isMailerFound());
0263     MailCommon::Util::foundMailer(lst, MailImporter::FilterIcedove::isMailerFound());
0264     const QStringList otherMailer = MailImporter::OtherMailerUtil::isMailerFound();
0265     if (!otherMailer.isEmpty()) {
0266         lst << otherMailer;
0267     }
0268     return lst;
0269 }