7#include "messagepart.h"
8#include "cryptohelper.h"
9#include "job/qgpgmejobexecutor.h"
10#include "memento/compositememento.h"
11#include "memento/cryptobodypartmemento.h"
12#include "memento/decryptverifybodypartmemento.h"
13#include "memento/keycachememento.h"
14#include "memento/verifydetachedbodypartmemento.h"
15#include "memento/verifyopaquebodypartmemento.h"
16#include "mimetreeparser_debug.h"
17#include "objecttreeparser.h"
19#include "bodyformatter/utils.h"
21#include <KMime/Content>
23#include <Libkleo/Compliance>
24#include <Libkleo/KeyCache>
27#include <QGpgME/ImportJob>
28#include <QGpgME/Protocol>
29#include <QGpgME/VerifyDetachedJob>
30#include <QGpgME/VerifyOpaqueJob>
32#include <gpgme++/key.h>
33#include <gpgme++/keylistresult.h>
36#include <KLocalizedString>
40using namespace MimeTreeParser;
43namespace MimeTreeParser
45class MessagePartPrivate
53 PartMetaData mMetaData;
55 bool mIsImage =
false;
56 bool mNeverDisplayInline =
false;
62 , d(new MessagePartPrivate)
67MessagePart::~MessagePart() =
default;
71 return d->mParentPart;
74void MessagePart::setParentPart(
MessagePart *parentPart)
76 d->mParentPart = parentPart;
79QString MessagePart::htmlContent()
const
84QString MessagePart::plaintextContent()
const
89PartMetaData *MessagePart::partMetaData()
const
96 return nodeHelper()->bodyPartMemento(
content(),
"__plugin__");
101 nodeHelper()->setBodyPartMemento(
content(),
"__plugin__", memento);
116 return d->mAttachmentNode;
121 d->mAttachmentNode = node;
124bool MessagePart::isAttachment()
const
126 return d->mAttachmentNode;
136 return mOtp->nodeHelper()->asHREF(
content(), QStringLiteral(
"body"));
142 static int serial = 0;
146 return QStringLiteral(
"x-kmail:/bodypart/%1/%2/%3")
151void MessagePart::setIsRoot(
bool root)
156bool MessagePart::isRoot()
const
161QString MessagePart::text()
const
166void MessagePart::setText(
const QString &text)
171bool MessagePart::isHtml()
const
179 return mOtp->mSource;
185 return mOtp->nodeHelper();
188void MessagePart::parseInternal(
KMime::Content *node,
bool onlyOneMimePart)
190 auto subMessagePart = mOtp->parseObjectTreeInternal(node, onlyOneMimePart);
191 d->mRoot = subMessagePart->isRoot();
193 for (
const auto &part : subParts) {
198QString MessagePart::renderInternalText()
const
201 const auto subPartsLst = subParts();
202 for (
const auto &mp : subPartsLst) {
208void MessagePart::fix()
const
210 const auto subPartsLst = subParts();
211 for (
const auto &mp : subPartsLst) {
221 messagePart->setParentPart(
this);
222 d->mBlocks.append(messagePart);
230bool MessagePart::hasSubParts()
const
232 return !d->mBlocks.isEmpty();
235void MessagePart::clearSubParts()
240bool MessagePart::neverDisplayInline()
const
242 return d->mNeverDisplayInline;
245void MessagePart::setNeverDisplayInline(
bool displayInline)
247 d->mNeverDisplayInline = displayInline;
250bool MessagePart::isImage()
const
255void MessagePart::setIsImage(
bool image)
260bool MessagePart::hasHeader(
const char *headerType)
const
284MessagePartList::~MessagePartList() =
default;
286QString MessagePartList::text()
const
288 return renderInternalText();
291QString MessagePartList::plaintextContent()
const
296QString MessagePartList::htmlContent()
const
305 , mDecryptMessage(decryptMessage)
308 qCWarning(MIMETREEPARSER_LOG) <<
"not a valid node";
317TextMessagePart::~TextMessagePart() =
default;
319bool TextMessagePart::decryptMessage()
const
321 return mDecryptMessage;
324void TextMessagePart::parseContent()
326 const auto codecName = mOtp->codecNameFor(
content());
328 const QString &fromAddress = mOtp->nodeHelper()->fromAsString(
content());
329 mSignatureState = KMMsgNotSigned;
330 mEncryptionState = KMMsgNotEncrypted;
331 const auto blocks = prepareMessageForDecryption(
content()->decodedContent());
333 const auto cryptProto = QGpgME::openpgp();
335 if (!blocks.isEmpty()) {
343 bool fullySignedOrEncrypted =
true;
344 bool fullySignedOrEncryptedTmp =
true;
347 for (
const auto &block : blocks) {
349 if (!fullySignedOrEncryptedTmp) {
350 fullySignedOrEncrypted =
false;
353 if (block.type() == NoPgpBlock && !block.text().trimmed().isEmpty()) {
354 fullySignedOrEncryptedTmp =
false;
357 }
else if (block.type() == PgpMessageBlock) {
359 mp->setDecryptMessage(decryptMessage());
360 mp->setIsEncrypted(
true);
361 mp->setMementoName(mp->mementoName() +
"-" + nodeHelper()->asHREF(
content(),
QString::number(blockIndex)).toLocal8Bit());
363 if (!decryptMessage()) {
366 mp->startDecryption(block.text(), codecName);
367 if (mp->partMetaData()->inProgress) {
370 }
else if (block.type() == ClearsignedBlock) {
372 mp->setMementoName(mp->mementoName() +
"-" + nodeHelper()->asHREF(
content(),
QString::number(blockIndex)).toLocal8Bit());
374 mp->startVerification(block.text(), codecName);
380 const PartMetaData *messagePart(mp->partMetaData());
382 if (!messagePart->isEncrypted && !messagePart->isSigned && !block.text().trimmed().isEmpty()) {
384 mp->setText(aCodec.decode(block.text()));
387 if (messagePart->isEncrypted) {
388 mEncryptionState = KMMsgPartiallyEncrypted;
391 if (messagePart->isSigned) {
392 mSignatureState = KMMsgPartiallySigned;
397 if (fullySignedOrEncrypted) {
398 if (mSignatureState == KMMsgPartiallySigned) {
399 mSignatureState = KMMsgFullySigned;
401 if (mEncryptionState == KMMsgPartiallyEncrypted) {
402 mEncryptionState = KMMsgFullyEncrypted;
408KMMsgEncryptionState TextMessagePart::encryptionState()
const
410 return mEncryptionState;
413KMMsgSignatureState TextMessagePart::signatureState()
const
415 return mSignatureState;
418bool TextMessagePart::showLink()
const
423bool TextMessagePart::isFirstTextPart()
const
428bool TextMessagePart::hasLabel()
const
438 label =
i18nc(
"display name for an unnamed attachment",
"Unnamed");
446 if (comment == label()) {
464AttachmentMessagePart::~AttachmentMessagePart() =
default;
473 qCWarning(MIMETREEPARSER_LOG) <<
"not a valid node";
483HtmlMessagePart::~HtmlMessagePart() =
default;
485void HtmlMessagePart::fix()
const
487 mOtp->mHtmlContent += mBodyHTML;
490QString HtmlMessagePart::text()
const
495QString MimeTreeParser::HtmlMessagePart::plaintextContent()
const
500bool HtmlMessagePart::isHtml()
const
505QString HtmlMessagePart::bodyHtml()
const
514 , mOnlyOneMimePart(onlyOneMimePart)
517 qCWarning(MIMETREEPARSER_LOG) <<
"not a valid node";
522 parseInternal(node, mOnlyOneMimePart);
525MimeMessagePart::~MimeMessagePart() =
default;
527QString MimeMessagePart::text()
const
529 return renderInternalText();
532QString MimeMessagePart::plaintextContent()
const
537QString MimeMessagePart::htmlContent()
const
546 , mPreferredMode(preferredMode)
549 KMime::Content *dataIcal = findTypeInDirectChilds(node,
"text/calendar");
550 KMime::Content *dataHtml = findTypeInDirectChilds(node,
"text/html");
551 KMime::Content *dataText = findTypeInDirectChilds(node,
"text/plain");
558 dataHtml = findTypeInDirectChilds(node,
"multipart/related");
566 dataHtml = findTypeInDirectChilds(node,
"multipart/mixed");
582 if (mChildNodes.isEmpty()) {
583 qCWarning(MIMETREEPARSER_LOG) <<
"no valid nodes";
588 while (i.hasNext()) {
594AlternativeMessagePart::~AlternativeMessagePart() =
default;
598 return mPreferredMode;
601void AlternativeMessagePart::setPreferredMode(
Util::HtmlMode preferredMode)
603 mPreferredMode = preferredMode;
608 return mChildParts.keys();
611QString AlternativeMessagePart::text()
const
619void AlternativeMessagePart::fix()
const
625 const auto mode = preferredMode();
627 mChildParts[mode]->fix();
636bool AlternativeMessagePart::isHtml()
const
641QString AlternativeMessagePart::plaintextContent()
const
646QString AlternativeMessagePart::htmlContent()
const
651 return plaintextContent();
659 , mAutoImport(autoImport)
660 , mCryptoProto(cryptoProto)
663 qCWarning(MIMETREEPARSER_LOG) <<
"not a valid node";
674 QGpgME::ImportJob *
import = mCryptoProto->importJob();
676 mImportResult = executor.exec(
import, certData);
679CertMessagePart::~CertMessagePart() =
default;
681QString CertMessagePart::text()
const
686const GpgME::ImportResult &CertMessagePart::importResult()
const
688 return mImportResult;
694 const QGpgME::Protocol *cryptoProto,
698 , mCryptoProto(cryptoProto)
699 , mFromAddress(fromAddress)
700 , mMementoName(
"verification")
703 partMetaData()->technicalProblem = (mCryptoProto ==
nullptr);
704 partMetaData()->isSigned =
true;
705 partMetaData()->isGoodSignature =
false;
706 partMetaData()->status =
i18n(
"Wrong Crypto Plug-In.");
707 partMetaData()->status_code = GPGME_SIG_STAT_NONE;
710SignedMessagePart::~SignedMessagePart() =
default;
712void SignedMessagePart::setIsSigned(
bool isSigned)
714 partMetaData()->isSigned = isSigned;
717bool SignedMessagePart::isSigned()
const
719 return partMetaData()->isSigned;
722QByteArray SignedMessagePart::mementoName()
const
727void SignedMessagePart::setMementoName(
const QByteArray &name)
732static GpgME::Protocol toGpgMeProtocol(
const QGpgME::Protocol *protocol)
734 if (protocol == QGpgME::openpgp()) {
735 return GpgME::OpenPGP;
738 if (protocol == QGpgME::smime()) {
742 return GpgME::UnknownProtocol;
749 partMetaData()->isSigned =
false;
750 partMetaData()->technicalProblem = (mCryptoProto ==
nullptr);
751 partMetaData()->status =
i18n(
"Wrong Crypto Plug-In.");
752 partMetaData()->status_code = GPGME_SIG_STAT_NONE;
754 const QByteArray _mementoName = mementoName();
756 auto m =
dynamic_cast<CompositeMemento *
>(nodeHelper->bodyPartMemento(
content(), _mementoName));
757 Q_ASSERT(!m || mCryptoProto);
759 if (!m && mCryptoProto) {
760 CryptoBodyPartMemento *newM =
nullptr;
762 QGpgME::VerifyDetachedJob *job = mCryptoProto->verifyDetachedJob();
764 newM =
new VerifyDetachedBodyPartMemento(job, mCryptoProto->keyListJob(), signature, data);
767 QGpgME::VerifyOpaqueJob *job = mCryptoProto->verifyOpaqueJob();
769 newM =
new VerifyOpaqueBodyPartMemento(job, mCryptoProto->keyListJob(), data);
774 m =
new CompositeMemento();
776 m->addMemento(
new KeyCacheMemento(Kleo::KeyCache::mutableInstance(), toGpgMeProtocol(mCryptoProto)));
780 if (mOtp->allowAsync()) {
781 QObject::connect(m, &CryptoBodyPartMemento::update, nodeHelper, &NodeHelper::update);
783 partMetaData()->inProgress =
true;
784 mOtp->mHasPendingAsyncJobs =
true;
789 nodeHelper->setBodyPartMemento(
content(), _mementoName, m);
791 }
else if (m && m->isRunning()) {
792 partMetaData()->inProgress =
true;
793 mOtp->mHasPendingAsyncJobs =
true;
795 partMetaData()->inProgress =
false;
796 mOtp->mHasPendingAsyncJobs =
false;
799 if (m && !partMetaData()->inProgress) {
801 mVerifiedText = data;
803 setVerificationResult(m, textNode);
806 if (!m && !partMetaData()->inProgress) {
811 cryptPlugLibName = mCryptoProto->name();
812 cryptPlugDisplayName = mCryptoProto->displayName();
816 if (cryptPlugDisplayName.
isEmpty()) {
817 errorMsg =
i18n(
"No appropriate crypto plug-in was found.");
819 errorMsg =
i18nc(
"%1 is either 'OpenPGP' or 'S/MIME'",
"No %1 plug-in was found.", cryptPlugDisplayName);
822 errorMsg =
i18n(
"Crypto plug-in \"%1\" cannot verify signatures.", cryptPlugLibName);
824 partMetaData()->errorText =
i18n(
825 "The message is signed, but the "
826 "validity of the signature cannot be "
832 return partMetaData()->isSigned;
835QString prettifyDN(
const char *uid)
837 return QGpgME::DN(uid).prettyDN();
842 startVerificationDetached(text,
nullptr,
QByteArray());
844 if (!
content() && partMetaData()->isSigned) {
846 setText(codec.decode(mVerifiedText));
852 partMetaData()->isEncrypted =
false;
853 partMetaData()->isDecryptable =
false;
856 parseInternal(textNode,
false);
859 if (!okVerify(text, signature, textNode)) {
860 partMetaData()->creationTime =
QDateTime();
864void SignedMessagePart::setVerificationResult(
const CompositeMemento *m,
KMime::Content *textNode)
867 const auto kc = m->memento<KeyCacheMemento>();
869 mKeyCache = kc->keyCache();
873 const auto vm = m->memento<VerifyDetachedBodyPartMemento>();
875 mSignatures = vm->verifyResult().signatures();
876 partMetaData()->verificationResult = vm->verifyResult();
880 const auto vm = m->memento<VerifyOpaqueBodyPartMemento>();
882 mVerifiedText = vm->plainText();
883 mSignatures = vm->verifyResult().signatures();
884 partMetaData()->verificationResult = vm->verifyResult();
888 const auto vm = m->memento<DecryptVerifyBodyPartMemento>();
890 mVerifiedText = vm->plainText();
891 mSignatures = vm->verifyResult().signatures();
892 partMetaData()->verificationResult = vm->verifyResult();
895 partMetaData()->auditLogError = m->auditLogError();
896 partMetaData()->auditLog = m->auditLogAsHtml();
897 partMetaData()->isSigned = !mSignatures.empty();
899 if (partMetaData()->isSigned &&
content()) {
900 mOtp->nodeHelper()->setSignatureState(
content(), KMMsgFullySigned);
905 mOtp->nodeHelper()->setPartMetaData(
content(), *partMetaData());
907 if (!mVerifiedText.
isEmpty()) {
909 tempNode->setContent(KMime::CRLFtoLF(mVerifiedText.
constData()));
912 if (!tempNode->head().isEmpty()) {
913 tempNode->contentDescription()->from7BitString(
"signed data");
917 parseInternal(tempNode,
false);
922QString SignedMessagePart::plaintextContent()
const
925 return MessagePart::text();
931QString SignedMessagePart::htmlContent()
const
934 return MessagePart::text();
940const QGpgME::Protocol *SignedMessagePart::cryptoProto()
const
945QString SignedMessagePart::fromAddress()
const
950bool SignedMessagePart::hasHeader(
const char *headerType)
const
958const KMime::Headers::Base *MimeTreeParser::SignedMessagePart::header(
const char *headerType)
const
961 return content()->headerByType(headerType);
977 const QGpgME::Protocol *cryptoProto,
981 , mPassphraseError(false)
983 , mDecryptMessage(false)
984 , mCryptoProto(cryptoProto)
985 , mFromAddress(fromAddress)
986 , mMementoName(
"decryptverify")
989 partMetaData()->technicalProblem = (mCryptoProto ==
nullptr);
990 partMetaData()->isSigned =
false;
991 partMetaData()->isGoodSignature =
false;
992 partMetaData()->isEncrypted =
false;
993 partMetaData()->isDecryptable =
false;
994 partMetaData()->status =
i18n(
"Wrong Crypto Plug-In.");
995 partMetaData()->status_code = GPGME_SIG_STAT_NONE;
998EncryptedMessagePart::~EncryptedMessagePart() =
default;
1000void EncryptedMessagePart::setDecryptMessage(
bool decrypt)
1002 mDecryptMessage = decrypt;
1005bool EncryptedMessagePart::decryptMessage()
const
1007 return mDecryptMessage;
1010void EncryptedMessagePart::setIsEncrypted(
bool encrypted)
1012 partMetaData()->isEncrypted = encrypted;
1015bool EncryptedMessagePart::isEncrypted()
const
1017 return partMetaData()->isEncrypted;
1020bool EncryptedMessagePart::isDecryptable()
const
1022 return partMetaData()->isDecryptable;
1025bool EncryptedMessagePart::isNoSecKey()
const
1030bool EncryptedMessagePart::passphraseError()
const
1032 return mPassphraseError;
1035QByteArray EncryptedMessagePart::mementoName()
const
1037 return mMementoName;
1040void EncryptedMessagePart::setMementoName(
const QByteArray &name)
1042 mMementoName =
name;
1053 if (!partMetaData()->inProgress && partMetaData()->isDecryptable) {
1055 if (hasSubParts()) {
1056 auto _mp = (subParts()[0]).dynamicCast<SignedMessagePart>();
1058 _mp->setText(codec.decode(mDecryptedData));
1060 setText(codec.decode(mDecryptedData));
1063 setText(codec.decode(mDecryptedData));
1071 mPassphraseError =
false;
1072 partMetaData()->inProgress =
false;
1073 partMetaData()->errorText.
clear();
1074 partMetaData()->auditLogError = GpgME::Error();
1075 partMetaData()->auditLog.
clear();
1076 bool bDecryptionOk =
false;
1077 bool cannotDecrypt =
false;
1080 Q_ASSERT(decryptMessage());
1082 const QByteArray _mementoName = mementoName();
1084 const auto *m =
dynamic_cast<CompositeMemento *
>(nodeHelper->bodyPartMemento(&data, _mementoName));
1086 Q_ASSERT(!m || mCryptoProto);
1088 if (!m && mCryptoProto) {
1089 QGpgME::DecryptVerifyJob *job = mCryptoProto->decryptVerifyJob();
1091 cannotDecrypt =
true;
1094 auto newM =
new CompositeMemento();
1095 newM->addMemento(
new KeyCacheMemento(Kleo::KeyCache::mutableInstance(), toGpgMeProtocol(mCryptoProto)));
1096 newM->addMemento(
new DecryptVerifyBodyPartMemento(job, ciphertext));
1097 if (mOtp->allowAsync()) {
1098 QObject::connect(newM, &CryptoBodyPartMemento::update, nodeHelper, &NodeHelper::update);
1099 if (newM->start()) {
1100 partMetaData()->inProgress =
true;
1101 mOtp->mHasPendingAsyncJobs =
true;
1110 nodeHelper->setBodyPartMemento(&data, _mementoName, newM);
1112 }
else if (m && m->isRunning()) {
1113 partMetaData()->inProgress =
true;
1114 mOtp->mHasPendingAsyncJobs =
true;
1120 const auto *kcm = m->memento<KeyCacheMemento>();
1122 mKeyCache = kcm->keyCache();
1125 auto *decryptMemento = m->memento<DecryptVerifyBodyPartMemento>();
1126 const QByteArray &plainText = decryptMemento->plainText();
1127 const GpgME::DecryptionResult &decryptResult = decryptMemento->decryptResult();
1128 const GpgME::VerificationResult &verifyResult = decryptMemento->verifyResult();
1129 partMetaData()->isSigned = verifyResult.signatures().size() > 0;
1131 if (partMetaData()->isSigned) {
1133 subPart->setVerificationResult(m,
nullptr);
1134 appendSubPart(subPart);
1137 mDecryptRecipients.clear();
1138 bDecryptionOk = !decryptResult.error();
1144 for (
const auto &recipient : decryptResult.recipients()) {
1145 if (!recipient.status()) {
1146 bDecryptionOk =
true;
1149 key = mKeyCache->findByKeyIDOrFingerprint(recipient.keyID());
1151 auto ret = mKeyCache->findSubkeysByKeyID({recipient.keyID()});
1152 if (ret.size() == 1) {
1153 key = ret.front().parent();
1156 qCDebug(MIMETREEPARSER_LOG) <<
"Found no Key for KeyID " << recipient.keyID();
1159 mDecryptRecipients.emplace_back(recipient, key);
1162 if (!bDecryptionOk && partMetaData()->isSigned) {
1164 partMetaData()->isEncrypted =
false;
1165 bDecryptionOk =
true;
1166 mDecryptedData = plainText;
1168 mPassphraseError = decryptResult.error().isCanceled() || decryptResult.error().code() == GPG_ERR_NO_SECKEY;
1169 partMetaData()->isEncrypted = bDecryptionOk || decryptResult.error().code() != GPG_ERR_NO_DATA;
1171 if (decryptResult.error().isCanceled()) {
1172 setDecryptMessage(
false);
1176 if (Kleo::DeVSCompliance::isCompliant()) {
1177 partMetaData()->isCompliant = decryptResult.isDeVs();
1178 partMetaData()->compliance = Kleo::DeVSCompliance::name(decryptResult.isDeVs());
1180 partMetaData()->isCompliant =
true;
1182 if (partMetaData()->isEncrypted && decryptResult.numRecipients() > 0) {
1183 partMetaData()->keyId = decryptResult.recipient(0).keyID();
1186 if (bDecryptionOk) {
1187 mDecryptedData = plainText;
1190 const auto decryRecipients = decryptResult.recipients();
1191 for (
const GpgME::DecryptionResult::Recipient &recipient : decryRecipients) {
1192 mNoSecKey &= (recipient.status().code() == GPG_ERR_NO_SECKEY);
1194 if (!mPassphraseError && !mNoSecKey) {
1195 mPassphraseError =
true;
1201 if (!bDecryptionOk) {
1204 cryptPlugLibName = mCryptoProto->name();
1207 if (!mCryptoProto) {
1208 partMetaData()->errorText =
i18n(
"No appropriate crypto plug-in was found.");
1209 }
else if (cannotDecrypt) {
1210 partMetaData()->errorText =
i18n(
"Crypto plug-in \"%1\" cannot decrypt messages.", cryptPlugLibName);
1211 }
else if (!passphraseError()) {
1212 partMetaData()->errorText =
i18n(
"Crypto plug-in \"%1\" could not decrypt the data.", cryptPlugLibName) +
QLatin1StringView(
"<br />")
1213 +
i18n(
"Error: %1", partMetaData()->errorText);
1216 return bDecryptionOk;
1229 partMetaData()->isEncrypted =
true;
1231 bool bOkDecrypt = okDecryptMIME(*data);
1233 if (partMetaData()->inProgress) {
1236 partMetaData()->isDecryptable = bOkDecrypt;
1238 if (!partMetaData()->isDecryptable) {
1242 if (partMetaData()->isEncrypted && !decryptMessage()) {
1243 partMetaData()->isDecryptable =
true;
1246 if (
content() && !partMetaData()->isSigned) {
1247 mOtp->nodeHelper()->setPartMetaData(
content(), *partMetaData());
1249 if (decryptMessage()) {
1251 tempNode->setContent(KMime::CRLFtoLF(mDecryptedData.
constData()));
1254 if (!tempNode->head().isEmpty()) {
1255 tempNode->contentDescription()->from7BitString(
"encrypted data");
1259 parseInternal(tempNode,
false);
1264QString EncryptedMessagePart::plaintextContent()
const
1267 return MessagePart::text();
1273QString EncryptedMessagePart::htmlContent()
const
1276 return MessagePart::text();
1282QString EncryptedMessagePart::text()
const
1284 if (hasSubParts()) {
1285 auto _mp = (subParts()[0]).dynamicCast<SignedMessagePart>();
1289 return MessagePart::text();
1292 return MessagePart::text();
1296const QGpgME::Protocol *EncryptedMessagePart::cryptoProto()
const
1298 return mCryptoProto;
1301QString EncryptedMessagePart::fromAddress()
const
1303 return mFromAddress;
1306const std::vector<std::pair<GpgME::DecryptionResult::Recipient, GpgME::Key>> &EncryptedMessagePart::decryptRecipients()
const
1308 return mDecryptRecipients;
1311bool EncryptedMessagePart::hasHeader(
const char *headerType)
const
1313 const auto extraContent = mOtp->nodeHelper()->decryptedNodeForContent(
content());
1315 return nodeHelper()->hasMailHeader(headerType, extraContent);
1322 const auto extraContent = mOtp->nodeHelper()->decryptedNodeForContent(
content());
1324 return nodeHelper()->mailHeaderAsBase(headerType, extraContent);
1331 const auto extraContent = mOtp->nodeHelper()->decryptedNodeForContent(
content());
1333 return nodeHelper()->headers(headerType, extraContent);
1343 partMetaData()->isEncrypted =
false;
1344 partMetaData()->isSigned =
false;
1345 partMetaData()->isEncapsulatedRfc822Message =
true;
1347 mOtp->nodeHelper()->setNodeDisplayedEmbedded(node,
true);
1348 mOtp->nodeHelper()->setPartMetaData(node, *partMetaData());
1351 qCWarning(MIMETREEPARSER_LOG) <<
"Node is of type message/rfc822 but doesn't have a message!";
1359 parseInternal(message.
data(),
false);
1362EncapsulatedRfc822MessagePart::~EncapsulatedRfc822MessagePart() =
default;
1364QString EncapsulatedRfc822MessagePart::text()
const
1366 return renderInternalText();
1369void EncapsulatedRfc822MessagePart::fix()
const
1378#include "moc_messagepart.cpp"
const Headers::ContentType * contentType() const
ContentIndex index() const
QByteArray decodedContent() const
QList< Headers::Base * > headersByType(QByteArrayView type) const
bool hasHeader(QByteArrayView type) const
void setBody(const QByteArray &body)
const Headers::ContentDescription * contentDescription() const
The EncryptedMessagePart class.
interface of classes that implement status for BodyPartFormatters.
Interface for object tree sources.
The MessagePartList class.
KMime::Content * content() const
The KMime::Content* node that's represented by this part.
QString makeLink(const QString &path) const
Returns a string representation of an URL that can be used to invoke a BodyPartURLHandler for this bo...
KMime::Content * attachmentContent() const
The KMime::Content* node that's the source of this part.
QString attachmentLink() const
The MimeMessagePart class.
static QByteArray charset(const KMime::Content *node)
Returns the charset for the given node.
static QString fileName(const KMime::Content *node)
Returns a usable filename for a node, that can be the filename from the content disposition header,...
void attachExtraContent(KMime::Content *topLevelNode, KMime::Content *content)
Attach an extra node to an existing node.
QString writeNodeToTempFile(KMime::Content *node)
Writes the given message part to a temporary file and returns the name of this file or QString() if w...
Parses messages and generates HTML display code out of them.
Helper class for synchronous execution of Kleo crypto jobs.
The SignedMessagePart class.
The TextMessagePart class.
QString temporaryFilePath() const
Temporary file containing the part content.
QString i18nc(const char *context, const char *text, const TYPE &arg...)
QString i18n(const char *text, const TYPE &arg...)
QString name(StandardAction id)
HtmlMode
Describes the type of the displayed message.
@ MultipartPlain
A multipart/alternative message, the plain text part is currently displayed.
@ MultipartIcal
A multipart/alternative message, the ICal part is currently displayed.
@ MultipartHtml
A multipart/alternative message, the HTML part is currently displayed.
const char * constData() const const
bool isEmpty() const const
const_pointer constData() const const
QMetaObject::Connection connect(const QObject *sender, PointerToMemberFunction signal, Functor functor)
QString arg(Args &&... args) const const
QString fromLatin1(QByteArrayView str)
QString fromLocal8Bit(QByteArrayView str)
QString fromUtf8(QByteArrayView str)
bool isEmpty() const const
QString number(double n, char format, int precision)
EncodedData< QByteArrayView > decode(QByteArrayView ba)
QByteArray toPercentEncoding(const QString &input, const QByteArray &exclude, const QByteArray &include)