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"