File indexing completed on 2025-03-09 04:54:28
0001 /* 0002 SPDX-FileCopyrightText: 2019-2024 Laurent Montel <montel@kde.org> 0003 0004 SPDX-License-Identifier: LGPL-2.0-or-later 0005 */ 0006 0007 #include "dkimcheckfulljob.h" 0008 #include "dkimauthenticationstatusinfoconverter.h" 0009 #include "dkimcheckauthenticationstatusjob.h" 0010 #include "dkimcheckpolicyjob.h" 0011 #include "dkimgeneraterulejob.h" 0012 #include "dkimmanagerkey.h" 0013 #include "dkimstoreresultjob.h" 0014 #include "messageviewer_dkimcheckerdebug.h" 0015 #include <KLocalizedString> 0016 #include <KMessageBox> 0017 using namespace MessageViewer; 0018 0019 DKIMCheckFullJob::DKIMCheckFullJob(QObject *parent) 0020 : QObject(parent) 0021 { 0022 } 0023 0024 DKIMCheckFullJob::~DKIMCheckFullJob() = default; 0025 0026 DKIMCheckPolicy DKIMCheckFullJob::policy() const 0027 { 0028 return mCheckPolicy; 0029 } 0030 0031 void DKIMCheckFullJob::setPolicy(const DKIMCheckPolicy &policy) 0032 { 0033 mCheckPolicy = policy; 0034 } 0035 0036 void DKIMCheckFullJob::startCheckFullInfo(const Akonadi::Item &item) 0037 { 0038 if (!item.isValid()) { 0039 deleteLater(); 0040 qCWarning(MESSAGEVIEWER_DKIMCHECKER_LOG) << "Invalid item"; 0041 return; 0042 } 0043 mAkonadiItem = item; 0044 if (mAkonadiItem.hasPayload<KMime::Message::Ptr>()) { 0045 mMessage = mAkonadiItem.payload<KMime::Message::Ptr>(); 0046 } 0047 if (!mMessage) { 0048 deleteLater(); 0049 qCWarning(MESSAGEVIEWER_DKIMCHECKER_LOG) << "Invalid message"; 0050 return; 0051 } 0052 checkAuthenticationResults(); 0053 } 0054 0055 void DKIMCheckFullJob::checkAuthenticationResults() 0056 { 0057 if (mCheckPolicy.useAuthenticationResults()) { 0058 auto job = new DKIMCheckAuthenticationStatusJob(this); 0059 mHeaderParser.setHead(mMessage->head()); 0060 mHeaderParser.parse(); 0061 job->setHeaderParser(mHeaderParser); 0062 job->setUseRelaxedParsing(mCheckPolicy.useRelaxedParsing()); 0063 connect(job, &DKIMCheckAuthenticationStatusJob::result, this, &DKIMCheckFullJob::slotCheckAuthenticationStatusResult); 0064 job->start(); 0065 } else { 0066 checkSignature(); 0067 } 0068 } 0069 0070 void DKIMCheckFullJob::checkSignature(const QList<DKIMCheckSignatureJob::DKIMCheckSignatureAuthenticationResult> &lst) 0071 { 0072 auto job = new DKIMCheckSignatureJob(this); 0073 connect(job, &DKIMCheckSignatureJob::storeKey, this, &DKIMCheckFullJob::storeKey); 0074 connect(job, &DKIMCheckSignatureJob::result, this, &DKIMCheckFullJob::slotCheckSignatureResult); 0075 job->setMessage(mMessage); 0076 job->setHeaderParser(mHeaderParser); 0077 job->setPolicy(mCheckPolicy); 0078 job->setCheckSignatureAuthenticationResult(lst); 0079 job->start(); 0080 } 0081 0082 void DKIMCheckFullJob::startCheckFullInfo(const KMime::Message::Ptr &message) 0083 { 0084 mMessage = message; 0085 if (!mMessage) { 0086 deleteLater(); 0087 qCWarning(MESSAGEVIEWER_DKIMCHECKER_LOG) << "Invalid message"; 0088 return; 0089 } 0090 checkAuthenticationResults(); 0091 } 0092 0093 void DKIMCheckFullJob::storeKey(const QString &key, const QString &domain, const QString &selector) 0094 { 0095 switch (mCheckPolicy.saveKey()) { 0096 case MessageViewer::MessageViewerSettings::EnumSaveKey::NotSaving: 0097 // Nothing 0098 break; 0099 case MessageViewer::MessageViewerSettings::EnumSaveKey::Save: 0100 storeInKeyManager(key, selector, domain, false); 0101 break; 0102 case MessageViewer::MessageViewerSettings::EnumSaveKey::SaveAndCompare: 0103 storeInKeyManager(key, selector, domain, true); 0104 break; 0105 } 0106 } 0107 0108 void DKIMCheckFullJob::storeInKeyManager(const QString &key, const QString &domain, const QString &selector, bool verify) 0109 { 0110 const MessageViewer::KeyInfo info{key, selector, domain, QDateTime::currentDateTime()}; 0111 if (verify) { 0112 const QString keyStored = MessageViewer::DKIMManagerKey::self()->keyValue(selector, domain); 0113 if (!keyStored.isEmpty()) { 0114 if (keyStored != key) { 0115 // qDebug() << "storeInKeyManager : keyStored " << keyStored << " key " << key; 0116 // qDebug() << "domain " << domain << " selector " << selector; 0117 const int answer = KMessageBox::warningTwoActions(nullptr, 0118 i18n("Stored DKIM key is different from the current one. Do you want to store this one too?"), 0119 i18nc("@title:window", "Key Changed"), 0120 KGuiItem(i18nc("@action:button", "Store")), 0121 KStandardGuiItem::discard()); 0122 if (answer == KMessageBox::ButtonCode::SecondaryAction) { 0123 return; 0124 } 0125 } 0126 } 0127 } 0128 MessageViewer::DKIMManagerKey::self()->addKey(info); 0129 } 0130 0131 void DKIMCheckFullJob::slotCheckAuthenticationStatusResult(const MessageViewer::DKIMAuthenticationStatusInfo &info) 0132 { 0133 // qDebug() << "info " << info; 0134 DKIMAuthenticationStatusInfoConverter converter; 0135 converter.setStatusInfo(info); 0136 // TODO Convert to CheckSignatureAuthenticationResult + add this list to CheckSignatureResult directly 0137 const QList<DKIMCheckSignatureJob::DKIMCheckSignatureAuthenticationResult> lst = converter.convert(); 0138 // qDebug() << " lst " << lst; 0139 // TODO use it. 0140 0141 // TODO check info ! if auth is ok not necessary to checkSignature 0142 if (mCheckPolicy.useOnlyAuthenticationResults()) { 0143 // Don't check signature if not necessary. 0144 } 0145 checkSignature(lst); 0146 } 0147 0148 void DKIMCheckFullJob::storeResult(const DKIMCheckSignatureJob::CheckSignatureResult &checkResult) 0149 { 0150 if (mCheckPolicy.saveDkimResult()) { 0151 if (checkResult.status == DKIMCheckSignatureJob::DKIMStatus::Valid || checkResult.status == DKIMCheckSignatureJob::DKIMStatus::Invalid 0152 || checkResult.status == DKIMCheckSignatureJob::DKIMStatus::NeedToBeSigned) { 0153 auto job = new DKIMStoreResultJob(this); 0154 job->setItem(mAkonadiItem); 0155 job->setResult(checkResult); 0156 job->start(); 0157 } 0158 } 0159 if (mCheckPolicy.autogenerateRule()) { 0160 if (mCheckPolicy.autogenerateRuleOnlyIfSenderInSDID()) { 0161 // TODO 0162 // FIXME Check value SDID ! 0163 generateRule(checkResult); 0164 } else { 0165 generateRule(checkResult); 0166 } 0167 } 0168 0169 qCDebug(MESSAGEVIEWER_DKIMCHECKER_LOG) << "result : status " << checkResult.status << " error : " << checkResult.error << " warning " 0170 << checkResult.warning; 0171 Q_EMIT result(checkResult, mAkonadiItem.id()); 0172 deleteLater(); 0173 } 0174 0175 void DKIMCheckFullJob::generateRule(const DKIMCheckSignatureJob::CheckSignatureResult &checkResult) 0176 { 0177 if (checkResult.status == DKIMCheckSignatureJob::DKIMStatus::Valid) { 0178 auto job = new DKIMGenerateRuleJob(this); 0179 job->setResult(checkResult); 0180 if (!job->start()) { 0181 qCWarning(MESSAGEVIEWER_DKIMCHECKER_LOG) << "Impossible to start autogenerate rule"; 0182 } 0183 } 0184 } 0185 0186 void DKIMCheckFullJob::slotCheckSignatureResult(const DKIMCheckSignatureJob::CheckSignatureResult &checkResult) 0187 { 0188 if (mCheckPolicy.checkIfEmailShouldBeSigned() && (checkResult.status == DKIMCheckSignatureJob::DKIMStatus::EmailNotSigned)) { 0189 auto job = new DKIMCheckPolicyJob(this); 0190 connect(job, &DKIMCheckPolicyJob::result, this, &DKIMCheckFullJob::storeResult); 0191 job->setCheckResult(checkResult); 0192 job->setEmailAddress(checkResult.fromEmail); 0193 if (!job->start()) { 0194 storeResult(checkResult); 0195 } 0196 } else { 0197 storeResult(checkResult); 0198 } 0199 } 0200 0201 #include "moc_dkimcheckfulljob.cpp"