diff --git a/CMakeLists.txt b/CMakeLists.txt index c95fbd1..14307de 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,68 +1,68 @@ cmake_minimum_required(VERSION 3.5) set(PIM_VERSION "5.11.40") project(MailTransport VERSION ${PIM_VERSION}) # ECM setup set(KF5_MIN_VERSION "5.56.0") find_package(ECM ${KF5_MIN_VERSION} CONFIG REQUIRED) set(CMAKE_MODULE_PATH ${ECM_MODULE_PATH}) include(GenerateExportHeader) include(ECMGenerateHeaders) include(ECMGeneratePriFile) include(ECMSetupVersion) include(FeatureSummary) include(KDEInstallDirs) include(KDECMakeSettings) include(KDEFrameworkCompilerSettings NO_POLICY_SCOPE) include(ECMQtDeclareLoggingCategory) add_definitions(-DTRANSLATION_DOMAIN=\"libmailtransport5\") set(KMAILTRANSPORT_LIB_VERSION ${PIM_VERSION}) set(KMIME_LIB_VERSION "5.11.40") set(AKONADI_LIB_VERSION "5.11.40") set(AKONADIMIME_LIB_VERSION "5.11.40") set(KSMTP_LIB_VERSION "5.11.40") set(KGAPI_LIB_VERSION "5.11.40") set(CMAKECONFIG_INSTALL_DIR "${KDE_INSTALL_CMAKEPACKAGEDIR}/KF5MailTransport") ########### Find packages ########### find_package(KF5KCMUtils ${KF5_MIN_VERSION} CONFIG REQUIRED) find_package(KF5ConfigWidgets ${KF5_MIN_VERSION} CONFIG REQUIRED) find_package(KF5Wallet ${KF5_MIN_VERSION} CONFIG REQUIRED) find_package(KF5I18n ${KF5_MIN_VERSION} CONFIG REQUIRED) find_package(KF5KIO ${KF5_MIN_VERSION} CONFIG REQUIRED) find_package(KF5Mime ${KMIME_LIB_VERSION} CONFIG REQUIRED) find_package(KF5Akonadi ${AKONADI_LIB_VERSION} CONFIG REQUIRED) find_package(KF5AkonadiMime ${AKONADIMIME_LIB_VERSION} CONFIG REQUIRED) find_package(KPimSMTP ${KSMTP_LIB_VERSION} CONFIG REQUIRED) find_package(KPimGAPI ${KGAPI_LIB_VERSION} CONFIG REQUIRED) option(KDEPIM_RUN_AKONADI_TEST "Enable autotest based on Akonadi." TRUE) # workaround for https://bugreports.qt.io/browse/QTBUG-74665 (bug in qt5.13 reevaluate it) if (${Qt5Widgets_VERSION} STRGREATER "5.13") MESSAGE(STATUS "Qt version: ${Qt5Widgets_VERSION} DISABLE compile without deprecated methods. bug QTBUG-74665") else() add_definitions(-DQT_DISABLE_DEPRECATED_BEFORE=0x060000) endif() if (${KF5Config_VERSION} STRGREATER "5.56.0") add_definitions(-DQT_NO_FOREACH) MESSAGE(STATUS "compile without foreach") endif() - +set(CMAKE_CXX_STANDARD 14) if(BUILD_TESTING) add_definitions(-DBUILD_TESTING) endif(BUILD_TESTING) ########### Targets ########### add_subdirectory(src) install( FILES kmailtransport.renamecategories kmailtransport.categories DESTINATION ${KDE_INSTALL_CONFDIR} ) feature_summary(WHAT ALL FATAL_ON_MISSING_REQUIRED_PACKAGES) diff --git a/src/kmailtransport/plugins/smtp/smtpconfigwidget.cpp b/src/kmailtransport/plugins/smtp/smtpconfigwidget.cpp index 608d51c..31fd244 100644 --- a/src/kmailtransport/plugins/smtp/smtpconfigwidget.cpp +++ b/src/kmailtransport/plugins/smtp/smtpconfigwidget.cpp @@ -1,369 +1,369 @@ /* Copyright (c) 2009 Constantin Berzan Based on MailTransport code by: Copyright (c) 2006 - 2007 Volker Krause Copyright (c) 2007 KovoKs Based on KMail code by: Copyright (c) 2001-2002 Michael Haeckel This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "smtpconfigwidget.h" #include "ui_smtpsettings.h" #include "widgets/transportconfigwidget_p.h" #include "transport.h" #include "transportmanager.h" #include "servertest.h" #include "mailtransport_defs.h" #include "mailtransportplugin_smtp_debug.h" #include #include #include #include "mailtransport_debug.h" #include using namespace MailTransport; class MailTransport::SMTPConfigWidgetPrivate : public TransportConfigWidgetPrivate { public: ::Ui::SMTPSettings ui; ServerTest *serverTest = nullptr; QButtonGroup *encryptionGroup = nullptr; // detected authentication capabilities QVector noEncCapa, sslCapa, tlsCapa; bool serverTestFailed; static void addAuthenticationItem(QComboBox *combo, int authenticationType) { combo->addItem(Transport::authenticationTypeString(authenticationType), QVariant(authenticationType)); } void resetAuthCapabilities() { noEncCapa.clear(); noEncCapa << Transport::EnumAuthenticationType::LOGIN << Transport::EnumAuthenticationType::PLAIN << Transport::EnumAuthenticationType::CRAM_MD5 << Transport::EnumAuthenticationType::DIGEST_MD5 << Transport::EnumAuthenticationType::NTLM << Transport::EnumAuthenticationType::GSSAPI << Transport::EnumAuthenticationType::XOAUTH2; sslCapa = tlsCapa = noEncCapa; updateAuthCapbilities(); } void enablePasswordLine() { ui.password->setEnabled(ui.kcfg_storePassword->isChecked()); } void updateAuthCapbilities() { if (serverTestFailed) { return; } QVector capa = noEncCapa; if (ui.encryptionSsl->isChecked()) { capa = sslCapa; } else if (ui.encryptionTls->isChecked()) { capa = tlsCapa; } ui.authCombo->clear(); for (int authType : qAsConst(capa)) { addAuthenticationItem(ui.authCombo, authType); } if (transport->isValid()) { const int idx = ui.authCombo->findData(transport->authenticationType()); if (idx != -1) { ui.authCombo->setCurrentIndex(idx); } } if (capa.isEmpty()) { ui.noAuthPossible->setVisible(true); ui.kcfg_requiresAuthentication->setChecked(false); ui.kcfg_requiresAuthentication->setEnabled(false); ui.kcfg_requiresAuthentication->setVisible(false); ui.authCombo->setEnabled(false); ui.authLabel->setEnabled(false); } else { ui.noAuthPossible->setVisible(false); ui.kcfg_requiresAuthentication->setEnabled(true); ui.kcfg_requiresAuthentication->setVisible(true); ui.authCombo->setEnabled(true); ui.authLabel->setEnabled(true); enablePasswordLine(); } } }; SMTPConfigWidget::SMTPConfigWidget(Transport *transport, QWidget *parent) : TransportConfigWidget(*new SMTPConfigWidgetPrivate, transport, parent) { init(); } static void checkHighestEnabledButton(QButtonGroup *group) { Q_ASSERT(group); for (int i = group->buttons().count() - 1; i >= 0; --i) { QAbstractButton *b = group->buttons().at(i); if (b && b->isEnabled()) { b->animateClick(); return; } } } void SMTPConfigWidget::init() { Q_D(SMTPConfigWidget); d->serverTest = nullptr; connect(TransportManager::self(), &TransportManager::passwordsChanged, this, &SMTPConfigWidget::passwordsLoaded); d->serverTestFailed = false; d->ui.setupUi(this); d->manager->addWidget(this); // otherwise it doesn't find out about these widgets d->manager->updateWidgets(); d->ui.password->setWhatsThis(i18n("The password to send to the server for authorization.")); d->ui.kcfg_userName->setClearButtonEnabled(true); d->encryptionGroup = new QButtonGroup(this); d->encryptionGroup->addButton(d->ui.encryptionNone, Transport::EnumEncryption::None); d->encryptionGroup->addButton(d->ui.encryptionSsl, Transport::EnumEncryption::SSL); d->encryptionGroup->addButton(d->ui.encryptionTls, Transport::EnumEncryption::TLS); d->ui.encryptionNone->setChecked(d->transport->encryption() == Transport::EnumEncryption::None); d->ui.encryptionSsl->setChecked(d->transport->encryption() == Transport::EnumEncryption::SSL); d->ui.encryptionTls->setChecked(d->transport->encryption() == Transport::EnumEncryption::TLS); d->resetAuthCapabilities(); if (!KProtocolInfo::capabilities(SMTP_PROTOCOL).contains(QLatin1String("SASL"))) { d->ui.authCombo->removeItem(d->ui.authCombo->findData( Transport::EnumAuthenticationType::NTLM)); d->ui.authCombo->removeItem(d->ui.authCombo->findData( Transport::EnumAuthenticationType::GSSAPI)); } connect(d->ui.checkCapabilities, &QPushButton::clicked, this, &SMTPConfigWidget::checkSmtpCapabilities); connect(d->ui.kcfg_host, &QLineEdit::textChanged, this, &SMTPConfigWidget::hostNameChanged); - connect(d->encryptionGroup, QOverload::of(&QButtonGroup::buttonClicked), this, &SMTPConfigWidget::encryptionChanged); + connect(d->encryptionGroup, qOverload(&QButtonGroup::buttonClicked), this, &SMTPConfigWidget::encryptionChanged); connect(d->ui.kcfg_requiresAuthentication, &QCheckBox::toggled, this, &SMTPConfigWidget::ensureValidAuthSelection); connect(d->ui.kcfg_storePassword, &QCheckBox::toggled, this, &SMTPConfigWidget::enablePasswordLine); if (!d->transport->isValid()) { checkHighestEnabledButton(d->encryptionGroup); } // load the password d->transport->updatePasswordState(); if (d->transport->isComplete()) { d->ui.password->setPassword(d->transport->password()); } else { if (d->transport->requiresAuthentication()) { TransportManager::self()->loadPasswordsAsync(); } } hostNameChanged(d->transport->host()); } void SMTPConfigWidget::enablePasswordLine() { Q_D(SMTPConfigWidget); d->enablePasswordLine(); } void SMTPConfigWidget::checkSmtpCapabilities() { Q_D(SMTPConfigWidget); d->serverTest = new ServerTest(this); d->serverTest->setProtocol(SMTP_PROTOCOL); d->serverTest->setServer(d->ui.kcfg_host->text().trimmed()); if (d->ui.kcfg_specifyHostname->isChecked()) { d->serverTest->setFakeHostname(d->ui.kcfg_localHostname->text()); } QAbstractButton *encryptionChecked = d->encryptionGroup->checkedButton(); if (encryptionChecked == d->ui.encryptionNone) { d->serverTest->setPort(Transport::EnumEncryption::None, d->ui.kcfg_port->value()); } else if (encryptionChecked == d->ui.encryptionSsl) { d->serverTest->setPort(Transport::EnumEncryption::SSL, d->ui.kcfg_port->value()); } d->serverTest->setProgressBar(d->ui.checkCapabilitiesProgress); d->ui.checkCapabilitiesStack->setCurrentIndex(1); qApp->setOverrideCursor(Qt::BusyCursor); connect(d->serverTest, &ServerTest::finished, this, &SMTPConfigWidget::slotFinished); connect(d->serverTest, &ServerTest::finished, qApp, [](){ qApp->restoreOverrideCursor(); }); d->ui.checkCapabilities->setEnabled(false); d->serverTest->start(); d->serverTestFailed = false; } void SMTPConfigWidget::apply() { Q_D(SMTPConfigWidget); Q_ASSERT(d->manager); d->manager->updateSettings(); if (!d->ui.kcfg_storePassword->isChecked() && d->ui.kcfg_requiresAuthentication->isChecked()) { //Delete stored password TransportManager::self()->removePasswordFromWallet(d->transport->id()); } d->transport->setPassword(d->ui.password->password()); KConfigGroup group(d->transport->config(), d->transport->currentGroup()); const int index = d->ui.authCombo->currentIndex(); if (index >= 0) { group.writeEntry("authtype", d->ui.authCombo->itemData(index).toInt()); } if (d->ui.encryptionNone->isChecked()) { d->transport->setEncryption(Transport::EnumEncryption::None); } else if (d->ui.encryptionSsl->isChecked()) { d->transport->setEncryption(Transport::EnumEncryption::SSL); } else if (d->ui.encryptionTls->isChecked()) { d->transport->setEncryption(Transport::EnumEncryption::TLS); } TransportConfigWidget::apply(); } void SMTPConfigWidget::passwordsLoaded() { Q_D(SMTPConfigWidget); // Load the password from the original to our cloned copy d->transport->updatePasswordState(); if (d->ui.password->password().isEmpty()) { d->ui.password->setPassword(d->transport->password()); } } // TODO rename void SMTPConfigWidget::slotFinished(const QVector &results) { Q_D(SMTPConfigWidget); d->ui.checkCapabilitiesStack->setCurrentIndex(0); d->ui.checkCapabilities->setEnabled(true); d->serverTest->deleteLater(); // If the servertest did not find any usable authentication modes, assume the // connection failed and don't disable any of the radioboxes. if (results.isEmpty()) { KMessageBox::error(this, i18n("Failed to check capabilities. Please verify port and authentication mode."), i18n("Check Capabilities Failed")); d->serverTestFailed = true; d->serverTest->deleteLater(); return; } // encryption method d->ui.encryptionNone->setEnabled(results.contains(Transport::EnumEncryption::None)); d->ui.encryptionSsl->setEnabled(results.contains(Transport::EnumEncryption::SSL)); d->ui.encryptionTls->setEnabled(results.contains(Transport::EnumEncryption::TLS)); checkHighestEnabledButton(d->encryptionGroup); d->noEncCapa = d->serverTest->normalProtocols(); if (d->ui.encryptionTls->isEnabled()) { d->tlsCapa = d->serverTest->tlsProtocols(); } else { d->tlsCapa.clear(); } d->sslCapa = d->serverTest->secureProtocols(); d->updateAuthCapbilities(); //Show correct port from capabilities. if (d->ui.encryptionSsl->isEnabled()) { const int portValue = d->serverTest->port(Transport::EnumEncryption::SSL); d->ui.kcfg_port->setValue(portValue == -1 ? SMTPS_PORT : portValue); } else if (d->ui.encryptionNone->isEnabled()) { const int portValue = d->serverTest->port(Transport::EnumEncryption::None); d->ui.kcfg_port->setValue(portValue == -1 ? SMTP_PORT : portValue); } d->serverTest->deleteLater(); } void SMTPConfigWidget::hostNameChanged(const QString &text) { // TODO: really? is this done at every change? wtf Q_D(SMTPConfigWidget); // sanitize hostname... const int pos = d->ui.kcfg_host->cursorPosition(); d->ui.kcfg_host->blockSignals(true); d->ui.kcfg_host->setText(text.trimmed()); d->ui.kcfg_host->blockSignals(false); d->ui.kcfg_host->setCursorPosition(pos); d->resetAuthCapabilities(); if (d->encryptionGroup) { for (int i = 0; i < d->encryptionGroup->buttons().count(); ++i) { d->encryptionGroup->buttons().at(i)->setEnabled(true); } } } void SMTPConfigWidget::ensureValidAuthSelection() { Q_D(SMTPConfigWidget); // adjust available authentication methods d->updateAuthCapbilities(); d->enablePasswordLine(); } void SMTPConfigWidget::encryptionChanged(int enc) { Q_D(SMTPConfigWidget); qCDebug(MAILTRANSPORT_SMTP_LOG) << enc; // adjust port if (enc == Transport::EnumEncryption::SSL) { if (d->ui.kcfg_port->value() == SMTP_PORT) { d->ui.kcfg_port->setValue(SMTPS_PORT); } } else { if (d->ui.kcfg_port->value() == SMTPS_PORT) { d->ui.kcfg_port->setValue(SMTP_PORT); } } ensureValidAuthSelection(); } diff --git a/src/kmailtransport/precommandjob.cpp b/src/kmailtransport/precommandjob.cpp index 2eb3c0d..0064109 100644 --- a/src/kmailtransport/precommandjob.cpp +++ b/src/kmailtransport/precommandjob.cpp @@ -1,121 +1,121 @@ /* Copyright (c) 2007 Volker Krause Based on KMail code by: Copyright (c) 1996-1998 Stefan Taferner Copyright (c) 2000-2002 Michael Haeckel This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 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 Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "precommandjob.h" #include #include using namespace MailTransport; /** * Private class that helps to provide binary compatibility between releases. * @internal */ class PreCommandJobPrivate { public: PreCommandJobPrivate(PrecommandJob *parent); QProcess *process = nullptr; QString precommand; PrecommandJob *q; // Slots void slotFinished(int, QProcess::ExitStatus); void slotStarted(); void slotError(QProcess::ProcessError error); }; PreCommandJobPrivate::PreCommandJobPrivate(PrecommandJob *parent) : process(nullptr) , q(parent) { } PrecommandJob::PrecommandJob(const QString &precommand, QObject *parent) : KJob(parent) , d(new PreCommandJobPrivate(this)) { d->precommand = precommand; d->process = new QProcess(this); connect(d->process, &QProcess::started, this, [this]() { d->slotStarted(); }); connect(d->process, &QProcess::errorOccurred, this, [this](QProcess::ProcessError error) { d->slotError(error); }); - connect(d->process, QOverload::of(&QProcess::finished), + connect(d->process, qOverload(&QProcess::finished), this, [this](int val, QProcess::ExitStatus status) { d->slotFinished(val, status); }); } PrecommandJob::~PrecommandJob() { delete d; } void PrecommandJob::start() { d->process->start(d->precommand); } void PreCommandJobPrivate::slotStarted() { emit q->infoMessage(q, i18n("Executing precommand"), i18n("Executing precommand '%1'.", precommand)); } void PreCommandJobPrivate::slotError(QProcess::ProcessError error) { q->setError(KJob::UserDefinedError); if (error == QProcess::FailedToStart) { q->setErrorText(i18n("Unable to start precommand '%1'.", precommand)); } else { q->setErrorText(i18n("Error while executing precommand '%1'.", precommand)); } q->emitResult(); } bool PrecommandJob::doKill() { delete d->process; d->process = nullptr; return true; } void PreCommandJobPrivate::slotFinished(int exitCode, QProcess::ExitStatus exitStatus) { if (exitStatus == QProcess::CrashExit) { q->setError(KJob::UserDefinedError); q->setErrorText(i18n("The precommand crashed.")); } else if (exitCode != 0) { q->setError(KJob::UserDefinedError); q->setErrorText(i18n("The precommand exited with code %1.", process->exitStatus())); } q->emitResult(); } #include "moc_precommandjob.cpp"