Messagelib

dmarcinfo.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 "dmarcinfo.h"
8 #include "messageviewer_dkimcheckerdebug.h"
9 
10 using namespace MessageViewer;
11 DMARCInfo::DMARCInfo() = default;
12 
13 bool DMARCInfo::parseDMARC(const QString &key)
14 {
15  if (key.isEmpty()) {
16  qCWarning(MESSAGEVIEWER_DKIMCHECKER_LOG) << "Error: key empty";
17  return false;
18  }
19  QString cleanKey = key;
20  cleanKey.replace(QLatin1String("; "), QLatin1String(";"));
21  const QStringList items = cleanKey.split(QLatin1Char(';'), Qt::SkipEmptyParts);
22  for (int i = 0; i < items.count(); ++i) {
23  const QString elem = items.at(i).trimmed();
24  if (elem.startsWith(QLatin1String("v="))) {
25  // v: Version (plain-text; REQUIRED). Identifies the record retrieved
26  // as a DMARC record. It MUST have the value of "DMARC1". The value
27  // of this tag MUST match precisely; if it does not or it is absent,
28  // the entire retrieved record MUST be ignored. It MUST be the first
29  // tag in the list.
30  mVersion = elem.right(elem.length() - 2);
31  } else if (elem.startsWith(QLatin1String("r="))) {
32  // adkim: (plain-text; OPTIONAL; default is "r".) Indicates whether
33  // strict or relaxed DKIM Identifier Alignment mode is required by
34  // the Domain Owner. See Section 3.1.1 for details. Valid values
35  // are as follows:
36  // r: relaxed mode
37  // s: strict mode
38  mAdkim = elem.right(elem.length() - 2);
39  } else if (elem.startsWith(QLatin1String("p="))) {
40  // p: Requested Mail Receiver policy (plain-text; REQUIRED for policy
41  // records). Indicates the policy to be enacted by the Receiver at
42  // the request of the Domain Owner. Policy applies to the domain
43  // queried and to subdomains, unless subdomain policy is explicitly
44  // described using the "sp" tag. This tag is mandatory for policy
45  // records only, but not for third-party reporting records (see
46  // Section 7.1). Possible values are as follows:
47 
48  // none: The Domain Owner requests no specific action be taken
49  // regarding delivery of messages.
50 
51  // quarantine: The Domain Owner wishes to have email that fails the
52  // DMARC mechanism check be treated by Mail Receivers as
53  // suspicious. Depending on the capabilities of the Mail
54  // Receiver, this can mean "place into spam folder", "scrutinize
55  // with additional intensity", and/or "flag as suspicious".
56 
57  // reject: The Domain Owner wishes for Mail Receivers to reject
58  // email that fails the DMARC mechanism check. Rejection SHOULD
59  // occur during the SMTP transaction. See Section 10.3 for some
60  // discussion of SMTP rejection methods and their implications.
61  mPolicy = elem.right(elem.length() - 2);
62  } else if (elem.startsWith(QLatin1String("ptc="))) {
63  // pct: (plain-text integer between 0 and 100, inclusive; OPTIONAL;
64  // default is 100). Percentage of messages from the Domain Owner's
65  // mail stream to which the DMARC policy is to be applied. However,
66  // this MUST NOT be applied to the DMARC-generated reports, all of
67  // which must be sent and received unhindered. The purpose of the
68  // "pct" tag is to allow Domain Owners to enact a slow rollout
69  // enforcement of the DMARC mechanism. The prospect of "all or
70  // nothing" is recognized as preventing many organizations from
71  // experimenting with strong authentication-based mechanisms. See
72  // Section 6.6.4 for details. Note that random selection based on
73  // this percentage, such as the following pseudocode, is adequate:
74 
75  // if (random mod 100) < pct then
76  // selected = true
77  // else
78  // selected = false
79  // TODO verify if it's a percentage
80  mPercentage = QStringView(elem).right(elem.length() - 4).toInt();
81  } else if (elem.startsWith(QLatin1String("sp="))) {
82  // sp: Requested Mail Receiver policy for all subdomains (plain-text;
83  // OPTIONAL). Indicates the policy to be enacted by the Receiver at
84  // the request of the Domain Owner. It applies only to subdomains of
85  // the domain queried and not to the domain itself. Its syntax is
86  // identical to that of the "p" tag defined above. If absent, the
87  // policy specified by the "p" tag MUST be applied for subdomains.
88  // Note that "sp" will be ignored for DMARC records published on
89  // subdomains of Organizational Domains due to the effect of the
90  // DMARC policy discovery mechanism described in Section 6.6.3.
91  mSubDomainPolicy = elem.right(elem.length() - 3);
92  }
93  }
94  if (mAdkim.isEmpty() && mVersion == QLatin1String("DMARC1")) {
95  mAdkim = QLatin1Char('r');
96  }
97 
98  return true;
99 }
100 
101 QString DMARCInfo::version() const
102 {
103  return mVersion;
104 }
105 
106 void DMARCInfo::setVersion(const QString &version)
107 {
108  mVersion = version;
109 }
110 
111 QString DMARCInfo::adkim() const
112 {
113  return mAdkim;
114 }
115 
116 void DMARCInfo::setAdkim(const QString &adkim)
117 {
118  mAdkim = adkim;
119 }
120 
121 QString DMARCInfo::policy() const
122 {
123  return mPolicy;
124 }
125 
126 void DMARCInfo::setPolicy(const QString &policy)
127 {
128  mPolicy = policy;
129 }
130 
131 int DMARCInfo::percentage() const
132 {
133  return mPercentage;
134 }
135 
136 void DMARCInfo::setPercentage(int percentage)
137 {
138  mPercentage = percentage;
139 }
140 
141 QString DMARCInfo::subDomainPolicy() const
142 {
143  return mSubDomainPolicy;
144 }
145 
146 void DMARCInfo::setSubDomainPolicy(const QString &subDomainPolicy)
147 {
148  mSubDomainPolicy = subDomainPolicy;
149 }
150 
151 bool DMARCInfo::operator==(const DMARCInfo &other) const
152 {
153  return mVersion == other.version() && mAdkim == other.adkim() && mPolicy == other.policy() && mSubDomainPolicy == other.subDomainPolicy()
154  && mPercentage == other.percentage();
155 }
156 
157 QDebug operator<<(QDebug d, const DMARCInfo &t)
158 {
159  d << " mVersion " << t.version();
160  d << " mAdkim " << t.adkim();
161  d << " mPolicy " << t.policy();
162  d << " mSubDomainPolicy " << t.subDomainPolicy();
163  d << " mPercentage " << t.percentage();
164  return d;
165 }
QStringView right(qsizetype length) const const
QStringList split(const QString &sep, QString::SplitBehavior behavior, Qt::CaseSensitivity cs) const const
int count(const T &value) const const
QDataStream & operator<<(QDataStream &out, const KDateTime &dateTime)
SkipEmptyParts
bool isEmpty() const const
The DMARCInfo class.
Definition: dmarcinfo.h:17
int length() const const
const T & at(int i) const const
QString & replace(int position, int n, QChar after)
bool startsWith(const QString &s, Qt::CaseSensitivity cs) const const
unsigned int version()
QString right(int n) const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Wed Mar 22 2023 04:07:14 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.