7 #include "dkimchecksignaturejob.h"
8 #include "dkimdownloadkeyjob.h"
10 #include "dkimkeyrecord.h"
11 #include "dkimmanagerkey.h"
13 #include "messageviewer_dkimcheckerdebug.h"
15 #include <KEmailAddress>
16 #include <QCryptographicHash>
19 #include <QRegularExpression>
24 using namespace MessageViewer;
25 DKIMCheckSignatureJob::DKIMCheckSignatureJob(
QObject *parent)
30 DKIMCheckSignatureJob::~DKIMCheckSignatureJob() =
default;
32 MessageViewer::DKIMCheckSignatureJob::CheckSignatureResult DKIMCheckSignatureJob::createCheckResult()
const
34 MessageViewer::DKIMCheckSignatureJob::CheckSignatureResult result;
35 result.error = mError;
36 result.warning = mWarning;
37 result.status = mStatus;
38 result.sdid = mDkimInfo.domain();
39 result.auid = mDkimInfo.agentOrUserIdentifier();
40 result.fromEmail = mFromEmail;
41 result.listSignatureAuthenticationResult = mCheckSignatureAuthenticationResult;
45 QString DKIMCheckSignatureJob::bodyCanonizationResult()
const
47 return mBodyCanonizationResult;
50 QString DKIMCheckSignatureJob::headerCanonizationResult()
const
52 return mHeaderCanonizationResult;
55 void DKIMCheckSignatureJob::start()
58 qCWarning(MESSAGEVIEWER_DKIMCHECKER_LOG) <<
"Item has not a message";
59 mStatus = MessageViewer::DKIMCheckSignatureJob::DKIMStatus::Invalid;
60 Q_EMIT result(createCheckResult());
64 if (
auto hrd = mMessage->headerByType(
"DKIM-Signature")) {
65 mDkimValue = hrd->asUnicodeString();
68 if (
auto hrd = mMessage->from(
false)) {
72 mStatus = MessageViewer::DKIMCheckSignatureJob::DKIMStatus::EmailNotSigned;
73 Q_EMIT result(createCheckResult());
77 qCDebug(MESSAGEVIEWER_DKIMCHECKER_LOG) <<
"mFromEmail " << mFromEmail;
78 if (!mDkimInfo.parseDKIM(mDkimValue)) {
79 qCWarning(MESSAGEVIEWER_DKIMCHECKER_LOG) <<
"Impossible to parse header" << mDkimValue;
80 mStatus = MessageViewer::DKIMCheckSignatureJob::DKIMStatus::Invalid;
81 Q_EMIT result(createCheckResult());
86 const MessageViewer::DKIMCheckSignatureJob::DKIMStatus status = checkSignature(mDkimInfo);
87 if (status != MessageViewer::DKIMCheckSignatureJob::DKIMStatus::Valid) {
89 Q_EMIT result(createCheckResult());
94 switch (mDkimInfo.bodyCanonization()) {
95 case MessageViewer::DKIMInfo::CanonicalizationType::Unknown:
96 mError = MessageViewer::DKIMCheckSignatureJob::DKIMError::InvalidBodyCanonicalization;
97 mStatus = MessageViewer::DKIMCheckSignatureJob::DKIMStatus::Invalid;
98 Q_EMIT result(createCheckResult());
101 case MessageViewer::DKIMInfo::CanonicalizationType::Simple:
102 mBodyCanonizationResult = bodyCanonizationSimple();
104 case MessageViewer::DKIMInfo::CanonicalizationType::Relaxed:
105 mBodyCanonizationResult = bodyCanonizationRelaxed();
110 if (mDkimInfo.bodyLengthCount() != -1) {
111 if (mDkimInfo.bodyLengthCount() > mBodyCanonizationResult.
length()) {
113 qCDebug(MESSAGEVIEWER_DKIMCHECKER_LOG) <<
" mDkimInfo.bodyLengthCount() " << mDkimInfo.bodyLengthCount() <<
" mBodyCanonizationResult.length() "
114 << mBodyCanonizationResult.
length();
115 mError = MessageViewer::DKIMCheckSignatureJob::DKIMError::SignatureTooLarge;
116 mStatus = MessageViewer::DKIMCheckSignatureJob::DKIMStatus::Invalid;
117 Q_EMIT result(createCheckResult());
120 }
else if (mDkimInfo.bodyLengthCount() < mBodyCanonizationResult.
length()) {
121 mWarning = MessageViewer::DKIMCheckSignatureJob::DKIMWarning::SignatureTooSmall;
124 mBodyCanonizationResult = mBodyCanonizationResult.
left(mDkimInfo.bodyLengthCount());
127 mBodyCanonizationResult = mBodyCanonizationResult.
right(mBodyCanonizationResult.
length() - 2);
131 mBodyCanonizationResult.
replace(QStringLiteral(
" This is a multi-part message in MIME format"),
132 QStringLiteral(
"This is a multi-part message in MIME format"));
135 if (mBodyCanonizationResult.
startsWith(
QLatin1String(
" This is a cryptographically signed message in MIME format."))) {
136 mBodyCanonizationResult.
replace(QStringLiteral(
" This is a cryptographically signed message in MIME format."),
137 QStringLiteral(
"This is a cryptographically signed message in MIME format."));
141 mBodyCanonizationResult.
remove(reg);
143 #ifdef DEBUG_SIGNATURE_DKIM
144 QFile caFile(QStringLiteral(
"/tmp/bodycanon-kmail.txt"));
147 outStream << mBodyCanonizationResult;
152 switch (mDkimInfo.hashingAlgorithm()) {
153 case DKIMInfo::HashingAlgorithmType::Sha1:
156 case DKIMInfo::HashingAlgorithmType::Sha256:
159 case DKIMInfo::HashingAlgorithmType::Any:
160 case DKIMInfo::HashingAlgorithmType::Unknown:
161 mError = MessageViewer::DKIMCheckSignatureJob::DKIMError::InsupportedHashAlgorithm;
162 mStatus = MessageViewer::DKIMCheckSignatureJob::DKIMStatus::Invalid;
163 Q_EMIT result(createCheckResult());
169 qDebug(MESSAGEVIEWER_DKIMCHECKER_LOG) <<
"resultHash " << resultHash <<
"mDkimInfo.bodyHash()" << mDkimInfo.bodyHash();
170 if (resultHash != mDkimInfo.bodyHash().
toLatin1()) {
171 qCWarning(MESSAGEVIEWER_DKIMCHECKER_LOG) <<
" Corrupted body hash";
172 mError = MessageViewer::DKIMCheckSignatureJob::DKIMError::CorruptedBodyHash;
173 mStatus = MessageViewer::DKIMCheckSignatureJob::DKIMStatus::Invalid;
174 Q_EMIT result(createCheckResult());
179 if (mDkimInfo.headerCanonization() == MessageViewer::DKIMInfo::CanonicalizationType::Unknown) {
180 mError = MessageViewer::DKIMCheckSignatureJob::DKIMError::InvalidHeaderCanonicalization;
181 mStatus = MessageViewer::DKIMCheckSignatureJob::DKIMStatus::Invalid;
182 Q_EMIT result(createCheckResult());
187 if (!mHeaderParser.wasAlreadyParsed()) {
188 mHeaderParser.setHead(mMessage->head());
189 mHeaderParser.parse();
192 computeHeaderCanonization(
true);
193 if (mPolicy.saveKey() == MessageViewer::MessageViewerSettings::EnumSaveKey::Save) {
194 const QString keyValue = MessageViewer::DKIMManagerKey::self()->keyValue(mDkimInfo.selector(), mDkimInfo.domain());
197 downloadKey(mDkimInfo);
199 parseDKIMKeyRecord(keyValue, mDkimInfo.domain(), mDkimInfo.selector(),
false);
200 MessageViewer::DKIMManagerKey::self()->updateLastUsed(mDkimInfo.domain(), mDkimInfo.selector());
203 downloadKey(mDkimInfo);
207 void DKIMCheckSignatureJob::computeHeaderCanonization(
bool removeQuoteOnContentType)
210 switch (mDkimInfo.headerCanonization()) {
211 case MessageViewer::DKIMInfo::CanonicalizationType::Unknown:
213 case MessageViewer::DKIMInfo::CanonicalizationType::Simple:
214 mHeaderCanonizationResult = headerCanonizationSimple();
216 case MessageViewer::DKIMInfo::CanonicalizationType::Relaxed:
217 mHeaderCanonizationResult = headerCanonizationRelaxed(removeQuoteOnContentType);
240 QString dkimValue = mDkimValue;
242 switch (mDkimInfo.headerCanonization()) {
243 case MessageViewer::DKIMInfo::CanonicalizationType::Unknown:
245 case MessageViewer::DKIMInfo::CanonicalizationType::Simple:
246 mHeaderCanonizationResult +=
QLatin1String(
"\r\n") + MessageViewer::DKIMUtil::headerCanonizationSimple(QStringLiteral(
"dkim-signature"), dkimValue);
248 case MessageViewer::DKIMInfo::CanonicalizationType::Relaxed:
249 mHeaderCanonizationResult +=
250 QLatin1String(
"\r\n") + MessageViewer::DKIMUtil::headerCanonizationRelaxed(QStringLiteral(
"dkim-signature"), dkimValue, removeQuoteOnContentType);
253 #ifdef DEBUG_SIGNATURE_DKIM
254 QFile headerFile(QStringLiteral(
"/tmp/headercanon-kmail-%1.txt").arg(removeQuoteOnContentType ?
QLatin1String(
"removequote") :
QLatin1String(
"withquote")));
257 outHeaderStream << mHeaderCanonizationResult;
262 void DKIMCheckSignatureJob::setHeaderParser(
const DKIMHeaderParser &headerParser)
264 mHeaderParser = headerParser;
269 mCheckSignatureAuthenticationResult = lst;
272 QString DKIMCheckSignatureJob::bodyCanonizationSimple()
const
289 return MessageViewer::DKIMUtil::bodyCanonizationSimple(
QString::fromLatin1(mMessage->encodedBody()));
292 QString DKIMCheckSignatureJob::bodyCanonizationRelaxed()
const
317 QString DKIMCheckSignatureJob::headerCanonizationSimple()
const
323 const auto listSignedHeader{mDkimInfo.listSignedHeader()};
324 for (
const QString &header : listSignedHeader) {
325 const QString str = parser.headerType(header.toLower());
330 headers += MessageViewer::DKIMUtil::headerCanonizationSimple(header, str);
336 QString DKIMCheckSignatureJob::headerCanonizationRelaxed(
bool removeQuoteOnContentType)
const
363 const auto listSignedHeader = mDkimInfo.listSignedHeader();
364 for (
const QString &header : listSignedHeader) {
365 const QString str = parser.headerType(header.toLower());
370 headers += MessageViewer::DKIMUtil::headerCanonizationRelaxed(header, str, removeQuoteOnContentType);
376 void DKIMCheckSignatureJob::downloadKey(
const DKIMInfo &info)
379 job->setDomainName(info.domain());
380 job->setSelectorName(info.selector());
381 connect(job, &DKIMDownloadKeyJob::error,
this, [
this](
const QString &errorString) {
382 qCWarning(MESSAGEVIEWER_DKIMCHECKER_LOG) <<
"Impossible to start downloadkey: error returned: " << errorString;
383 mError = MessageViewer::DKIMCheckSignatureJob::DKIMError::ImpossibleToDownloadKey;
384 mStatus = MessageViewer::DKIMCheckSignatureJob::DKIMStatus::Invalid;
385 Q_EMIT result(createCheckResult());
388 connect(job, &DKIMDownloadKeyJob::success,
this, &DKIMCheckSignatureJob::slotDownloadKeyDone);
391 qCWarning(MESSAGEVIEWER_DKIMCHECKER_LOG) <<
"Impossible to start downloadkey";
392 mError = MessageViewer::DKIMCheckSignatureJob::DKIMError::ImpossibleToDownloadKey;
393 mStatus = MessageViewer::DKIMCheckSignatureJob::DKIMStatus::Invalid;
394 Q_EMIT result(createCheckResult());
402 if (lst.
count() != 1) {
413 void DKIMCheckSignatureJob::parseDKIMKeyRecord(
const QString &str,
const QString &domain,
const QString &selector,
bool storeKeyValue)
415 qCDebug(MESSAGEVIEWER_DKIMCHECKER_LOG)
416 <<
"void DKIMCheckSignatureJob::parseDKIMKeyRecord(const QString &str, const QString &domain, const QString &selector, bool storeKeyValue) key:" << str;
417 if (!mDkimKeyRecord.parseKey(str)) {
418 qCWarning(MESSAGEVIEWER_DKIMCHECKER_LOG) <<
"Impossible to parse key record " << str;
419 mStatus = MessageViewer::DKIMCheckSignatureJob::DKIMStatus::Invalid;
420 Q_EMIT result(createCheckResult());
424 const QString keyType{mDkimKeyRecord.keyType()};
426 qCWarning(MESSAGEVIEWER_DKIMCHECKER_LOG) <<
"mDkimKeyRecord key type is unknown " << keyType <<
" str " << str;
427 mStatus = MessageViewer::DKIMCheckSignatureJob::DKIMStatus::Invalid;
428 Q_EMIT result(createCheckResult());
441 if (mDkimInfo.iDomain() != mDkimInfo.domain()) {
442 mStatus = MessageViewer::DKIMCheckSignatureJob::DKIMStatus::Invalid;
443 mError = MessageViewer::DKIMCheckSignatureJob::DKIMError::DomainI;
444 Q_EMIT result(createCheckResult());
453 if (!mPolicy.verifySignatureWhenOnlyTest()) {
454 qCWarning(MESSAGEVIEWER_DKIMCHECKER_LOG) <<
"Testing mode!";
455 mError = MessageViewer::DKIMCheckSignatureJob::DKIMError::TestKeyMode;
456 mStatus = MessageViewer::DKIMCheckSignatureJob::DKIMStatus::Invalid;
457 Q_EMIT result(createCheckResult());
462 if (mDkimKeyRecord.publicKey().
isEmpty()) {
464 qCWarning(MESSAGEVIEWER_DKIMCHECKER_LOG) <<
"mDkimKeyRecord public key is empty. It was revoked ";
465 mError = MessageViewer::DKIMCheckSignatureJob::DKIMError::PublicKeyWasRevoked;
466 mStatus = MessageViewer::DKIMCheckSignatureJob::DKIMStatus::Invalid;
467 Q_EMIT result(createCheckResult());
473 Q_EMIT storeKey(str, domain, selector);
479 void DKIMCheckSignatureJob::verifySignature()
481 const QString keyType{mDkimKeyRecord.keyType()};
483 verifyRSASignature();
485 verifyEd25519Signature();
487 qCWarning(MESSAGEVIEWER_DKIMCHECKER_LOG) <<
" It's a bug " << keyType;
491 void DKIMCheckSignatureJob::verifyEd25519Signature()
494 qCWarning(MESSAGEVIEWER_DKIMCHECKER_LOG) <<
"it's a Ed25519 signed email";
495 mError = MessageViewer::DKIMCheckSignatureJob::DKIMError::PublicKeyConversionError;
496 mStatus = MessageViewer::DKIMCheckSignatureJob::DKIMStatus::Invalid;
497 Q_EMIT result(createCheckResult());
501 void DKIMCheckSignatureJob::verifyRSASignature()
507 if (QCA::ConvertGood != conversionResult) {
508 qCWarning(MESSAGEVIEWER_DKIMCHECKER_LOG) <<
"Public key read failed" << conversionResult <<
" public key" << mDkimKeyRecord.publicKey();
509 mError = MessageViewer::DKIMCheckSignatureJob::DKIMError::PublicKeyConversionError;
510 mStatus = MessageViewer::DKIMCheckSignatureJob::DKIMStatus::Invalid;
511 Q_EMIT result(createCheckResult());
515 qDebug(MESSAGEVIEWER_DKIMCHECKER_LOG) <<
"Success loading public key";
522 const int publicRsaTooSmallPolicyValue = mPolicy.publicRsaTooSmallPolicy();
523 if (publicRsaTooSmallPolicyValue == MessageViewer::MessageViewerSettings::EnumPublicRsaTooSmall::Nothing) {
525 }
else if (publicRsaTooSmallPolicyValue == MessageViewer::MessageViewerSettings::EnumPublicRsaTooSmall::Warning) {
526 mWarning = MessageViewer::DKIMCheckSignatureJob::DKIMWarning::PublicRsaKeyTooSmall;
527 }
else if (publicRsaTooSmallPolicyValue == MessageViewer::MessageViewerSettings::EnumPublicRsaTooSmall::Error) {
528 mError = MessageViewer::DKIMCheckSignatureJob::DKIMError::PublicKeyTooSmall;
529 mStatus = MessageViewer::DKIMCheckSignatureJob::DKIMStatus::Invalid;
530 Q_EMIT result(createCheckResult());
545 switch (mDkimInfo.hashingAlgorithm()) {
546 case DKIMInfo::HashingAlgorithmType::Sha1:
549 case DKIMInfo::HashingAlgorithmType::Sha256:
552 case DKIMInfo::HashingAlgorithmType::Any:
553 case DKIMInfo::HashingAlgorithmType::Unknown: {
555 mError = MessageViewer::DKIMCheckSignatureJob::DKIMError::ImpossibleToVerifySignature;
556 mStatus = MessageViewer::DKIMCheckSignatureJob::DKIMStatus::Invalid;
557 Q_EMIT result(createCheckResult());
559 qCWarning(MESSAGEVIEWER_DKIMCHECKER_LOG) <<
"DKIMInfo::HashingAlgorithmType undefined ! ";
563 if (!rsaPublicKey.
verifyMessage(sec, ba, sigAlg, QCA::DERSequence)) {
564 computeHeaderCanonization(
false);
565 const QCA::SecureArray secWithoutQuote = mHeaderCanonizationResult.toLatin1();
566 if (!rsaPublicKey.
verifyMessage(secWithoutQuote, ba, sigAlg, QCA::DERSequence)) {
567 qCWarning(MESSAGEVIEWER_DKIMCHECKER_LOG) <<
"Signature invalid";
569 mError = MessageViewer::DKIMCheckSignatureJob::DKIMError::ImpossibleToVerifySignature;
570 mStatus = MessageViewer::DKIMCheckSignatureJob::DKIMStatus::Invalid;
571 Q_EMIT result(createCheckResult());
577 qCWarning(MESSAGEVIEWER_DKIMCHECKER_LOG) <<
"Impossible to verify signature";
578 mError = MessageViewer::DKIMCheckSignatureJob::DKIMError::ImpossibleToVerifySignature;
579 mStatus = MessageViewer::DKIMCheckSignatureJob::DKIMStatus::Invalid;
580 Q_EMIT result(createCheckResult());
584 mStatus = MessageViewer::DKIMCheckSignatureJob::DKIMStatus::Valid;
585 Q_EMIT result(createCheckResult());
599 DKIMCheckSignatureJob::DKIMWarning DKIMCheckSignatureJob::warning()
const
604 void DKIMCheckSignatureJob::setWarning(DKIMCheckSignatureJob::DKIMWarning warning)
619 MessageViewer::DKIMCheckSignatureJob::DKIMStatus DKIMCheckSignatureJob::checkSignature(
const DKIMInfo &info)
622 if (info.expireTime() != -1 && info.expireTime() < currentDate) {
623 mWarning = DKIMCheckSignatureJob::DKIMWarning::SignatureExpired;
625 if (info.signatureTimeStamp() != -1 && info.signatureTimeStamp() > currentDate) {
626 mWarning = DKIMCheckSignatureJob::DKIMWarning::SignatureCreatedInFuture;
628 if (info.signature().
isEmpty()) {
629 qCWarning(MESSAGEVIEWER_DKIMCHECKER_LOG) <<
"Signature doesn't exist";
630 mError = MessageViewer::DKIMCheckSignatureJob::DKIMError::MissingSignature;
631 return MessageViewer::DKIMCheckSignatureJob::DKIMStatus::Invalid;
634 qCWarning(MESSAGEVIEWER_DKIMCHECKER_LOG) <<
"From is not include in headers list";
635 mError = MessageViewer::DKIMCheckSignatureJob::DKIMError::MissingFrom;
636 return MessageViewer::DKIMCheckSignatureJob::DKIMStatus::Invalid;
639 qCWarning(MESSAGEVIEWER_DKIMCHECKER_LOG) <<
"Domain is not defined.";
640 mError = MessageViewer::DKIMCheckSignatureJob::DKIMError::DomainNotExist;
641 return MessageViewer::DKIMCheckSignatureJob::DKIMStatus::Invalid;
644 qCWarning(MESSAGEVIEWER_DKIMCHECKER_LOG) <<
"Query is incorrect: " << info.query();
645 mError = MessageViewer::DKIMCheckSignatureJob::DKIMError::InvalidQueryMethod;
646 return MessageViewer::DKIMCheckSignatureJob::DKIMStatus::Invalid;
649 if ((info.hashingAlgorithm() == MessageViewer::DKIMInfo::HashingAlgorithmType::Any)
650 || (info.hashingAlgorithm() == MessageViewer::DKIMInfo::HashingAlgorithmType::Unknown)) {
651 qCWarning(MESSAGEVIEWER_DKIMCHECKER_LOG) <<
"body header algorithm is empty";
652 mError = MessageViewer::DKIMCheckSignatureJob::DKIMError::InvalidBodyHashAlgorithm;
653 return MessageViewer::DKIMCheckSignatureJob::DKIMStatus::Invalid;
655 if (info.signingAlgorithm().
isEmpty()) {
656 qCWarning(MESSAGEVIEWER_DKIMCHECKER_LOG) <<
"signature algorithm is empty";
657 mError = MessageViewer::DKIMCheckSignatureJob::DKIMError::InvalidSignAlgorithm;
658 return MessageViewer::DKIMCheckSignatureJob::DKIMStatus::Invalid;
661 if (info.hashingAlgorithm() == DKIMInfo::HashingAlgorithmType::Sha1) {
662 if (mPolicy.rsaSha1Policy() == MessageViewer::MessageViewerSettings::EnumPolicyRsaSha1::Nothing) {
664 }
else if (mPolicy.rsaSha1Policy() == MessageViewer::MessageViewerSettings::EnumPolicyRsaSha1::Warning) {
665 qCWarning(MESSAGEVIEWER_DKIMCHECKER_LOG) <<
"hash algorithm is not secure sha1 : Error";
666 mWarning = MessageViewer::DKIMCheckSignatureJob::DKIMWarning::HashAlgorithmUnsafe;
667 }
else if (mPolicy.rsaSha1Policy() == MessageViewer::MessageViewerSettings::EnumPolicyRsaSha1::Error) {
668 qCWarning(MESSAGEVIEWER_DKIMCHECKER_LOG) <<
"hash algorithm is not secure sha1: Error";
669 mError = MessageViewer::DKIMCheckSignatureJob::DKIMError::HashAlgorithmUnsafeSha1;
670 return MessageViewer::DKIMCheckSignatureJob::DKIMStatus::Invalid;
675 if (!info.agentOrUserIdentifier().
endsWith(info.iDomain())) {
676 qCWarning(MESSAGEVIEWER_DKIMCHECKER_LOG) <<
"AUID is not in a subdomain of SDID";
677 mError = MessageViewer::DKIMCheckSignatureJob::DKIMError::IDomainError;
678 return MessageViewer::DKIMCheckSignatureJob::DKIMStatus::Invalid;
682 return MessageViewer::DKIMCheckSignatureJob::DKIMStatus::Valid;
685 DKIMCheckSignatureJob::DKIMError DKIMCheckSignatureJob::error()
const
690 DKIMCheckSignatureJob::DKIMStatus DKIMCheckSignatureJob::status()
const
695 void DKIMCheckSignatureJob::setStatus(DKIMCheckSignatureJob::DKIMStatus
status)
700 QString DKIMCheckSignatureJob::dkimValue()
const
705 bool DKIMCheckSignatureJob::CheckSignatureResult::isValid()
const
707 return status != DKIMCheckSignatureJob::DKIMStatus::Unknown;
710 bool DKIMCheckSignatureJob::CheckSignatureResult::operator==(
const DKIMCheckSignatureJob::CheckSignatureResult &other)
const
712 return error == other.error && warning == other.warning &&
status == other.status && fromEmail == other.fromEmail && auid == other.auid
713 && sdid == other.sdid && listSignatureAuthenticationResult == other.listSignatureAuthenticationResult;
716 bool DKIMCheckSignatureJob::CheckSignatureResult::operator!=(
const DKIMCheckSignatureJob::CheckSignatureResult &other)
const
718 return !CheckSignatureResult::operator==(other);
723 d <<
" error " << t.error;
724 d <<
" warning " << t.warning;
725 d <<
" status " << t.status;
726 d <<
" signedBy " << t.sdid;
727 d <<
" fromEmail " << t.fromEmail;
728 d <<
" auid " << t.auid;
729 d <<
" authenticationResult " << t.listSignatureAuthenticationResult;
735 d <<
" method " << t.method;
736 d <<
" errorStr " << t.errorStr;
737 d <<
" status " << t.status;
738 d <<
" sdid " << t.sdid;
739 d <<
" auid " << t.auid;
740 d <<
" inforesult " << t.infoResult;
744 bool DKIMCheckSignatureJob::DKIMCheckSignatureAuthenticationResult::operator==(
const DKIMCheckSignatureJob::DKIMCheckSignatureAuthenticationResult &other)
const
746 return errorStr == other.errorStr && method == other.method &&
status == other.status && sdid == other.sdid && auid == other.auid
747 && infoResult == other.infoResult;
750 bool DKIMCheckSignatureJob::DKIMCheckSignatureAuthenticationResult::isValid()
const
753 return (method != AuthenticationMethod::Unknown);