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"