diff --git a/CMakeLists.txt b/CMakeLists.txt index 03928ee..21a68c0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,89 +1,85 @@ cmake_minimum_required(VERSION 3.0) set(PIM_VERSION "5.8.41") project(KSMTP VERSION ${PIM_VERSION}) # ECM setup set(KF5_VERSION "5.44.0") find_package(ECM ${KF5_VERSION} CONFIG REQUIRED) set(CMAKE_MODULE_PATH ${ECM_MODULE_PATH}) include(GenerateExportHeader) include(ECMGenerateHeaders) include(ECMGeneratePriFile) include(CMakePackageConfigHelpers) include(ECMSetupVersion) include(FeatureSummary) include(KDEInstallDirs) include(KDECMakeSettings) include(KDEFrameworkCompilerSettings NO_POLICY_SCOPE) include(ECMQtDeclareLoggingCategory) include(ECMCoverageOption) set(KSMTP_LIB_VERSION ${PIM_VERSION}) set(QT5_REQUIRED_VERSION "5.8.0") -set(KMIME_LIB_VERSION "5.8.0") ecm_setup_version(PROJECT VARIABLE_PREFIX KSMTP VERSION_HEADER ${KSMTP_BINARY_DIR}/ksmtp_version.h PACKAGE_VERSION_FILE ${KSMTP_BINARY_DIR}/KPimSMTPConfigVersion.cmake SOVERSION 5 ) ############ Find packages ############ find_package(Qt5Network ${QT_REQUIRED_VERSION} REQUIRED) find_package(KF5CoreAddons ${KF5_VERSION} CONFIG REQUIRED) find_package(KF5I18n ${KF5_VERSION} CONFIG REQUIRED) find_package(KF5KIO ${KF5_VERSION} CONFIG REQUIRED) -find_package(KF5Mime ${KMIME_LIB_VERSION} CONFIG REQUIRED) - - find_package(Sasl2) set_package_properties(Sasl2 PROPERTIES TYPE REQUIRED) ########### CMake Config Files ############ set(CMAKECONFIG_INSTALL_DIR "${KDE_INSTALL_CMAKEPACKAGEDIR}/KPimSMTP") configure_package_config_file( "${KSMTP_SOURCE_DIR}/KPimSMTPConfig.cmake.in" "${KSMTP_BINARY_DIR}/KPimSMTPConfig.cmake" INSTALL_DESTINATION ${CMAKECONFIG_INSTALL_DIR} ) add_definitions(-DTRANSLATION_DOMAIN=\"libksmtp5\") add_definitions(-DQT_DISABLE_DEPRECATED_BEFORE=0x060000) add_definitions(-DQT_NO_CAST_FROM_ASCII) add_definitions(-DQT_NO_CAST_TO_ASCII) add_definitions(-DQT_NO_NARROWING_CONVERSIONS_IN_CONNECT) ########### Targets ########### add_subdirectory(src) if (BUILD_TESTING) add_subdirectory(autotests) add_subdirectory(tests) endif () ########### Install Files ############ install(FILES "${KSMTP_BINARY_DIR}/KPimSMTPConfig.cmake" "${KSMTP_BINARY_DIR}/KPimSMTPConfigVersion.cmake" DESTINATION "${CMAKECONFIG_INSTALL_DIR}" COMPONENT Devel ) install(EXPORT KPimSMTPTargets DESTINATION "${CMAKECONFIG_INSTALL_DIR}" FILE KPimSMTPTargets.cmake NAMESPACE KPim::) install(FILES ${KSMTP_BINARY_DIR}/ksmtp_version.h DESTINATION ${KDE_INSTALL_INCLUDEDIR}/KPim COMPONENT Devel ) install(FILES ksmtp.categories DESTINATION ${KDE_INSTALL_CONFDIR}) feature_summary(WHAT ALL FATAL_ON_MISSING_REQUIRED_PACKAGES) diff --git a/KPimSMTPConfig.cmake.in b/KPimSMTPConfig.cmake.in index 5730769..36b28db 100644 --- a/KPimSMTPConfig.cmake.in +++ b/KPimSMTPConfig.cmake.in @@ -1,7 +1,6 @@ @PACKAGE_INIT@ include(CMakeFindDependencyMacro) find_dependency(KF5CoreAddons "@KF5_VERSION@") -find_dependency(KF5Mime "@KMIME_LIB_VERSION@") include("${CMAKE_CURRENT_LIST_DIR}/KPimSMTPTargets.cmake") diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 83c2bcb..0d1fb79 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,68 +1,67 @@ set(ksmtp_SRCS job.cpp loginjob.cpp sendjob.cpp session.cpp sessionthread.cpp sessionuiproxy.cpp ) ecm_qt_declare_logging_category(ksmtp_SRCS HEADER ksmtp_debug.h IDENTIFIER KSMTP_LOG CATEGORY_NAME org.kde.pim.ksmtp) add_library(KPimSMTP ${ksmtp_SRCS}) generate_export_header(KPimSMTP BASE_NAME ksmtp) add_library(KPim::SMTP ALIAS KPimSMTP) target_include_directories(KPimSMTP INTERFACE "$") if (WIN32) set(extra_LIBS ws2_32) endif() target_link_libraries(KPimSMTP PUBLIC - KF5::Mime KF5::CoreAddons PRIVATE KF5::I18n KF5::KIOCore Qt5::Network Sasl2::Sasl2 ${extra_LIBS} ) set_target_properties(KPimSMTP PROPERTIES VERSION ${KSMTP_VERSION_STRING} SOVERSION ${KSMTP_SOVERSION} EXPORT_NAME SMTP ) ecm_generate_headers(KSMTP_CamelCase_HEADERS HEADER_NAMES Job LoginJob SendJob Session SessionUiProxy PREFIX KSMTP REQUIRED_HEADERS KSMTP_HEADERS ) install(TARGETS KPimSMTP EXPORT KPimSMTPTargets ${KF5_INSTALL_TARGETS_DEFAULT_ARGS}) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/ksmtp_export.h ${KSMTP_HEADERS} DESTINATION ${KDE_INSTALL_INCLUDEDIR}/KPim/KSMTP/ksmtp ) install(FILES ${KSMTP_CamelCase_HEADERS} DESTINATION ${KDE_INSTALL_INCLUDEDIR}/KPim/KSMTP/KSMTP ) -ecm_generate_pri_file(BASE_NAME KSMTP LIB_NAME KPimSMTP DEPS "Mime" FILENAME_VAR PRI_FILENAME INCLUDE_INSTALL_DIR ${KDE_INSTALL_INCLUDEDIR}/KPim/KSMTP) +ecm_generate_pri_file(BASE_NAME KSMTP LIB_NAME KPimSMTP DEPS "" FILENAME_VAR PRI_FILENAME INCLUDE_INSTALL_DIR ${KDE_INSTALL_INCLUDEDIR}/KPim/KSMTP) install(FILES ${PRI_FILENAME} DESTINATION ${ECM_MKSPECS_INSTALL_DIR}) diff --git a/src/sendjob.cpp b/src/sendjob.cpp index ca4cb10..5b20a08 100644 --- a/src/sendjob.cpp +++ b/src/sendjob.cpp @@ -1,277 +1,234 @@ /* Copyright 2010 BetterInbox Author: Christophe Laveault Gregory Schlomoff This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library. If not, see . */ #include "sendjob.h" #include "job_p.h" #include "serverresponse_p.h" #include "ksmtp_debug.h" #include -#include namespace KSmtp { class SendJobPrivate : public JobPrivate { public: enum Status { Idle, SendingReturnPath, SendingRecipients, SendingData }; SendJobPrivate(SendJob *job, Session *session, const QString &name) : JobPrivate(session, name), q(job), m_status(Idle) { } SendJob *q = nullptr; void sendNextRecipient(); void addRecipients(const QStringList &rcpts); bool prepare(); typedef struct { QString contentType; QString name; QByteArray content; } MessagePart; QString m_returnPath; QStringList m_recipients; QByteArray m_data; - KMime::Message::Ptr m_message; - QStringList m_recipientsCopy; Status m_status; }; } using namespace KSmtp; SendJob::SendJob(Session *session) : Job(*new SendJobPrivate(this, session, i18n("SendJob"))) { } void SendJob::setFrom(const QString &from) { Q_D(SendJob); const auto start = from.indexOf(QLatin1Char('<')); if (start > -1) { const auto end = qMax(start, from.indexOf(QLatin1Char('>'), start)); d->m_returnPath = QStringLiteral("<%1>").arg(from.mid(start + 1, end - start - 1)); } else { d->m_returnPath = QStringLiteral("<%1>").arg(from); } } void SendJob::setTo(const QStringList &to) { Q_D(SendJob); d->addRecipients(to); } void SendJob::setCc(const QStringList &cc) { Q_D(SendJob); d->addRecipients(cc); } void SendJob::setBcc(const QStringList &bcc) { Q_D(SendJob); d->addRecipients(bcc); } void SendJob::setData(const QByteArray &data) { Q_D(SendJob); d->m_data = data; // A line with a single dot would make SMTP think "end of message", so use two dots in that case, // as per https://tools.ietf.org/html/rfc5321#section-4.5.2 d->m_data.replace("\r\n.", "\r\n.."); } void SendJob::doStart() { Q_D(SendJob); if (!d->prepare()) { setError(KJob::UserDefinedError); setErrorText(i18n("Could not send the message because either the sender or recipient field is missing or invalid")); emitResult(); return; } int sizeLimit = session()->sizeLimit(); if (sizeLimit > 0 && size() > sizeLimit) { setError(KJob::UserDefinedError); setErrorText(i18n("Could not send the message because it exceeds the maximum allowed size of %1 bytes. (Message size: %2 bytes.)", sizeLimit, size())); emitResult(); return; } d->m_status = SendJobPrivate::SendingReturnPath; sendCommand("MAIL FROM:" + d->m_returnPath.toUtf8()); } void SendJob::handleResponse(const ServerResponse &r) { Q_D(SendJob); // Handle server errors handleErrors(r); switch (d->m_status) { case SendJobPrivate::Idle: //TODO: anything to do here? break; case SendJobPrivate::SendingReturnPath: // Expected response: server agreement if (r.isCode(25)) { d->m_status = SendJobPrivate::SendingRecipients; d->sendNextRecipient(); } break; case SendJobPrivate::SendingRecipients: // Expected response: server agreement if (r.isCode(25)) { if (d->m_recipientsCopy.isEmpty()) { sendCommand("DATA"); d->m_status = SendJobPrivate::SendingData; } else { d->sendNextRecipient(); } } break; case SendJobPrivate::SendingData: // Expected responses: // 354: Go ahead sending data if (r.isCode(354)) { sendCommand(d->m_data); sendCommand("\r\n."); } // 25x: Data received correctly if (r.isCode(25)) { emitResult(); } break; } } void SendJobPrivate::sendNextRecipient() { q->sendCommand("RCPT TO:<" + m_recipientsCopy.takeFirst().toUtf8() + '>'); } void SendJobPrivate::addRecipients(const QStringList &rcpts) { for (const auto &rcpt : rcpts) { if (rcpt.isEmpty()) { continue; } const int start = rcpt.indexOf(QLatin1Char('<')); if (start > -1) { const int end = qMax(start, rcpt.indexOf(QLatin1Char('>'), start)); m_recipients.push_back(rcpt.mid(start + 1, end - start - 1)); } else { m_recipients.push_back(rcpt); } } } bool SendJobPrivate::prepare() { - if (!m_message && m_data.isEmpty()) { + if (m_data.isEmpty()) { qCWarning(KSMTP_LOG) << "A message has to be set before starting a SendJob"; return false; } - if (m_message) { - if (auto from = m_message->from(false)) { - if (from->isEmpty()) { - qCWarning(KSMTP_LOG) << "Message has no sender"; - return false; - } - } - - if (auto returnPath = m_message->headerByType("Return-Path")) { - m_returnPath = returnPath->asUnicodeString(); - } else { - m_returnPath = m_message->from(false)->asUnicodeString(); - if (m_returnPath.contains(QLatin1Char('<'))) { - m_returnPath = m_returnPath.split(QLatin1Char('<'))[1].split(QLatin1Char('>'))[0]; - } - m_returnPath = QStringLiteral("<%1>").arg(m_returnPath); - } - - if (auto to = m_message->to(false)) { - addRecipients(to->asUnicodeString().split(QStringLiteral(", "))); - } - if (auto cc = m_message->cc(false)) { - addRecipients(cc->asUnicodeString().split(QStringLiteral(", "))); - } - if (auto bcc = m_message->bcc(false)) { - addRecipients(bcc->asUnicodeString().split(QStringLiteral(", "))); - } - - m_data = m_message->encodedContent(); - } m_recipientsCopy = m_recipients; if (m_recipients.isEmpty()) { qCWarning(KSMTP_LOG) << "Message has no recipients"; return false; } return true; } -void SendJob::setMessage(const KMime::Message::Ptr &message) -{ - Q_D(SendJob); - d->m_message = message; -} - int SendJob::size() const { Q_D(const SendJob); - if (d->m_message) { - return d->m_message->encodedContent().size(); - } else { - return d->m_data.size(); - } + return d->m_data.size(); } diff --git a/src/sendjob.h b/src/sendjob.h index 66c0894..ad830cc 100644 --- a/src/sendjob.h +++ b/src/sendjob.h @@ -1,87 +1,78 @@ /* Copyright 2010 BetterInbox Author: Christophe Laveault Gregory Schlomoff This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library. If not, see . */ #ifndef KSMTP_SENDJOB_H #define KSMTP_SENDJOB_H #include "ksmtp_export.h" #include "job.h" -#include - namespace KSmtp { class SendJobPrivate; class KSMTP_EXPORT SendJob : public Job { Q_OBJECT Q_DECLARE_PRIVATE(SendJob) public: explicit SendJob(Session *session); /** * Set the sender email address */ void setFrom(const QString &from); /** * Add recipients. * */ void setTo(const QStringList &to); /** * Add recipients. */ void setCc(const QStringList &cc); /** * Add recipients. */ void setBcc(const QStringList &bcc); /** * Set the actual message data. */ void setData(const QByteArray &data); - /** - * Set a message. Sender, recipients and the data will be extracted - * from the message, so it is not necessary to call setFrom(), setTo(), - * etc. after this. - */ - void setMessage(const KMime::Message::Ptr &message); - /** * Returns size of the encoded message data. */ int size() const; protected: void doStart() override; void handleResponse(const ServerResponse &r) override; }; } #endif // KSMTP_SENDJOB_H