File indexing completed on 2024-11-24 04:43:49
0001 /* 0002 SPDX-FileCopyrightText: 2015-2016 Krzysztof Nowicki <krissn@op.pl> 0003 0004 SPDX-License-Identifier: LGPL-2.0-or-later 0005 */ 0006 0007 #include "ewsfetchmaildetailjob.h" 0008 0009 #include <Akonadi/MessageFlags> 0010 #include <KMime/Message> 0011 0012 #include "ewsgetitemrequest.h" 0013 #include "ewsitemshape.h" 0014 #include "ewsmailbox.h" 0015 #include "ewsmailhandler.h" 0016 #include "ewsresource_debug.h" 0017 0018 using namespace Akonadi; 0019 0020 EwsFetchMailDetailJob::EwsFetchMailDetailJob(EwsClient &client, QObject *parent, const Akonadi::Collection &collection) 0021 : EwsFetchItemDetailJob(client, parent, collection) 0022 { 0023 EwsItemShape shape(EwsShapeIdOnly); 0024 shape << EwsPropertyField(QStringLiteral("item:Subject")); 0025 shape << EwsPropertyField(QStringLiteral("item:Importance")); 0026 shape << EwsPropertyField(QStringLiteral("message:From")); 0027 shape << EwsPropertyField(QStringLiteral("message:ToRecipients")); 0028 shape << EwsPropertyField(QStringLiteral("message:CcRecipients")); 0029 shape << EwsPropertyField(QStringLiteral("message:BccRecipients")); 0030 shape << EwsPropertyField(QStringLiteral("item:Categories")); 0031 shape << EwsPropertyField(QStringLiteral("item:DateTimeReceived")); 0032 shape << EwsPropertyField(QStringLiteral("item:InReplyTo")); 0033 shape << EwsPropertyField(QStringLiteral("message:References")); 0034 shape << EwsPropertyField(QStringLiteral("message:ReplyTo")); 0035 shape << EwsPropertyField(QStringLiteral("message:InternetMessageId")); 0036 shape << EwsPropertyField(QStringLiteral("item:Size")); 0037 const auto flagsProperties = EwsMailHandler::flagsProperties(); 0038 for (const EwsPropertyField &field : flagsProperties) { 0039 shape << field; 0040 } 0041 const auto tagsProperties = EwsItemHandler::tagsProperties(); 0042 for (const EwsPropertyField &field : tagsProperties) { 0043 shape << field; 0044 } 0045 mRequest->setItemShape(shape); 0046 } 0047 0048 EwsFetchMailDetailJob::~EwsFetchMailDetailJob() = default; 0049 0050 void EwsFetchMailDetailJob::processItems(const EwsGetItemRequest::Response::List &responses) 0051 { 0052 Item::List::iterator it = mChangedItems.begin(); 0053 0054 for (const EwsGetItemRequest::Response &resp : responses) { 0055 Item &item = *it; 0056 0057 if (!resp.isSuccess()) { 0058 qCWarningNC(EWSRES_LOG) << QStringLiteral("Failed to fetch item %1").arg(item.remoteId()); 0059 continue; 0060 } 0061 0062 const EwsItem &ewsItem = resp.item(); 0063 KMime::Message::Ptr msg(new KMime::Message); 0064 0065 // Rebuild the message headers 0066 QVariant v = ewsItem[EwsItemFieldSubject]; 0067 if (Q_LIKELY(v.isValid())) { 0068 msg->subject()->fromUnicodeString(v.toString(), "utf-8"); 0069 } 0070 0071 v = ewsItem[EwsItemFieldFrom]; 0072 if (Q_LIKELY(v.isValid())) { 0073 const auto mbox = v.value<EwsMailbox>(); 0074 msg->from()->addAddress(mbox); 0075 } 0076 0077 v = ewsItem[EwsItemFieldToRecipients]; 0078 if (Q_LIKELY(v.isValid())) { 0079 const auto mboxList = v.value<EwsMailbox::List>(); 0080 for (const EwsMailbox &mbox : mboxList) { 0081 msg->to()->addAddress(mbox); 0082 } 0083 } 0084 0085 v = ewsItem[EwsItemFieldCcRecipients]; 0086 if (Q_LIKELY(v.isValid())) { 0087 const auto mboxList = v.value<EwsMailbox::List>(); 0088 for (const EwsMailbox &mbox : mboxList) { 0089 msg->cc()->addAddress(mbox); 0090 } 0091 } 0092 0093 v = ewsItem[EwsItemFieldBccRecipients]; 0094 if (v.isValid()) { 0095 const auto mboxList = v.value<EwsMailbox::List>(); 0096 for (const EwsMailbox &mbox : mboxList) { 0097 msg->bcc()->addAddress(mbox); 0098 } 0099 } 0100 0101 v = ewsItem[EwsItemFieldInternetMessageId]; 0102 if (v.isValid()) { 0103 msg->messageID()->from7BitString(v.toString().toLatin1()); 0104 } 0105 0106 v = ewsItem[EwsItemFieldInReplyTo]; 0107 if (v.isValid()) { 0108 msg->inReplyTo()->from7BitString(v.toString().toLatin1()); 0109 } 0110 0111 v = ewsItem[EwsItemFieldDateTimeReceived]; 0112 if (v.isValid()) { 0113 msg->date()->setDateTime(v.toDateTime()); 0114 } 0115 0116 v = ewsItem[EwsItemFieldReferences]; 0117 if (v.isValid()) { 0118 msg->references()->from7BitString(v.toString().toLatin1()); 0119 } 0120 0121 v = ewsItem[EwsItemFieldReplyTo]; 0122 if (v.isValid()) { 0123 const auto mbox = v.value<EwsMailbox>(); 0124 msg->replyTo()->addAddress(mbox); 0125 } 0126 0127 msg->assemble(); 0128 item.setPayload(KMime::Message::Ptr(msg)); 0129 0130 v = ewsItem[EwsItemFieldSize]; 0131 if (v.isValid()) { 0132 item.setSize(v.toUInt()); 0133 } 0134 0135 // Workaround for Akonadi bug 0136 // When setting flags, adding each of them separately vs. setting a list in one go makes 0137 // a difference. In the former case the item treats this as an incremental change and 0138 // records flags added and removed. In the latter it sets a flag indicating that flags were 0139 // reset. 0140 // For some strange reason Akonadi is not seeing the flags in the latter case. 0141 const auto flags{EwsMailHandler::readFlags(ewsItem)}; 0142 for (const QByteArray &flag : flags) { 0143 item.setFlag(flag); 0144 } 0145 qCDebugNC(EWSRES_LOG) << "EwsFetchMailDetailJob::processItems:" << ewsHash(item.remoteId()) << item.flags(); 0146 0147 ++it; 0148 } 0149 0150 qCDebugNC(EWSRES_LOG) << "EwsFetchMailDetailJob::processItems: done"; 0151 0152 emitResult(); 0153 } 0154 0155 #include "moc_ewsfetchmaildetailjob.cpp"