diff --git a/server/autotests/infoparttest.cpp b/server/autotests/infoparttest.cpp index caf4532..1fb30c3 100644 --- a/server/autotests/infoparttest.cpp +++ b/server/autotests/infoparttest.cpp @@ -1,38 +1,37 @@ /* SPDX-FileCopyrightText: 2014-2024 Laurent Montel SPDX-License-Identifier: GPL-2.0-or-later */ #include "infoparttest.h" #include "../editor/part/infopart.h" #include InfoPartTest::InfoPartTest(QObject *parent) : QObject(parent) { } InfoPartTest::~InfoPartTest() = default; void InfoPartTest::shouldHaveDefaultValue() { MessageComposer::InfoPart infopart; - QCOMPARE(infopart.transportId(), 0); QVERIFY(!infopart.urgent()); QVERIFY(infopart.from().isEmpty()); QVERIFY(infopart.to().isEmpty()); QVERIFY(infopart.cc().isEmpty()); QVERIFY(infopart.bcc().isEmpty()); QVERIFY(infopart.replyTo().isEmpty()); QVERIFY(infopart.subject().isEmpty()); QVERIFY(infopart.fcc().isEmpty()); QVERIFY(infopart.userAgent().isEmpty()); QVERIFY(infopart.inReplyTo().isEmpty()); QVERIFY(infopart.references().isEmpty()); QVERIFY(infopart.extraHeaders().isEmpty()); } QTEST_MAIN(InfoPartTest) #include "moc_infoparttest.cpp" diff --git a/server/editor/job/skeletonmessagejob.cpp b/server/editor/job/skeletonmessagejob.cpp index a4bfbe2..70f51b5 100644 --- a/server/editor/job/skeletonmessagejob.cpp +++ b/server/editor/job/skeletonmessagejob.cpp @@ -1,280 +1,273 @@ /* SPDX-FileCopyrightText: 2009 Constantin Berzan SPDX-License-Identifier: LGPL-2.0-or-later */ #include "skeletonmessagejob.h" #include "jobbase_p.h" #include "messagecomposersettings.h" #include "../part/globalpart.h" #include "../part/infopart.h" #include #include #include "editor_debug.h" #include #include using namespace MessageComposer; class MessageComposer::SkeletonMessageJobPrivate : public JobBasePrivate { public: SkeletonMessageJobPrivate(SkeletonMessageJob *qq) : JobBasePrivate(qq) { } void doStart(); // slot InfoPart *infoPart = nullptr; GlobalPart *globalPart = nullptr; KMime::Message *message = nullptr; Q_DECLARE_PUBLIC(SkeletonMessageJob) }; void SkeletonMessageJobPrivate::doStart() { Q_Q(SkeletonMessageJob); Q_ASSERT(infoPart); Q_ASSERT(message == nullptr); message = new KMime::Message; // From: { auto from = new KMime::Headers::From; KMime::Types::Mailbox address; address.fromUnicodeString(KEmailAddress::normalizeAddressesAndEncodeIdn(infoPart->from())); from->fromUnicodeString(QString::fromLatin1(address.as7BitString("utf-8")), "utf-8"); message->setHeader(from); } // To: { auto to = new KMime::Headers::To; QByteArray sTo; const QStringList lstTo = infoPart->to(); for (const QString &a : lstTo) { KMime::Types::Mailbox address; address.fromUnicodeString(KEmailAddress::normalizeAddressesAndEncodeIdn(a)); if (!sTo.isEmpty()) { sTo.append(","); } sTo.append(address.as7BitString("utf-8")); } to->fromUnicodeString(QString::fromLatin1(sTo), "utf-8"); message->setHeader(to); } // Reply To: if (!infoPart->replyTo().isEmpty()) { auto replyTo = new KMime::Headers::ReplyTo; const QStringList lstReplyTo = infoPart->replyTo(); QByteArray sReplyTo; for (const QString &a : lstReplyTo) { KMime::Types::Mailbox address; address.fromUnicodeString(KEmailAddress::normalizeAddressesAndEncodeIdn(a)); if (!sReplyTo.isEmpty()) { sReplyTo.append(","); } sReplyTo.append(address.as7BitString("utf-8")); } replyTo->fromUnicodeString(QString::fromLatin1(sReplyTo), "utf-8"); message->setHeader(replyTo); } // Cc: { auto cc = new KMime::Headers::Cc; QByteArray sCc; const QStringList lstCc = infoPart->cc(); for (const QString &a : lstCc) { KMime::Types::Mailbox address; address.fromUnicodeString(KEmailAddress::normalizeAddressesAndEncodeIdn(a)); if (!sCc.isEmpty()) { sCc.append(","); } sCc.append(address.as7BitString("utf-8")); } cc->fromUnicodeString(QString::fromLatin1(sCc), "utf-8"); message->setHeader(cc); } // Bcc: { auto bcc = new KMime::Headers::Bcc; QByteArray sBcc; const QStringList lstBcc = infoPart->bcc(); for (const QString &a : lstBcc) { KMime::Types::Mailbox address; address.fromUnicodeString(KEmailAddress::normalizeAddressesAndEncodeIdn(a)); if (!sBcc.isEmpty()) { sBcc.append(","); } sBcc.append(address.as7BitString("utf-8")); } bcc->fromUnicodeString(QString::fromLatin1(sBcc), "utf-8"); message->setHeader(bcc); } // Subject: { auto subject = new KMime::Headers::Subject; subject->fromUnicodeString(infoPart->subject(), "utf-8"); // TODO should we be more specific about the charset? message->setHeader(subject); } // Date: { auto date = new KMime::Headers::Date; date->setDateTime(QDateTime::currentDateTime()); message->setHeader(date); } // Fcc: if (!infoPart->fcc().isEmpty()) { auto header = new KMime::Headers::Generic("X-KMail-Fcc"); header->fromUnicodeString(infoPart->fcc(), "utf-8"); message->setHeader(header); } - // Transport: - if (infoPart->transportId() > -1) { - auto header = new KMime::Headers::Generic("X-KMail-Transport"); - header->fromUnicodeString(QString::number(infoPart->transportId()), "utf-8"); - message->setHeader(header); - } - // Message-ID { auto messageId = new KMime::Headers::MessageID(); QByteArray fqdn; if (MessageComposer::MessageComposerSettings::self()->useCustomMessageIdSuffix()) { fqdn = QUrl::toAce(MessageComposer::MessageComposerSettings::self()->customMsgIDSuffix()); } if (fqdn.isEmpty()) { fqdn = QUrl::toAce(QHostInfo::localHostName()); } if (fqdn.isEmpty()) { qCWarning(EDITOR_LOG) << "Unable to generate a Message-ID, falling back to 'localhost.localdomain'."; fqdn = "local.domain"; } messageId->generate(fqdn); message->setHeader(messageId); } // Extras const KMime::Headers::Base::List extraHeaders = infoPart->extraHeaders(); for (KMime::Headers::Base *extra : extraHeaders) { const QByteArray headerType(extra->type()); auto copyHeader = KMime::Headers::createHeader(headerType); if (!copyHeader) { copyHeader = new KMime::Headers::Generic(headerType.constData(), headerType.size()); } copyHeader->from7BitString(extra->as7BitString(false)); message->setHeader(copyHeader); } // Request Delivery Confirmation { if (globalPart->requestDeleveryConfirmation()) { // TODO fix me multi address const QString addr = infoPart->replyTo().isEmpty() ? infoPart->from() : infoPart->replyTo().at(0); auto requestDeleveryConfirmation = new KMime::Headers::Generic("Return-Receipt-To"); requestDeleveryConfirmation->fromUnicodeString(addr, "utf-8"); message->setHeader(requestDeleveryConfirmation); } } // MDN { if (globalPart->MDNRequested()) { // TODO fix me multi address const QString addr = infoPart->replyTo().isEmpty() ? infoPart->from() : infoPart->replyTo().at(0); auto mdn = new KMime::Headers::Generic("Disposition-Notification-To"); mdn->fromUnicodeString(addr, "utf-8"); message->setHeader(mdn); } } // Urgent header if (infoPart->urgent()) { auto urg1 = new KMime::Headers::Generic("X-PRIORITY"); urg1->fromUnicodeString(QStringLiteral("2 (High)"), "utf-8"); auto urg2 = new KMime::Headers::Generic("Priority"); urg2->fromUnicodeString(QStringLiteral("urgent"), "utf-8"); message->setHeader(urg1); message->setHeader(urg2); } // In-Reply-To if (!infoPart->inReplyTo().isEmpty()) { auto header = new KMime::Headers::InReplyTo; header->fromUnicodeString(infoPart->inReplyTo(), "utf-8"); message->setHeader(header); } // References if (!infoPart->references().isEmpty()) { auto header = new KMime::Headers::References; header->fromUnicodeString(infoPart->references(), "utf-8"); message->setHeader(header); } q->emitResult(); // Success. } SkeletonMessageJob::SkeletonMessageJob(InfoPart *infoPart, GlobalPart *globalPart, QObject *parent) : JobBase(*new SkeletonMessageJobPrivate(this), parent) { Q_D(SkeletonMessageJob); d->infoPart = infoPart; d->globalPart = globalPart; } SkeletonMessageJob::~SkeletonMessageJob() = default; InfoPart *SkeletonMessageJob::infoPart() const { Q_D(const SkeletonMessageJob); return d->infoPart; } void SkeletonMessageJob::setInfoPart(InfoPart *part) { Q_D(SkeletonMessageJob); d->infoPart = part; } GlobalPart *SkeletonMessageJob::globalPart() const { Q_D(const SkeletonMessageJob); return d->globalPart; } void SkeletonMessageJob::setGlobalPart(GlobalPart *part) { Q_D(SkeletonMessageJob); d->globalPart = part; } KMime::Message *SkeletonMessageJob::message() const { Q_D(const SkeletonMessageJob); return d->message; } void SkeletonMessageJob::start() { Q_D(SkeletonMessageJob); d->doStart(); } #include "moc_skeletonmessagejob.cpp" diff --git a/server/editor/part/infopart.cpp b/server/editor/part/infopart.cpp index af7f86e..bd58789 100644 --- a/server/editor/part/infopart.cpp +++ b/server/editor/part/infopart.cpp @@ -1,209 +1,198 @@ /* SPDX-FileCopyrightText: 2009 Constantin Berzan SPDX-License-Identifier: LGPL-2.0-or-later */ #include "infopart.h" using namespace MessageComposer; class InfoPart::InfoPartPrivate { public: InfoPartPrivate() = default; KMime::Headers::Base::List extraHeaders; QStringList to; QStringList cc; QStringList bcc; QStringList replyTo; QString subject; QString from; QString fcc; QString userAgent; QString inReplyTo; QString references; - int transportId = 0; bool urgent = false; }; InfoPart::InfoPart(QObject *parent) : MessagePart(parent) , d(new InfoPartPrivate) { } InfoPart::~InfoPart() = default; QString InfoPart::from() const { return d->from; } void InfoPart::setFrom(const QString &from) { if (d->from == from) { return; } d->from = from; Q_EMIT fromChanged(); } QStringList InfoPart::to() const { return d->to; } void InfoPart::setTo(const QStringList &to) { if (d->to == to) { return; } d->to = to; Q_EMIT toChanged(); } QStringList InfoPart::cc() const { return d->cc; } void InfoPart::setCc(const QStringList &cc) { if (d->cc == cc) { return; } d->cc = cc; Q_EMIT ccChanged(); } QStringList InfoPart::bcc() const { return d->bcc; } void InfoPart::setBcc(const QStringList &bcc) { if (d->bcc == bcc) { return; } d->bcc = bcc; Q_EMIT bccChanged(); } QString InfoPart::subject() const { return d->subject; } void InfoPart::setSubject(const QString &subject) { if (d->subject == subject) { return; } d->subject = subject; Q_EMIT subjectChanged(); } QStringList InfoPart::replyTo() const { return d->replyTo; } void InfoPart::setReplyTo(const QStringList &replyTo) { if (d->replyTo == replyTo) { return; } d->replyTo = replyTo; Q_EMIT replyToChanged(); } -int InfoPart::transportId() const -{ - return d->transportId; -} - -void InfoPart::setTransportId(int tid) -{ - d->transportId = tid; -} - void InfoPart::setFcc(const QString &fcc) { if (d->fcc == fcc) { return; } d->fcc = fcc; Q_EMIT fccChanged(); } QString InfoPart::fcc() const { return d->fcc; } bool InfoPart::urgent() const { return d->urgent; } void InfoPart::setUrgent(bool urgent) { if (d->urgent == urgent) { return; } d->urgent = urgent; Q_EMIT urgentChanged(); } QString InfoPart::inReplyTo() const { return d->inReplyTo; } void InfoPart::setInReplyTo(const QString &inReplyTo) { if (d->inReplyTo == inReplyTo) { return; } d->inReplyTo = inReplyTo; Q_EMIT inReplyToChanged(); } QString InfoPart::references() const { return d->references; } void InfoPart::setReferences(const QString &references) { d->references = references; } void InfoPart::setExtraHeaders(const KMime::Headers::Base::List &headers) { d->extraHeaders = headers; } KMime::Headers::Base::List InfoPart::extraHeaders() const { return d->extraHeaders; } QString InfoPart::userAgent() const { return d->userAgent; } void InfoPart::setUserAgent(const QString &userAgent) { if (d->userAgent == userAgent) { return; } d->userAgent = userAgent; Q_EMIT userAgentChanged(); } #include "moc_infopart.cpp" diff --git a/server/editor/part/infopart.h b/server/editor/part/infopart.h index 4a19d9d..b74d832 100644 --- a/server/editor/part/infopart.h +++ b/server/editor/part/infopart.h @@ -1,112 +1,109 @@ /* SPDX-FileCopyrightText: 2009 Constantin Berzan SPDX-License-Identifier: LGPL-2.0-or-later */ #pragma once #include "messagepart.h" #include #include #include #include namespace MessageComposer { /** * @brief The InfoPart class contains the message header. */ class InfoPart : public MessageComposer::MessagePart { Q_OBJECT /// The email address and optionally the name of the author of the mail. Q_PROPERTY(QString from READ from WRITE setFrom NOTIFY fromChanged) /// The email address and optionally the name of the primary recipients. Q_PROPERTY(QStringList to READ to WRITE setTo NOTIFY toChanged) /// Carbon copy: The email address and optionally the name of the secondary recipients. Q_PROPERTY(QStringList cc READ cc WRITE setCc NOTIFY ccChanged) /// Blind Carbon copy: The email address and optionally the name of the secondary recipients. /// Only specified during SMTP delivery but not in the final mail delivery. Q_PROPERTY(QStringList bcc READ bcc WRITE setBcc NOTIFY bccChanged) /// Reply-To: Email address that should be used to reply to this mail. Q_PROPERTY(QStringList replyTo READ replyTo WRITE setReplyTo NOTIFY replyToChanged) /// Subject of the message. Q_PROPERTY(QString subject READ subject WRITE setSubject NOTIFY subjectChanged) /// The name of a file, to which a copy of the sent message should be appended. Q_PROPERTY(QString fcc READ fcc WRITE setFcc NOTIFY fccChanged) /// User agent of the sender. Q_PROPERTY(QString userAgent READ userAgent WRITE setUserAgent NOTIFY userAgentChanged) /// Set urgency of the message. Q_PROPERTY(bool urgent READ urgent WRITE setUrgent NOTIFY urgentChanged) /// In-Reply-To: Id of the message this message is a reply to. Q_PROPERTY(QString inReplyTo READ inReplyTo WRITE setInReplyTo NOTIFY inReplyToChanged) public: explicit InfoPart(QObject *parent = nullptr); ~InfoPart() override; [[nodiscard]] QString from() const; void setFrom(const QString &from); [[nodiscard]] QStringList to() const; void setTo(const QStringList &to); [[nodiscard]] QStringList cc() const; void setCc(const QStringList &cc); [[nodiscard]] QStringList bcc() const; void setBcc(const QStringList &bcc); [[nodiscard]] QStringList replyTo() const; void setReplyTo(const QStringList &replyTo); [[nodiscard]] QString subject() const; void setSubject(const QString &subject); [[nodiscard]] QString fcc() const; void setFcc(const QString &fcc); [[nodiscard]] QString userAgent() const; void setUserAgent(const QString &userAgent); [[nodiscard]] bool urgent() const; void setUrgent(bool); [[nodiscard]] QString inReplyTo() const; void setInReplyTo(const QString &inReplyTo); [[nodiscard]] QString references() const; void setReferences(const QString &references); void setExtraHeaders(const KMime::Headers::Base::List &headers); [[nodiscard]] KMime::Headers::Base::List extraHeaders() const; - [[nodiscard]] int transportId() const; - void setTransportId(int tid); - Q_SIGNALS: void toChanged(); void fromChanged(); void ccChanged(); void bccChanged(); void replyToChanged(); void subjectChanged(); void urgentChanged(); void userAgentChanged(); void inReplyToChanged(); void fccChanged(); private: class InfoPartPrivate; std::unique_ptr const d; }; } // namespace MessageComposer