File indexing completed on 2024-12-22 04:56:53

0001 /*
0002    SPDX-FileCopyrightText: 2013-2024 Laurent Montel <montel@kde.org>
0003 
0004    SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 #include "specialnotifierjob.h"
0008 #include "newmailnotifieragentsettings.h"
0009 #include "newmailnotifierreplymessagejob.h"
0010 #include "newmailnotifiershowmessagejob.h"
0011 
0012 #include <Akonadi/ContactSearchJob>
0013 #include <Akonadi/ItemDeleteJob>
0014 #include <Akonadi/ItemFetchJob>
0015 #include <Akonadi/ItemFetchScope>
0016 #include <Akonadi/MessageParts>
0017 
0018 #include <KEmailAddress>
0019 #include <KNotification>
0020 
0021 #include <KMime/Message>
0022 
0023 #include "newmailnotifier_debug.h"
0024 #include <KLocalizedString>
0025 
0026 SpecialNotifierJob::SpecialNotifierJob(const SpecialNotificationInfo &info, QObject *parent)
0027     : QObject(parent)
0028     , mSpecialNotificationInfo(info)
0029 {
0030     Akonadi::Item item(mSpecialNotificationInfo.itemId);
0031     auto job = new Akonadi::ItemFetchJob(item, this);
0032     job->fetchScope().fetchPayloadPart(Akonadi::MessagePart::Envelope, true);
0033 
0034     connect(job, &Akonadi::ItemFetchJob::result, this, &SpecialNotifierJob::slotItemFetchJobDone);
0035 }
0036 
0037 SpecialNotifierJob::~SpecialNotifierJob() = default;
0038 
0039 void SpecialNotifierJob::slotItemFetchJobDone(KJob *job)
0040 {
0041     if (job->error()) {
0042         qCWarning(NEWMAILNOTIFIER_LOG) << job->errorString();
0043         deleteLater();
0044         return;
0045     }
0046     const Akonadi::Item::List lst = qobject_cast<Akonadi::ItemFetchJob *>(job)->items();
0047     if (lst.count() == 1) {
0048         mItem = lst.first();
0049         if (!mItem.hasPayload<KMime::Message::Ptr>()) {
0050             qCDebug(NEWMAILNOTIFIER_LOG) << " message has not payload.";
0051             deleteLater();
0052             return;
0053         }
0054 
0055         const auto mb = mItem.payload<KMime::Message::Ptr>();
0056         mFrom = mb->from()->asUnicodeString();
0057         mSubject = mb->subject()->asUnicodeString();
0058         if (NewMailNotifierAgentSettings::showPhoto()) {
0059             auto searchJob = new Akonadi::ContactSearchJob(this);
0060             searchJob->setLimit(1);
0061             searchJob->setQuery(Akonadi::ContactSearchJob::Email, KEmailAddress::firstEmailAddress(mFrom).toLower(), Akonadi::ContactSearchJob::ExactMatch);
0062             connect(searchJob, &Akonadi::ItemFetchJob::result, this, &SpecialNotifierJob::slotSearchJobFinished);
0063         } else {
0064             emitNotification();
0065         }
0066     } else {
0067         qCWarning(NEWMAILNOTIFIER_LOG) << " Found item different from 1: " << lst.count();
0068         deleteLater();
0069         return;
0070     }
0071 }
0072 
0073 void SpecialNotifierJob::slotSearchJobFinished(KJob *job)
0074 {
0075     const Akonadi::ContactSearchJob *searchJob = qobject_cast<Akonadi::ContactSearchJob *>(job);
0076     if (searchJob->error()) {
0077         qCWarning(NEWMAILNOTIFIER_LOG) << "Unable to fetch contact:" << searchJob->errorText();
0078         emitNotification();
0079         return;
0080     }
0081     if (!searchJob->contacts().isEmpty()) {
0082         const KContacts::Addressee addressee = searchJob->contacts().at(0);
0083         const KContacts::Picture photo = addressee.photo();
0084         const QImage image = photo.data();
0085         if (image.isNull()) {
0086             emitNotification();
0087         } else {
0088             emitNotification(QPixmap::fromImage(image));
0089         }
0090     } else {
0091         emitNotification();
0092     }
0093 }
0094 
0095 void SpecialNotifierJob::emitNotification(const QPixmap &pixmap)
0096 {
0097     if (NewMailNotifierAgentSettings::excludeEmailsFromMe()) {
0098         for (const QString &email : std::as_const(mSpecialNotificationInfo.listEmails)) {
0099             if (mFrom.contains(email)) {
0100                 // Exclude this notification
0101                 deleteLater();
0102                 return;
0103             }
0104         }
0105     }
0106 
0107     QStringList result;
0108     if (NewMailNotifierAgentSettings::showFrom()) {
0109         result << i18n("From: %1", mFrom.toHtmlEscaped());
0110     }
0111     if (NewMailNotifierAgentSettings::showSubject()) {
0112         QString subject = mSubject.simplified();
0113         if (subject.length() > 80) {
0114             subject.truncate(80);
0115             subject += QStringLiteral("...");
0116         }
0117         result << i18n("Subject: %1", subject.toHtmlEscaped());
0118     }
0119     if (NewMailNotifierAgentSettings::showFolder()) {
0120         if (mSpecialNotificationInfo.resourceName.isEmpty()) {
0121             result << i18n("In: %1", mSpecialNotificationInfo.path);
0122         } else {
0123             result << i18n("In: %1 (%2)", mSpecialNotificationInfo.path, mSpecialNotificationInfo.resourceName);
0124         }
0125     }
0126 
0127     if (NewMailNotifierAgentSettings::textToSpeakEnabled()) {
0128         if (!NewMailNotifierAgentSettings::textToSpeak().isEmpty()) {
0129             QString message = NewMailNotifierAgentSettings::textToSpeak();
0130             message.replace(QLatin1StringView("%s"), mSubject.toHtmlEscaped());
0131             message.replace(QLatin1StringView("%f"), mFrom.toHtmlEscaped());
0132             Q_EMIT say(message);
0133         }
0134     }
0135 
0136     if (NewMailNotifierAgentSettings::showButtonToDisplayMail()) {
0137         auto notification =
0138             new KNotification(QStringLiteral("new-email"),
0139                               NewMailNotifierAgentSettings::keepPersistentNotification() ? KNotification::Persistent | KNotification::SkipGrouping
0140                                                                                          : KNotification::CloseOnTimeout);
0141         notification->setText(result.join(QLatin1Char('\n')));
0142         if (pixmap.isNull()) {
0143             notification->setIconName(mSpecialNotificationInfo.defaultIconName);
0144         } else {
0145             notification->setPixmap(pixmap);
0146         }
0147 
0148         auto showMailAction = notification->addAction(i18n("Show mail..."));
0149         connect(showMailAction, &KNotificationAction::activated, this, &SpecialNotifierJob::slotOpenMail);
0150 
0151         auto markAsReadAction = notification->addAction(i18n("Mark As Read"));
0152         connect(markAsReadAction, &KNotificationAction::activated, this, &SpecialNotifierJob::slotMarkAsRead);
0153 
0154         auto deleteAction = notification->addAction(i18n("Delete"));
0155         connect(deleteAction, &KNotificationAction::activated, this, &SpecialNotifierJob::slotDeleteMessage);
0156 
0157         if (NewMailNotifierAgentSettings::replyMail()) {
0158             QString replyLabel;
0159             switch (NewMailNotifierAgentSettings::replyMailType()) {
0160             case 0:
0161                 replyLabel = i18n("Reply to Author");
0162                 break;
0163             case 1:
0164                 replyLabel = i18n("Reply to All");
0165                 break;
0166             default:
0167                 qCWarning(NEWMAILNOTIFIER_LOG) << " Problem with NewMailNotifierAgentSettings::replyMailType() value: "
0168                                                << NewMailNotifierAgentSettings::replyMailType();
0169                 break;
0170             }
0171 
0172             auto replyAction = notification->addAction(replyLabel);
0173             connect(replyAction, &KNotificationAction::activated, this, &SpecialNotifierJob::slotReplyMessage);
0174         }
0175 
0176         connect(notification, &KNotification::closed, this, &SpecialNotifierJob::deleteLater);
0177 
0178         notification->sendEvent();
0179     } else {
0180         Q_EMIT displayNotification(pixmap, result.join(QStringLiteral("<br>")));
0181         deleteLater();
0182     }
0183 }
0184 
0185 void SpecialNotifierJob::slotReplyMessage()
0186 {
0187     auto job = new NewMailNotifierReplyMessageJob(mItem.id());
0188     job->setReplyToAll(NewMailNotifierAgentSettings::replyMailType() == 0 ? false : true);
0189     job->start();
0190     deleteLater();
0191 }
0192 
0193 void SpecialNotifierJob::slotDeleteMessage()
0194 {
0195     auto job = new Akonadi::ItemDeleteJob(mItem);
0196     connect(job, &Akonadi::ItemDeleteJob::result, this, &SpecialNotifierJob::deleteItemDone);
0197 }
0198 
0199 void SpecialNotifierJob::deleteItemDone(KJob *job)
0200 {
0201     if (job->error()) {
0202         qCWarning(NEWMAILNOTIFIER_LOG) << "SpecialNotifierJob::deleteItemDone error:" << job->errorString();
0203     }
0204     deleteLater();
0205 }
0206 
0207 void SpecialNotifierJob::slotMarkAsRead()
0208 {
0209     Akonadi::MessageStatus messageStatus;
0210     messageStatus.setRead(true);
0211     auto markAsReadAllJob = new Akonadi::MarkAsCommand(messageStatus, Akonadi::Item::List() << mItem);
0212     connect(markAsReadAllJob, &Akonadi::MarkAsCommand::result, this, &SpecialNotifierJob::slotMarkAsResult);
0213     markAsReadAllJob->execute();
0214 }
0215 
0216 void SpecialNotifierJob::slotMarkAsResult(Akonadi::MarkAsCommand::Result result)
0217 {
0218     switch (result) {
0219     case Akonadi::MarkAsCommand::Undefined:
0220         qCDebug(NEWMAILNOTIFIER_LOG) << "SpecialNotifierJob undefined result";
0221         break;
0222     case Akonadi::MarkAsCommand::OK:
0223         qCDebug(NEWMAILNOTIFIER_LOG) << "SpecialNotifierJob Done";
0224         break;
0225     case Akonadi::MarkAsCommand::Canceled:
0226         qCDebug(NEWMAILNOTIFIER_LOG) << "SpecialNotifierJob was canceled";
0227         break;
0228     case Akonadi::MarkAsCommand::Failed:
0229         qCDebug(NEWMAILNOTIFIER_LOG) << "SpecialNotifierJob was failed";
0230         break;
0231     }
0232     deleteLater();
0233 }
0234 
0235 void SpecialNotifierJob::slotOpenMail()
0236 {
0237     auto job = new NewMailNotifierShowMessageJob(mItem.id());
0238     job->start();
0239     deleteLater();
0240 }
0241 
0242 #include "moc_specialnotifierjob.cpp"