Commit 870dd3f1 authored by David Jarvie's avatar David Jarvie
Browse files

Move Akonadi dependent email send functions to the Akonadi plugin

parent 028b483f
Pipeline #166934 failed with stage
in 2 minutes and 1 second
......@@ -103,13 +103,13 @@ set_package_properties(KF5DocTools PROPERTIES DESCRIPTION
find_package(KF5IMAP ${KIMAP_LIB_VERSION} CONFIG REQUIRED)
find_package(KF5CalendarUtils ${CALENDARUTILS_LIB_VERSION} CONFIG REQUIRED)
find_package(KF5IdentityManagement ${IDENTITYMANAGEMENT_LIB_VERSION} CONFIG REQUIRED)
find_package(KF5MailTransportAkonadi ${KMAILTRANSPORT_LIB_VERSION} CONFIG REQUIRED)
find_package(KF5Mime ${KMIME_LIB_VERSION} CONFIG REQUIRED)
find_package(KF5PimTextEdit ${KPIMTEXTEDIT_LIB_VERSION} CONFIG REQUIRED)
if (ENABLE_AKONADI_PLUGIN)
find_package(KF5Akonadi ${AKONADI_VERSION} CONFIG REQUIRED)
find_package(KF5AkonadiContact ${AKONADI_CONTACT_VERSION} CONFIG REQUIRED)
find_package(KF5AkonadiMime ${AKONADI_MIMELIB_VERSION} CONFIG REQUIRED)
find_package(KF5MailTransportAkonadi ${KMAILTRANSPORT_LIB_VERSION} CONFIG REQUIRED)
endif()
configure_file(kalarm-version-string.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/kalarm-version-string.h @ONLY)
......
......@@ -4,14 +4,20 @@ Requirements
The following KDE packages must be installed in order to run KAlarm
successfully:
- Various KDE frameworks libraries
- Various KDE PIM libraries, notably kalarmcal
- kdepim-runtime: required for email alarms, and access to birthdays and
KOrganizer alarms and todos.
- Various KDE PIM libraries
KAlarm can use Akonadi if available, to provide email alarms, access to
birthdays, and KOrganizer alarms and todos. Akonadi functions are accessed
via KAlarm's Akonadi plugin, which is optionally built and installed when
KAlarm is built. The following KDE packages must be installed in order to
use KAlarm's Akonadi plugin:
- Various KDE PIM Akonadi libraries
- kdepim-runtime
The following optional packages enhance KAlarm if they are installed:
- Jovie (from kdeaccessibility): if installed and configured (together with
compatible speech synthesiser packages), it allows KAlarm to speak
alarm messages when alarms are displayed.
- Qt TextToSpeech: if installed and configured (together with compatible
speech synthesiser packages), it allows KAlarm to speak alarm
messages when alarms are displayed.
Setting up KAlarm on non-KDE desktops
=====================================
......
......@@ -56,8 +56,8 @@ LICENSES directory, for more details.
DESIGN
See DESIGN.html for some design information. Also see DESIGN.html in the
kalarmcal library for details of the alarm storage format.
See DESIGN.html for some design information. DESIGN-kalarmcalendar.html contains
details of the alarm storage format.
BUGS:
......
......@@ -313,6 +313,7 @@ target_link_libraries(kalarm_bin
KF5::GuiAddons
KF5::Holidays
KF5::IdleTime
KF5::ItemModels
KF5::KIOWidgets
KF5::Notifications
KF5::NotifyConfig
......@@ -327,8 +328,6 @@ target_link_libraries(kalarm_bin
KF5::Contacts
KF5::IdentityManagementWidgets
KF5::PimTextEdit
KF5::MailTransportAkonadi
KF5::MailTransport
KF5::Mime
)
......
......@@ -11,11 +11,13 @@ kcoreaddons_add_plugin(akonadiplugin
akonadiresourcemigrator.cpp
birthdaymodel.cpp
collectionattribute.cpp
sendakonadimail.cpp
akonadiplugin.h
akonadicollectionsearch.h
akonadiresourcemigrator.h
birthdaymodel.h
collectionattribute.h
sendakonadimail.h
INSTALL_NAMESPACE "kalarm"
)
......@@ -42,6 +44,7 @@ target_link_libraries(akonadiplugin
KF5::AkonadiMime
KF5::AkonadiContact
KF5::AkonadiWidgets
KF5::IdentityManagement
KF5::MailTransportAkonadi
KF5::MailTransport
)
......@@ -11,6 +11,7 @@
#include "akonadicollectionsearch.h"
#include "akonadiresourcemigrator.h"
#include "birthdaymodel.h"
#include "sendakonadimail.h"
#include "lib/autoqpointer.h"
#include "akonadiplugin_debug.h"
......@@ -79,6 +80,21 @@ int AkonadiPlugin::birthdayModelEnum(BirthdayModelValue value) const
}
}
/******************************************************************************
* Send an email via Akonadi.
*/
QString AkonadiPlugin::sendMail(KMime::Message::Ptr message, const KIdentityManagement::Identity& identity,
const QString normalizedFrom, bool keepSentMail, MailSend::JobData& jobdata)
{
if (!mSendAkonadiMail)
{
mSendAkonadiMail = SendAkonadiMail::instance();
connect(mSendAkonadiMail, &SendAkonadiMail::sent, this, &AkonadiPlugin::emailSent);
connect(mSendAkonadiMail, &SendAkonadiMail::queued, this, &AkonadiPlugin::emailQueued);
}
return mSendAkonadiMail->send(message, identity, normalizedFrom, keepSentMail, jobdata);
}
/******************************************************************************
* Extract dragged and dropped Akonadi RFC822 message data.
*/
......
......@@ -10,6 +10,8 @@
#include "pluginbase.h"
class SendAkonadiMail;
class AkonadiPlugin : public PluginBase
{
Q_OBJECT
......@@ -29,6 +31,12 @@ public:
/** Return BirthdayModel enum values. */
int birthdayModelEnum(BirthdayModelValue) const override;
/** Send an email using PIM libraries.
* @return empty string if sending initiated successfully, else error message.
*/
QString sendMail(KMime::Message::Ptr message, const KIdentityManagement::Identity& identity,
const QString normalizedFrom, bool keepSentMail, MailSend::JobData& jobdata) override;
/** Extract dragged and dropped Akonadi RFC822 message data.
* @param url the dropped URL.
* @param emailId updated with the Akonadi email ID.
......@@ -52,6 +60,9 @@ public:
* This should be called after the resource has been migrated.
*/
void deleteAkonadiResource(const QString& resourceName) override;
private:
SendAkonadiMail* mSendAkonadiMail {nullptr};
};
// vim: et sw=4:
/*
* sendakonadimail.cpp - sends email using MailTransport library
* Program: kalarm
* SPDX-FileCopyrightText: 2010-2022 David Jarvie <djarvie@kde.org>
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "sendakonadimail.h"
#include "mailsend.h"
#include "kalarmapp.h"
#include "akonadiplugin_debug.h"
#include <KIdentityManagement/Identity>
#include <MailTransport/TransportManager>
#include <MailTransport/Transport>
#include <MailTransportAkonadi/MessageQueueJob>
#include <KEmailAddress>
#include <KLocalizedString>
using namespace MailSend;
namespace
{
QStringList extractEmailsAndNormalize(const QString& emailAddresses);
}
SendAkonadiMail* SendAkonadiMail::mInstance = nullptr; // used only to enable signals/slots to work
QQueue<MailTransport::MessageQueueJob*> SendAkonadiMail::mJobs;
QQueue<JobData> SendAkonadiMail::mJobData;
SendAkonadiMail* SendAkonadiMail::instance()
{
if (!mInstance)
mInstance = new SendAkonadiMail();
return mInstance;
}
/******************************************************************************
* Send an email message.
* Reply = empty string if the message is queued for sending,
* = error message if the message was not sent.
*/
QString SendAkonadiMail::send(KMime::Message::Ptr message, const KIdentityManagement::Identity& identity,
const QString normalizedFrom, bool keepSentMail, JobData& jobdata)
{
qCDebug(AKONADIPLUGIN_LOG) << "SendAkonadiMail::send: Sending via KDE";
MailTransport::TransportManager* manager = MailTransport::TransportManager::self();
const int transportId = identity.transport().isEmpty() ? -1 : identity.transport().toInt();
MailTransport::Transport* transport = manager->transportById(transportId, true);
if (!transport)
{
qCCritical(AKONADIPLUGIN_LOG) << "SendAkonadiMail::send: No mail transport found for identity" << identity.identityName() << "uoid" << identity.uoid();
return xi18nc("@info", "No mail transport configured for email identity <resource>%1</resource>", identity.identityName());
}
qCDebug(AKONADIPLUGIN_LOG) << "SendAkonadiMail::send: Using transport" << transport->name() << ", id=" << transport->id();
auto mailjob = new MailTransport::MessageQueueJob(qApp);
mailjob->setMessage(message);
mailjob->transportAttribute().setTransportId(transport->id());
// MessageQueueJob email addresses must be pure, i.e. without display name. Note
// that display names are included in the actual headers set up in 'message'.
mailjob->addressAttribute().setFrom(normalizedFrom);
mailjob->addressAttribute().setTo(extractEmailsAndNormalize(jobdata.event.emailAddresses(QStringLiteral(","))));
if (!jobdata.bcc.isEmpty())
mailjob->addressAttribute().setBcc(extractEmailsAndNormalize(jobdata.bcc));
MailTransport::SentBehaviourAttribute::SentBehaviour sentAction =
keepSentMail ? MailTransport::SentBehaviourAttribute::MoveToDefaultSentCollection
: MailTransport::SentBehaviourAttribute::Delete;
mailjob->sentBehaviourAttribute().setSentBehaviour(sentAction);
mJobs.enqueue(mailjob);
mJobData.enqueue(jobdata);
if (mJobs.count() == 1)
{
// There are no jobs already active or queued, so send now
connect(mailjob, &KJob::result, instance(), &SendAkonadiMail::slotEmailSent);
mailjob->start();
}
return {};
}
/******************************************************************************
* Called when sending an email is complete.
*/
void SendAkonadiMail::slotEmailSent(KJob* job)
{
bool sendError = false;
QStringList errmsgs;
if (job->error())
{
qCCritical(AKONADIPLUGIN_LOG) << "SendAkonadiMail::slotEmailSent: Failed:" << job->errorString();
errmsgs += job->errorString();
sendError = true;
}
JobData jobdata;
if (mJobs.isEmpty() || mJobData.isEmpty() || job != std::as_const(mJobs).head())
{
// The queue has been corrupted, so we can't locate the job's data
qCCritical(AKONADIPLUGIN_LOG) << "SendAkonadiMail::slotEmailSent: Wrong job at head of queue: wiping queue";
mJobs.clear();
mJobData.clear();
if (!errmsgs.isEmpty())
Q_EMIT sent(jobdata, errmsgs, sendError);
errmsgs.clear();
errmsgs += i18nc("@info", "Emails may not have been sent");
errmsgs += i18nc("@info", "Program error");
Q_EMIT sent(jobdata, errmsgs, false);
return;
}
mJobs.dequeue();
jobdata = mJobData.dequeue();
if (jobdata.allowNotify)
Q_EMIT queued(jobdata.event);
Q_EMIT sent(jobdata, errmsgs, sendError);
if (!mJobs.isEmpty())
{
// Send the next queued email
auto job1 = mJobs.head();
connect(job1, &KJob::result, instance(), &SendAkonadiMail::slotEmailSent);
job1->start();
}
}
namespace
{
QStringList extractEmailsAndNormalize(const QString& emailAddresses)
{
const QStringList splitEmails(KEmailAddress::splitAddressList(emailAddresses));
QStringList normalizedEmail;
normalizedEmail.reserve(splitEmails.count());
for (const QString& email : splitEmails)
{
normalizedEmail << KEmailAddress::extractEmailAddress(KEmailAddress::normalizeAddressesAndEncodeIdn(email));
}
return normalizedEmail;
}
} // namespace
// vim: et sw=4:
/*
* sendakonadimail.h - sends email using MailTransport library
* Program: kalarm
* SPDX-FileCopyrightText: 2010-2022 David Jarvie <djarvie@kde.org>
*
* SPDX-License-Identifier: GPL-2.0-or-later
*/
#pragma once
#include "mailsend.h"
#include <KMime/Message>
#include <QObject>
#include <QQueue>
class QStringList;
class KJob;
namespace KIdentityManagement { class Identity; }
namespace MailTransport { class MessageQueueJob; }
namespace KAlarmCal { class KAEvent; }
class SendAkonadiMail : public QObject
{
Q_OBJECT
public:
static SendAkonadiMail* instance();
static QString send(KMime::Message::Ptr message, const KIdentityManagement::Identity& identity,
const QString normalizedFrom, bool keepSentMail, MailSend::JobData& jobdata);
Q_SIGNALS:
/** Emitted when a send job has been queued. */
void queued(const KAlarmCal::KAEvent&);
/** Emitted when an email has been sent, successfully or not.
* @param jobdata Job data supplied to send().
* @param errmsgs Error messages if an error occurred, else empty.
* @param sendError true if send failed.
*/
void sent(const MailSend::JobData&, const QStringList& errmsgs, bool sendError);
private Q_SLOTS:
void slotEmailSent(KJob*);
private:
SendAkonadiMail() = default;
static SendAkonadiMail* mInstance;
static QQueue<MailTransport::MessageQueueJob*> mJobs;
static QQueue<MailSend::JobData> mJobData;
};
// vim: et sw=4:
......@@ -184,9 +184,9 @@ SPDX-License-Identifier: GPL-2.0-or-later
<default code="true">QLatin1String("+")</default>
<emit signal="tooltipPreferencesChanged"/>
</entry>
<entry name="EmailClient" key="EmailClient" type="Enum">
<entry name="Base_EmailClient" key="EmailClient" type="Enum">
<label context="@label">Email client</label>
<whatsthis context="@info:whatsthis">&lt;p>How to send email when an email alarm is triggered.&lt;ul>&lt;li>KMail: The email is sent automatically via KMail. KMail is started first if necessary.&lt;/li>&lt;li>Sendmail: The email is sent automatically. This option will only work if your system is configured to use sendmail or a sendmail compatible mail transport agent.&lt;/li>&lt;/ul>&lt;/p></whatsthis>
<whatsthis context="@info:whatsthis">&lt;p>How to send email when an email alarm is triggered.&lt;ul>&lt;li>KMail: The email is sent automatically via KMail.&lt;/li>&lt;li>Sendmail: The email is sent automatically. This option will only work if your system is configured to use sendmail or a sendmail compatible mail transport agent.&lt;/li>&lt;/ul>&lt;/p></whatsthis>
<choices name="MailClient">
<choice name="sendmail"><label context="@option">Sendmail</label></choice>
<choice name="kmail"><label context="@option">KMail</label></choice>
......@@ -200,12 +200,12 @@ SPDX-License-Identifier: GPL-2.0-or-later
</entry>
<entry name="Base_EmailFrom" key="EmailFrom" type="String">
<label context="@label">'From' email address</label>
<whatsthis context="@info:whatsthis">Your email address, used to identify you as the sender when sending email alarms. Enter "@SystemSettings" to use the default email address set in KMail or System Settings, "@KMail" to allow choice of KMail identities, or enter the actual email address otherwise.</whatsthis>
<whatsthis context="@info:whatsthis">Your email address, used to identify you as the sender when sending email alarms. Enter "@SystemSettings" to use the default email address set in KMail, "@KMail" to allow choice of KMail identities, or enter the actual email address otherwise.</whatsthis>
<default code="true">KAlarmCal::Identities::identitiesExist() ? QLatin1String("@KMail") : QLatin1String("@SystemSettings")</default>
</entry>
<entry name="Base_EmailBccAddress" key="EmailBccAddress" type="String">
<label context="@label">'Bcc' email address</label>
<whatsthis context="@info:whatsthis">Your email address, used for blind copying email alarms to yourself. If you want blind copies to be sent to your account on the computer which KAlarm runs on, you can simply enter your user login name. Enter "@SystemSettings" to use the default email address set in KMail or System Settings, or enter the actual email address otherwise.</whatsthis>
<whatsthis context="@info:whatsthis">Your email address, used for blind copying email alarms to yourself. If you want blind copies to be sent to your account on the computer which KAlarm runs on, you can simply enter your user login name. Enter "@SystemSettings" to use the default email address set in KMail, or enter the actual email address otherwise.</whatsthis>
<default code="true">QLatin1String("@SystemSettings")</default>
</entry>
<entry name="Base_CmdXTermCommand" key="CmdXTerm" type="String">
......
......@@ -14,6 +14,8 @@
#include "displaycalendar.h"
#include "editdlgtypes.h"
#include "functions.h"
#include "kamail.h"
#include "mailsend.h"
#include "mainwindow.h"
#include "messagewindow.h"
#include "messagenotification.h"
......@@ -2370,7 +2372,7 @@ void* KAlarmApp::execAlarm(KAEvent& event, const KAAlarm& alarm, ExecAlarmFlags
{
qCDebug(KALARM_LOG) << "KAlarmApp::execAlarm: EMAIL to:" << event.emailAddresses(QStringLiteral(","));
QStringList errmsgs;
KAMail::JobData data(event, alarm, flags & Reschedule, flags & (Reschedule | AllowDefer));
MailSend::JobData data(event, alarm, flags & Reschedule, flags & (Reschedule | AllowDefer));
data.queued = true;
int ans = KAMail::send(data, errmsgs);
if (ans)
......@@ -2417,7 +2419,7 @@ void* KAlarmApp::execAlarm(KAEvent& event, const KAAlarm& alarm, ExecAlarmFlags
/******************************************************************************
* Called when sending an email has completed.
*/
void KAlarmApp::emailSent(KAMail::JobData& data, const QStringList& errmsgs, bool copyerr)
void KAlarmApp::emailSent(const MailSend::JobData& data, const QStringList& errmsgs, bool copyerr)
{
if (!errmsgs.isEmpty())
{
......
......@@ -11,7 +11,6 @@
/** @file kalarmapp.h - the KAlarm application object */
#include "eventid.h"
#include "kamail.h"
#include "preferences.h"
#include "kalarmcalendar/kaevent.h"
......@@ -20,6 +19,7 @@
#include <QQueue>
namespace KCal { class Event; }
namespace MailSend { struct JobData; }
class Resource;
class DBusHandler;
class MainWindow;
......@@ -119,7 +119,7 @@ public Q_SLOTS:
void notifyAudioStopped() { notifyAudioPlaying(false); }
void stopAudio();
void spreadWindows(bool);
void emailSent(KAMail::JobData&, const QStringList& errmsgs, bool copyerr = false);
void emailSent(const MailSend::JobData&, const QStringList& errmsgs, bool copyerr = false);
Q_SIGNALS:
void setExitValue(int); // set exit code for duplicate application instances
......
......@@ -12,18 +12,17 @@
#include "functions.h"
#include "kalarmapp.h"
#include "mainwindow.h"
#include "pluginmanager.h"
#include "preferences.h"
#include "lib/messagebox.h"
#include "kalarmcalendar/identities.h"
#include "akonadiplugin/akonadiplugin.h"
#include "kalarm_debug.h"
#include "kmailinterface.h"
#include <KIdentityManagement/IdentityManager>
#include <KIdentityManagement/Identity>
#include <MailTransport/TransportManager>
#include <MailTransport/Transport>
#include <MailTransportAkonadi/MessageQueueJob>
#include <KMime/HeaderParsing>
#include <KMime/Headers>
#include <KMime/Message>
......@@ -54,6 +53,8 @@
#define pclose _pclose
#endif
using namespace MailSend;
namespace HeaderParsing
{
bool parseAddress(const char* & scursor, const char* const send,
......@@ -62,10 +63,9 @@ bool parseAddress(const char* & scursor, const char* const send,
namespace
{
void initHeaders(KMime::Message&, KAMail::JobData&);
void initHeaders(KMime::Message&, JobData&);
KMime::Types::Mailbox::List parseAddresses(const QString& text, QString& invalidItem);
QString extractEmailAndNormalize(const QString& emailAddress);
QStringList extractEmailsAndNormalize(const QString& emailAddresses);
QByteArray autoDetectCharset(const QString& text);
const QTextCodec* codecForName(const QByteArray& str);
}
......@@ -76,9 +76,8 @@ QString KAMail::i18n_NeedFromEmailAddress()
QString KAMail::i18n_sent_mail()
{ return i18nc("@info KMail folder name: this should be translated the same as in kmail", "sent-mail"); }
KAMail* KAMail::mInstance = nullptr; // used only to enable signals/slots to work
QQueue<MailTransport::MessageQueueJob*> KAMail::mJobs;
QQueue<KAMail::JobData> KAMail::mJobData;
KAMail* KAMail::mInstance = nullptr; // used only to enable signals/slots to work
AkonadiPlugin* KAMail::mAkonadiPlugin = nullptr;
KAMail* KAMail::instance()
{
......@@ -203,20 +202,9 @@ int KAMail::send(JobData& jobdata, QStringList& errmsgs)
notifyQueued(jobdata.event);
return 1;
}
else
else if (PluginManager::instance()->akonadiPlugin())
{
qCDebug(KALARM_LOG) << "KAMail::send: Sending via KDE";
MailTransport::TransportManager* manager = MailTransport::TransportManager::self();
const int transportId = identity.transport().isEmpty() ? -1 : identity.transport().toInt();
MailTransport::Transport* transport = manager->transportById(transportId, true);
if (!transport)
{
qCCritical(KALARM_LOG) << "KAMail::send: No mail transport found for identity" << identity.identityName() << "uoid" << identity.uoid();
errmsgs = errors(xi18nc("@info", "No mail transport configured for email identity <resource>%1</resource>", identity.identityName()));
return -1;
}
qCDebug(KALARM_LOG) << "KAMail::send: Using transport" << transport->name() << ", id=" << transport->id();
initHeaders(*message, jobdata);
err = appendBodyAttachments(*message, jobdata);
if (!err.isNull())
......@@ -226,70 +214,32 @@ int KAMail::send(JobData& jobdata, QStringList& errmsgs)
return -1;
}
auto mailjob = new MailTransport::MessageQueueJob(qApp);
mailjob->setMessage(message);
mailjob->transportAttribute().setTransportId(transport->id());
// MessageQueueJob email addresses must be pure, i.e. without display name. Note
// that display names are included in the actual headers set up by initHeaders().
mailjob->addressAttribute().setFrom(extractEmailAndNormalize(jobdata.from));
mailjob->addressAttribute().setTo(extractEmailsAndNormalize(jobdata.event.emailAddresses(QStringLiteral(","))));
if (!jobdata.bcc.isEmpty())
mailjob->addressAttribute().setBcc(extractEmailsAndNormalize(jobdata.bcc));
MailTransport::SentBehaviourAttribute::SentBehaviour sentAction =
(Preferences::emailClient() == Preferences::kmail || Preferences::emailCopyToKMail())
? MailTransport::SentBehaviourAttribute::MoveToDefaultSentCollection : MailTransport::SentBehaviourAttribute::Delete;
mailjob->sentBehaviourAttribute().setSentBehaviour(sentAction);
mJobs.enqueue(mailjob);
mJobData.enqueue(jobdata);
if (mJobs.count() == 1)
if (!mAkonadiPlugin)
{
// There are no jobs already active or queued, so send now
connect(mailjob, &KJob::result, instance(), &KAMail::slotEmailSent);
mailjob->start();
mAkonadiPlugin = PluginManager::instance()->akonadiPlugin();
connect(mAkonadiPlugin, &AkonadiPlugin::emailSent, instance(), &KAMail::akonadiEmailSent);
connect(mAkonadiPlugin, &AkonadiPlugin::emailQueued, instance(), [](const KAEvent& e) { notifyQueued(e); });
}
const bool keepEmail = (Preferences::emailClient() == Preferences::kmail || Preferences::emailCopyToKMail());
err = mAkonadiPlugin->sendMail(message, identity, extractEmailAndNormalize(jobdata.from), keepEmail, jobdata);
if (!err.isEmpty())
{
errmsgs = errors(err);
return -1;
}
}
return 0;
}
/******************************************************************************
* Called when sending an email is complete.
* Called when sending an email via Akonadi is complete.
*/
void KAMail::slotEmailSent(KJob* job)
void KAMail::akonadiEmailSent(const JobData& jobdata, const QStringList& errmsgs, bool sendError)
{
bool copyerr = false;
QStringList errmsgs;
if (job->error())
{
qCCritical(KALARM_LOG) << "KAMail::slotEmailSent: Failed:" << job->errorString();
errmsgs = errors(job->errorString(), SEND_ERROR);
}
JobData jobdata;
if (mJobs.isEmpty() || mJobData.isEmpty() || job != std::as_const(mJobs).head())
{
// The queue has been corrupted, so we can't locate the job's data
qCCritical(KALARM_LOG) << "KAMail::slotEmailSent: Wrong job at head of queue: wiping queue";
mJobs.clear();
mJobData.clear();
if (!errmsgs.isEmpty())
theApp()->emailSent(jobdata, errmsgs);
errmsgs.clear();
errmsgs += i18nc("@info", "Emails may not have been sent");
errmsgs += i18nc("@info", "Program error");
theApp()->emailSent(jobdata, errmsgs);
return;
}
mJobs.dequeue();
jobdata = mJobData.dequeue();
if (jobdata.allowNotify)
notifyQueued(jobdata.event);
theApp()->emailSent(jobdata, errmsgs, copyerr);
if (!mJobs.isEmpty())
{
// Send the next queued email
auto job1 = mJobs.head();
connect(job1, &KJob::result, instance(), &KAMail::slotEmailSent);
job1->start();
}
QStringList messages = errmsgs;
if (!errmsgs.isEmpty() && sendError)
messages = errors(errmsgs.at(0), SEND_ERROR);
theApp()->emailSent(jobdata, messages);
}
/******************************************************************************
......@@ -608,7 +558,7 @@ namespace
/******************************************************************************
* Create the headers part of the email.
*/
void initHeaders(KMime::Message& message, KAMail::JobData& data)
void initHeaders(KMime::Message& message, JobData& data)
{
auto date = new KMime::Headers::Date;
date->setDateTime(KADateTime::currentDateTime(Preferences::timeSpec()).qDateTime());
......@@ -653,18 +603,6 @@ QString extractEmailAndNormalize(const QString& emailAddress)
return KEmailAddress::extractEmailAddress(KEmailAddress::normalizeAddressesAndEncodeIdn(emailAddress));
}
QStringList extractEmailsAndNormalize(const QString& emailAddresses)
{
const QStringList splitEmails(KEmailAddress::splitAddressList(emailAddresses));
QStringList normalizedEmail;