Messagelib

dkimcheckfulljob.cpp
1 /*
2  SPDX-FileCopyrightText: 2019-2023 Laurent Montel <[email protected]>
3 
4  SPDX-License-Identifier: LGPL-2.0-or-later
5 */
6 
7 #include "dkimcheckfulljob.h"
8 #include "dkimauthenticationstatusinfoconverter.h"
9 #include "dkimcheckauthenticationstatusjob.h"
10 #include "dkimcheckpolicyjob.h"
11 #include "dkimgeneraterulejob.h"
12 #include "dkimmanagerkey.h"
13 #include "dkimstoreresultjob.h"
14 #include "messageviewer_dkimcheckerdebug.h"
15 #include <KLocalizedString>
16 #include <KMessageBox>
17 using namespace MessageViewer;
18 
19 DKIMCheckFullJob::DKIMCheckFullJob(QObject *parent)
20  : QObject(parent)
21 {
22 }
23 
24 DKIMCheckFullJob::~DKIMCheckFullJob() = default;
25 
26 DKIMCheckPolicy DKIMCheckFullJob::policy() const
27 {
28  return mCheckPolicy;
29 }
30 
31 void DKIMCheckFullJob::setPolicy(const DKIMCheckPolicy &policy)
32 {
33  mCheckPolicy = policy;
34 }
35 
36 void DKIMCheckFullJob::startCheckFullInfo(const Akonadi::Item &item)
37 {
38  if (!item.isValid()) {
39  deleteLater();
40  qCWarning(MESSAGEVIEWER_DKIMCHECKER_LOG) << "Invalid item";
41  return;
42  }
43  mAkonadiItem = item;
44  if (mAkonadiItem.hasPayload<KMime::Message::Ptr>()) {
45  mMessage = mAkonadiItem.payload<KMime::Message::Ptr>();
46  }
47  if (!mMessage) {
48  deleteLater();
49  qCWarning(MESSAGEVIEWER_DKIMCHECKER_LOG) << "Invalid message";
50  return;
51  }
52  checkAuthenticationResults();
53 }
54 
55 void DKIMCheckFullJob::checkAuthenticationResults()
56 {
57  if (mCheckPolicy.useAuthenticationResults()) {
58  auto job = new DKIMCheckAuthenticationStatusJob(this);
59  mHeaderParser.setHead(mMessage->head());
60  mHeaderParser.parse();
61  job->setHeaderParser(mHeaderParser);
62  job->setUseRelaxedParsing(mCheckPolicy.useRelaxedParsing());
63  connect(job, &DKIMCheckAuthenticationStatusJob::result, this, &DKIMCheckFullJob::slotCheckAuthenticationStatusResult);
64  job->start();
65  } else {
66  checkSignature();
67  }
68 }
69 
70 void DKIMCheckFullJob::checkSignature(const QVector<DKIMCheckSignatureJob::DKIMCheckSignatureAuthenticationResult> &lst)
71 {
72  auto job = new DKIMCheckSignatureJob(this);
73  connect(job, &DKIMCheckSignatureJob::storeKey, this, &DKIMCheckFullJob::storeKey);
74  connect(job, &DKIMCheckSignatureJob::result, this, &DKIMCheckFullJob::slotCheckSignatureResult);
75  job->setMessage(mMessage);
76  job->setHeaderParser(mHeaderParser);
77  job->setPolicy(mCheckPolicy);
78  job->setCheckSignatureAuthenticationResult(lst);
79  job->start();
80 }
81 
82 void DKIMCheckFullJob::startCheckFullInfo(const KMime::Message::Ptr &message)
83 {
84  mMessage = message;
85  if (!mMessage) {
86  deleteLater();
87  qCWarning(MESSAGEVIEWER_DKIMCHECKER_LOG) << "Invalid message";
88  return;
89  }
90  checkAuthenticationResults();
91 }
92 
93 void DKIMCheckFullJob::storeKey(const QString &key, const QString &domain, const QString &selector)
94 {
95  switch (mCheckPolicy.saveKey()) {
96  case MessageViewer::MessageViewerSettings::EnumSaveKey::NotSaving:
97  // Nothing
98  break;
99  case MessageViewer::MessageViewerSettings::EnumSaveKey::Save:
100  storeInKeyManager(key, selector, domain, false);
101  break;
102  case MessageViewer::MessageViewerSettings::EnumSaveKey::SaveAndCompare:
103  storeInKeyManager(key, selector, domain, true);
104  break;
105  }
106 }
107 
108 void DKIMCheckFullJob::storeInKeyManager(const QString &key, const QString &domain, const QString &selector, bool verify)
109 {
110  const MessageViewer::KeyInfo info{key, selector, domain, QDateTime::currentDateTime()};
111  if (verify) {
112  const QString keyStored = MessageViewer::DKIMManagerKey::self()->keyValue(selector, domain);
113  if (!keyStored.isEmpty()) {
114  if (keyStored != key) {
115  // qDebug() << "storeInKeyManager : keyStored " << keyStored << " key " << key;
116  // qDebug() << "domain " << domain << " selector " << selector;
117  const int answer = KMessageBox::warningTwoActions(nullptr,
118  i18n("Stored DKIM key is different from the current one. Do you want to store this one too?"),
119  i18n("Key Changed"),
120  KGuiItem(i18nc("@action:button", "Store")),
122  if (answer == KMessageBox::ButtonCode::SecondaryAction) {
123  return;
124  }
125  }
126  }
127  }
128  MessageViewer::DKIMManagerKey::self()->addKey(info);
129 }
130 
131 void DKIMCheckFullJob::slotCheckAuthenticationStatusResult(const MessageViewer::DKIMAuthenticationStatusInfo &info)
132 {
133  // qDebug() << "info " << info;
134  DKIMAuthenticationStatusInfoConverter converter;
135  converter.setStatusInfo(info);
136  // TODO Convert to CheckSignatureAuthenticationResult + add this list to CheckSignatureResult directly
138  // qDebug() << " lst " << lst;
139  // TODO use it.
140 
141  // TODO check info ! if auth is ok not necessary to checkSignature
142  if (mCheckPolicy.useOnlyAuthenticationResults()) {
143  // Don't check signature if not necessary.
144  }
145  checkSignature(lst);
146 }
147 
148 void DKIMCheckFullJob::storeResult(const DKIMCheckSignatureJob::CheckSignatureResult &checkResult)
149 {
150  if (mCheckPolicy.saveDkimResult()) {
151  if (checkResult.status == DKIMCheckSignatureJob::DKIMStatus::Valid || checkResult.status == DKIMCheckSignatureJob::DKIMStatus::Invalid
152  || checkResult.status == DKIMCheckSignatureJob::DKIMStatus::NeedToBeSigned) {
153  auto job = new DKIMStoreResultJob(this);
154  job->setItem(mAkonadiItem);
155  job->setResult(checkResult);
156  job->start();
157  }
158  }
159  if (mCheckPolicy.autogenerateRule()) {
160  if (mCheckPolicy.autogenerateRuleOnlyIfSenderInSDID()) {
161  // TODO
162  // FIXME Check value SDID !
163  generateRule(checkResult);
164  } else {
165  generateRule(checkResult);
166  }
167  }
168 
169  qCDebug(MESSAGEVIEWER_DKIMCHECKER_LOG) << "result : status " << checkResult.status << " error : " << checkResult.error << " warning "
170  << checkResult.warning;
171  Q_EMIT result(checkResult, mAkonadiItem.id());
172  deleteLater();
173 }
174 
175 void DKIMCheckFullJob::generateRule(const DKIMCheckSignatureJob::CheckSignatureResult &checkResult)
176 {
177  if (checkResult.status == DKIMCheckSignatureJob::DKIMStatus::Valid) {
178  auto job = new DKIMGenerateRuleJob(this);
179  job->setResult(checkResult);
180  if (!job->start()) {
181  qCWarning(MESSAGEVIEWER_DKIMCHECKER_LOG) << "Impossible to start autogenerate rule";
182  }
183  }
184 }
185 
186 void DKIMCheckFullJob::slotCheckSignatureResult(const DKIMCheckSignatureJob::CheckSignatureResult &checkResult)
187 {
188  if (mCheckPolicy.checkIfEmailShouldBeSigned() && (checkResult.status == DKIMCheckSignatureJob::DKIMStatus::EmailNotSigned)) {
189  auto job = new DKIMCheckPolicyJob(this);
190  connect(job, &DKIMCheckPolicyJob::result, this, &DKIMCheckFullJob::storeResult);
191  job->setCheckResult(checkResult);
192  job->setEmailAddress(checkResult.fromEmail);
193  if (!job->start()) {
194  storeResult(checkResult);
195  }
196  } else {
197  storeResult(checkResult);
198  }
199 }
bool isValid() const
QDateTime currentDateTime()
The KeyInfo struct.
The DKIMCheckPolicy class.
The DKIMCheckSignatureJob class.
The DKIMCheckPolicyJob class.
QString i18n(const char *text, const TYPE &arg...)
bool isEmpty() const const
ButtonCode warningTwoActions(QWidget *parent, const QString &text, const QString &title, const KGuiItem &primaryAction, const KGuiItem &secondaryAction, const QString &dontAskAgainName=QString(), Options options=Options(Notify|Dangerous))
QString i18nc(const char *context, const char *text, const TYPE &arg...)
T payload() const
QString message
KGuiItem discard()
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Mon Mar 27 2023 04:08:17 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.