diff --git a/CMakeLists.txt b/CMakeLists.txt index 60ad6e4b1..524a18953 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,175 +1,175 @@ cmake_minimum_required(VERSION 3.5) set(PIM_VERSION "5.11.40") set(KDEPIM_RUNTIME_VERSION_NUMBER ${PIM_VERSION}) project(kdepim-runtime VERSION ${KDEPIM_RUNTIME_VERSION_NUMBER}) if (POLICY CMP0053) cmake_policy(SET CMP0053 NEW) endif() ############### KDEPIM-Runtime version ################ # KDEPIM_RUNTIME_VERSION # Version scheme: "x.y.z build". # # x is the version number. # y is the major release number. # z is the minor release number. # # "x.y.z" follow the kdelibs version kdepim is released with. # # If "z" is 0, it the version is "x.y" # # KDEPIM_DEV_VERSION # is empty for final versions. For development versions "build" is # something like "pre", "", "alpha2", "beta1", "beta2", "rc1", "rc2". # # Examples in chronological order: # # 3.0 # 3.0.1 # 3.1 # 3.1 beta1 # 3.1 beta2 # 3.1 rc1 # 3.1 # 3.1.1 # 3.2 pre # 3.2 set(KDEPIM_DEV_VERSION alpha) # add an extra space if(DEFINED KDEPIM_DEV_VERSION) set(KDEPIM_DEV_VERSION " ${KDEPIM_DEV_VERSION}") endif() set(KDEPIM_RUNTIME_VERSION "${KDEPIM_RUNTIME_VERSION_NUMBER}${KDEPIM_DEV_VERSION}") configure_file(kdepim-runtime-version.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/kdepim-runtime-version.h @ONLY) set(KF5_MIN_VERSION "5.58.0") find_package(ECM ${KF5_MIN_VERSION} CONFIG REQUIRED) set(CMAKE_MODULE_PATH ${kdepim-runtime_SOURCE_DIR}/cmake/ ${ECM_MODULE_PATH}) include(ECMSetupVersion) include(FeatureSummary) include(KDEInstallDirs) include(KDECMakeSettings) include(KDEFrameworkCompilerSettings NO_POLICY_SCOPE) include(ECMInstallIcons) include(ECMQtDeclareLoggingCategory) include(GenerateExportHeader) set(QT_REQUIRED_VERSION "5.10.0") set(KDEPIMRUNTIME_LIB_VERSION "${KDEPIM_RUNTIME_VERSION_NUMBER}") set(KDEPIMRUNTIME_LIB_SOVERSION "5") set(AKONADI_VERSION "5.11.40") set(KCONTACTS_LIB_VERSION "5.11.40") set(KCALENDARCORE_LIB_VERSION "5.11.43") set(IDENTITYMANAGEMENT_LIB_VERSION "5.11.40") set(KMAILTRANSPORT_LIB_VERSION "5.11.40") set(CALENDARUTILS_LIB_VERSION "5.11.40") set(KDAV_LIB_VERSION "5.11.40") -set(KIMAP_LIB_VERSION "5.11.40") +set(KIMAP_LIB_VERSION "5.11.41") set(KMBOX_LIB_VERSION "5.11.40") set(AKONADICALENDAR_LIB_VERSION "5.11.40") set(KONTACTINTERFACE_LIB_VERSION "5.11.40") set(AKONADIKALARM_LIB_VERSION "5.11.40") set(KMIME_LIB_VERSION "5.11.40") set(XMLRPCCLIENT_LIB_VERSION "5.11.40") set(KCONTACTS_LIB_VERSION "5.11.40") set(AKONADIMIME_LIB_VERSION "5.11.40") set(AKONADICONTACT_LIB_VERSION "5.11.40") set(AKONADINOTE_LIB_VERSION "5.11.40") set(PIMCOMMON_LIB_VERSION "5.11.40") set(KGAPI_LIB_VERSION "5.11.40") set( SharedMimeInfo_MINIMUM_VERSION "1.3" ) find_package(SharedMimeInfo ${SharedMimeInfo_MINIMUM_VERSION} REQUIRED) find_package(Sasl2) set_package_properties(Sasl2 PROPERTIES TYPE REQUIRED) find_package(Qca-qt5) option(KDEPIM_RUN_AKONADI_TEST "Enable autotest based on Akonadi." TRUE) # QT5 package find_package(Qt5 ${QT_REQUIRED_VERSION} CONFIG REQUIRED TextToSpeech Network Widgets Test XmlPatterns DBus WebEngineWidgets NetworkAuth) if (NOT Qca-qt5_FOUND) message(STATUS "QCA not found, public key authentication will not be supported") else() add_definitions(-DHAVE_QCA) endif() # KF5 package find_package(KF5Config ${KF5_MIN_VERSION} CONFIG REQUIRED) find_package(KF5ConfigWidgets ${KF5_MIN_VERSION} CONFIG REQUIRED) find_package(KF5NotifyConfig ${KF5_MIN_VERSION} CONFIG REQUIRED) find_package(KF5KIO ${KF5_MIN_VERSION} CONFIG REQUIRED) find_package(KF5ItemModels ${KF5_MIN_VERSION} CONFIG REQUIRED) find_package(KF5Codecs ${KF5_MIN_VERSION} CONFIG REQUIRED) find_package(KF5WindowSystem ${KF5_MIN_VERSION} CONFIG REQUIRED) find_package(KF5TextWidgets ${KF5_MIN_VERSION} CONFIG REQUIRED) # for KPluralHandlingSpinBox find_package(KF5Notifications ${KF5_MIN_VERSION} CONFIG REQUIRED) # pop3, ews find_package(KF5DocTools ${KF5_MIN_VERSION} CONFIG REQUIRED) # pop3 find_package(KF5Holidays ${KF5_MIN_VERSION} CONFIG REQUIRED) find_package(KF5DBusAddons ${KF5_MIN_VERSION} CONFIG REQUIRED) find_package(KF5IconThemes ${KF5_MIN_VERSION} CONFIG REQUIRED) # KdepimLibs package find_package(KF5Akonadi ${AKONADI_VERSION} CONFIG REQUIRED) find_package(KPimKDAV ${KDAV_LIB_VERSION} CONFIG REQUIRED) find_package(KF5Mime ${KMIME_LIB_VERSION} CONFIG REQUIRED) find_package(KF5AkonadiMime ${AKONADIMIME_LIB_VERSION} CONFIG REQUIRED) find_package(KF5MailTransportAkonadi ${KMAILTRANSPORT_LIB_VERSION} CONFIG REQUIRED) find_package(KF5IdentityManagement ${IDENTITYMANAGEMENT_LIB_VERSION} CONFIG REQUIRED) find_package(KF5AkonadiContact ${AKONADICONTACT_LIB_VERSION} CONFIG REQUIRED) find_package(KF5Contacts ${KCONTACTS_LIB_VERSION} CONFIG REQUIRED) find_package(KF5AlarmCalendar ${AKONADIKALARM_LIB_VERSION} CONFIG) find_package(KF5CalendarCore ${KCALENDARCORE_LIB_VERSION} CONFIG REQUIRED) find_package(KF5CalendarUtils ${CALENDARUTILS_LIB_VERSION} CONFIG REQUIRED) find_package(KF5Mbox ${KMBOX_LIB_VERSION} CONFIG REQUIRED) find_package(KF5IMAP ${KIMAP_LIB_VERSION} CONFIG REQUIRED) find_package(KF5AkonadiNotes ${AKONADINOTE_LIB_VERSION} CONFIG REQUIRED) find_package(KF5AkonadiCalendar ${AKONADICALENDAR_LIB_VERSION} CONFIG REQUIRED) find_package(KF5PimCommon ${PIMCOMMON_LIB_VERSION} CONFIG REQUIRED) find_package(KPimGAPI ${KGAPI_LIB_VERSION} CONFIG REQUIRED) option(KDEPIM_RUN_ISOLATED_TESTS "Run the isolated tests." FALSE) option(NO_REGENERATE_MIME "Don't regenerate mime file (developer-only option)" FALSE ) #add_definitions( -DQT_DISABLE_DEPRECATED_BEFORE=0x060000 ) find_package(Xsltproc) set_package_properties(Xsltproc PROPERTIES DESCRIPTION "XSLT processor from libxslt" TYPE REQUIRED PURPOSE "Required to generate D-Bus interfaces for all Akonadi resources.") add_subdirectory(resources) add_subdirectory(agents) add_subdirectory(defaultsetup) add_subdirectory(kioslave) add_subdirectory(migration) add_subdirectory(doc) ## install the MIME type spec file for KDEPIM specific MIME types install(FILES kdepim-mime.xml DESTINATION ${KDE_INSTALL_MIMEDIR}) if (NOT NO_REGENERATE_MIME) update_xdg_mimetypes(${KDE_INSTALL_MIMEDIR}) endif() if (${ECM_VERSION} STRGREATER "5.58.0") install(FILES kdepim-runtime.renamecategories kdepim-runtime.categories DESTINATION ${KDE_INSTALL_LOGGINGCATEGORIESDIR}) else() install(FILES kdepim-runtime.renamecategories kdepim-runtime.categories DESTINATION ${KDE_INSTALL_CONFDIR}) endif() feature_summary(WHAT ALL INCLUDE_QUIET_PACKAGES FATAL_ON_MISSING_REQUIRED_PACKAGES ) diff --git a/resources/imap/imapaccount.cpp b/resources/imap/imapaccount.cpp index 1b6a506a5..5b7f321e6 100644 --- a/resources/imap/imapaccount.cpp +++ b/resources/imap/imapaccount.cpp @@ -1,106 +1,116 @@ /* Copyright (c) 2007 Till Adam Copyright (C) 2008 Omat Holding B.V. Copyright (C) 2009 Kevin Ottens Copyright (c) 2010 Klarälvdalens Datakonsult AB, a KDAB Group company Author: Kevin Ottens 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 "imapaccount.h" ImapAccount::ImapAccount() : m_encryption(KIMAP::LoginJob::Unencrypted) , m_authentication(KIMAP::LoginJob::ClearText) { } ImapAccount::~ImapAccount() { } void ImapAccount::setServer(const QString &server) { m_server = server; } QString ImapAccount::server() const { return m_server; } void ImapAccount::setPort(quint16 port) { m_port = port; } quint16 ImapAccount::port() const { return m_port; } void ImapAccount::setUserName(const QString &userName) { m_userName = userName; } QString ImapAccount::userName() const { return m_userName; } void ImapAccount::setEncryptionMode(KIMAP::LoginJob::EncryptionMode mode) { m_encryption = mode; } KIMAP::LoginJob::EncryptionMode ImapAccount::encryptionMode() const { return m_encryption; } void ImapAccount::setAuthenticationMode(KIMAP::LoginJob::AuthenticationMode mode) { m_authentication = mode; } KIMAP::LoginJob::AuthenticationMode ImapAccount::authenticationMode() const { return m_authentication; } void ImapAccount::setSubscriptionEnabled(bool enabled) { m_subscriptionEnabled = enabled; } bool ImapAccount::isSubscriptionEnabled() const { return m_subscriptionEnabled; } void ImapAccount::setTimeout(int timeout) { m_timeout = timeout; } int ImapAccount::timeout() const { return m_timeout; } + +void ImapAccount::setUseNetworkProxy(bool useProxy) +{ + m_useProxy = useProxy; +} + +bool ImapAccount::useNetworkProxy() const +{ + return m_useProxy; +} diff --git a/resources/imap/imapaccount.h b/resources/imap/imapaccount.h index d2378b106..1df2ef354 100644 --- a/resources/imap/imapaccount.h +++ b/resources/imap/imapaccount.h @@ -1,69 +1,73 @@ /* Copyright (c) 2007 Till Adam Copyright (C) 2008 Omat Holding B.V. Copyright (C) 2009 Kevin Ottens Copyright (c) 2010 Klarälvdalens Datakonsult AB, a KDAB Group company Author: Kevin Ottens 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. */ #ifndef IMAPACCOUNT_H #define IMAPACCOUNT_H #include class ImapAccount { public: ImapAccount(); ~ImapAccount(); void setServer(const QString &server); QString server() const; void setPort(quint16 port); quint16 port() const; void setUserName(const QString &userName); QString userName() const; void setEncryptionMode(KIMAP::LoginJob::EncryptionMode mode); KIMAP::LoginJob::EncryptionMode encryptionMode() const; void setAuthenticationMode(KIMAP::LoginJob::AuthenticationMode mode); KIMAP::LoginJob::AuthenticationMode authenticationMode() const; void setSubscriptionEnabled(bool enabled); bool isSubscriptionEnabled() const; void setTimeout(int timeout); int timeout() const; + void setUseNetworkProxy(bool useProxy); + bool useNetworkProxy() const; + private: QString m_name; QString m_server; quint16 m_port = 0; QString m_userName; int m_timeout = 30; + bool m_useProxy = false; KIMAP::LoginJob::EncryptionMode m_encryption; KIMAP::LoginJob::AuthenticationMode m_authentication; bool m_subscriptionEnabled = false; }; #endif diff --git a/resources/imap/imapresource.kcfg b/resources/imap/imapresource.kcfg index 5f6920530..f6524c836 100644 --- a/resources/imap/imapresource.kcfg +++ b/resources/imap/imapresource.kcfg @@ -1,118 +1,123 @@ 993 SSL 1 false 30 + + +​ If checked, the system proxy settings will be used to connect to the mail server. + false + true true 5 true true -1 false true false true 4190 1 kmail-vacation.siv ImapUserPassword diff --git a/resources/imap/sessionpool.cpp b/resources/imap/sessionpool.cpp index e5dc24d03..49a8df32a 100644 --- a/resources/imap/sessionpool.cpp +++ b/resources/imap/sessionpool.cpp @@ -1,596 +1,597 @@ /* Copyright (c) 2010 Klarälvdalens Datakonsult AB, a KDAB Group company Author: Kevin Ottens 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 "sessionpool.h" #include #include #include "imapresource_debug.h" #include #include #include #include #include #include "imapaccount.h" #include "passwordrequesterinterface.h" qint64 SessionPool::m_requestCounter = 0; SessionPool::SessionPool(int maxPoolSize, QObject *parent) : QObject(parent) , m_maxPoolSize(maxPoolSize) { } SessionPool::~SessionPool() { disconnect(CloseSession); } PasswordRequesterInterface *SessionPool::passwordRequester() const { return m_passwordRequester; } void SessionPool::setPasswordRequester(PasswordRequesterInterface *requester) { delete m_passwordRequester; m_passwordRequester = requester; m_passwordRequester->setParent(this); QObject::connect(m_passwordRequester, &PasswordRequesterInterface::done, this, &SessionPool::onPasswordRequestDone); } void SessionPool::cancelPasswordRequests() { m_passwordRequester->cancelPasswordRequests(); } KIMAP::SessionUiProxy::Ptr SessionPool::sessionUiProxy() const { return m_sessionUiProxy; } void SessionPool::setSessionUiProxy(KIMAP::SessionUiProxy::Ptr proxy) { m_sessionUiProxy = proxy; } bool SessionPool::isConnected() const { return m_initialConnectDone; } bool SessionPool::connect(ImapAccount *account) { if (m_account) { return false; } m_account = account; if (m_account->authenticationMode() == KIMAP::LoginJob::GSSAPI) { // for GSSAPI we don't have to ask for username/password, because it uses session wide tickets QMetaObject::invokeMethod(this, "onPasswordRequestDone", Qt::QueuedConnection, Q_ARG(int, PasswordRequesterInterface::PasswordRetrieved), Q_ARG(QString, QString())); } else { m_passwordRequester->requestPassword(); } return true; } void SessionPool::disconnect(SessionTermination termination) { if (!m_account) { return; } foreach (KIMAP::Session *s, m_unusedPool + m_reservedPool + m_connectingPool) { killSession(s, termination); } m_unusedPool.clear(); m_reservedPool.clear(); m_connectingPool.clear(); m_pendingInitialSession = nullptr; m_passwordRequester->cancelPasswordRequests(); delete m_account; m_account = nullptr; m_namespaces.clear(); m_capabilities.clear(); m_initialConnectDone = false; Q_EMIT disconnectDone(); } qint64 SessionPool::requestSession() { if (!m_initialConnectDone) { return -1; } qint64 requestNumber = ++m_requestCounter; // The queue was empty, so trigger the processing if (m_pendingRequests.isEmpty()) { QTimer::singleShot(0, this, &SessionPool::processPendingRequests); } m_pendingRequests << requestNumber; return requestNumber; } void SessionPool::cancelSessionRequest(qint64 id) { Q_ASSERT(id > 0); m_pendingRequests.removeAll(id); } void SessionPool::releaseSession(KIMAP::Session *session) { const int removeSession = m_reservedPool.removeAll(session); if (removeSession > 0) { m_unusedPool << session; } } ImapAccount *SessionPool::account() const { return m_account; } QStringList SessionPool::serverCapabilities() const { return m_capabilities; } QList SessionPool::serverNamespaces() const { return m_namespaces; } QList SessionPool::serverNamespaces(Namespace ns) const { switch (ns) { case Personal: return m_personalNamespaces; case User: return m_userNamespaces; case Shared: return m_sharedNamespaces; default: break; } Q_ASSERT(false); return QList(); } void SessionPool::killSession(KIMAP::Session *session, SessionTermination termination) { Q_ASSERT(session); if (!m_unusedPool.contains(session) && !m_reservedPool.contains(session) && !m_connectingPool.contains(session)) { qCWarning(IMAPRESOURCE_LOG) << "Unmanaged session" << session; Q_ASSERT(false); return; } QObject::disconnect(session, &KIMAP::Session::connectionLost, this, &SessionPool::onConnectionLost); m_unusedPool.removeAll(session); m_reservedPool.removeAll(session); m_connectingPool.removeAll(session); if (session->state() != KIMAP::Session::Disconnected && termination == LogoutSession) { KIMAP::LogoutJob *logout = new KIMAP::LogoutJob(session); QObject::connect(logout, &KJob::result, session, &QObject::deleteLater); logout->start(); } else { session->close(); session->deleteLater(); } } void SessionPool::declareSessionReady(KIMAP::Session *session) { //This can happen if we happen to disconnect while capabilities and namespace are being retrieved, //resulting in us keeping a dangling pointer to a deleted session if (!m_connectingPool.contains(session)) { qCWarning(IMAPRESOURCE_LOG) << "Tried to declare a removed session ready"; return; } m_pendingInitialSession = nullptr; if (!m_initialConnectDone) { m_initialConnectDone = true; Q_EMIT connectDone(); // If the slot connected to connectDone() decided to disconnect the SessionPool // then we must end here, because we expect the pools to be empty now! if (!m_initialConnectDone) { return; } } m_connectingPool.removeAll(session); if (m_pendingRequests.isEmpty()) { m_unusedPool << session; } else { m_reservedPool << session; Q_EMIT sessionRequestDone(m_pendingRequests.takeFirst(), session); if (!m_pendingRequests.isEmpty()) { QTimer::singleShot(0, this, &SessionPool::processPendingRequests); } } } void SessionPool::cancelSessionCreation(KIMAP::Session *session, int errorCode, const QString &errorMessage) { m_pendingInitialSession = nullptr; QString msg; if (m_account) { msg = i18n("Could not connect to the IMAP-server %1.\n%2", m_account->server(), errorMessage); } else { // Can happen when we lose all ready connections while trying to establish // a new connection, for example. msg = i18n("Could not connect to the IMAP server.\n%1", errorMessage); } if (!m_initialConnectDone) { disconnect(); // kills all sessions, including \a session } else { if (session) { killSession(session, LogoutSession); } if (!m_pendingRequests.isEmpty()) { Q_EMIT sessionRequestDone(m_pendingRequests.takeFirst(), nullptr, errorCode, errorMessage); if (!m_pendingRequests.isEmpty()) { QTimer::singleShot(0, this, &SessionPool::processPendingRequests); } } } // Always emit this at the end. This can call SessionPool::disconnect via ImapResource. Q_EMIT connectDone(errorCode, msg); } void SessionPool::processPendingRequests() { if (!m_unusedPool.isEmpty()) { // We have a session ready to give out KIMAP::Session *session = m_unusedPool.takeFirst(); m_reservedPool << session; if (!m_pendingRequests.isEmpty()) { Q_EMIT sessionRequestDone(m_pendingRequests.takeFirst(), session); if (!m_pendingRequests.isEmpty()) { QTimer::singleShot(0, this, &SessionPool::processPendingRequests); } } } else if (m_unusedPool.size() + m_reservedPool.size() < m_maxPoolSize) { // We didn't reach the max pool size yet so create a new one m_passwordRequester->requestPassword(); } else { // No session available, and max pool size reached if (!m_pendingRequests.isEmpty()) { Q_EMIT sessionRequestDone( m_pendingRequests.takeFirst(), nullptr, NoAvailableSessionError, i18n("Could not create another extra connection to the IMAP-server %1.", m_account->server())); if (!m_pendingRequests.isEmpty()) { QTimer::singleShot(0, this, &SessionPool::processPendingRequests); } } } } void SessionPool::onPasswordRequestDone(int resultType, const QString &password) { QString errorMessage; if (!m_account) { // it looks like the connection was lost while we were waiting // for the password, we should fail all the pending requests and stop there for (int request : qAsConst(m_pendingRequests)) { Q_EMIT sessionRequestDone(request, nullptr, LoginFailError, i18n("Disconnected from server during login.")); } return; } switch (resultType) { case PasswordRequesterInterface::PasswordRetrieved: // All is fine break; case PasswordRequesterInterface::ReconnectNeeded: cancelSessionCreation(m_pendingInitialSession, ReconnectNeededError, errorMessage); return; case PasswordRequesterInterface::UserRejected: errorMessage = i18n("Could not read the password: user rejected wallet access"); if (m_pendingInitialSession) { cancelSessionCreation(m_pendingInitialSession, LoginFailError, errorMessage); } else { Q_EMIT connectDone(PasswordRequestError, errorMessage); } return; case PasswordRequesterInterface::EmptyPasswordEntered: errorMessage = i18n("Empty password"); if (m_pendingInitialSession) { cancelSessionCreation(m_pendingInitialSession, LoginFailError, errorMessage); } else { Q_EMIT connectDone(PasswordRequestError, errorMessage); } return; } if (m_account->encryptionMode() != KIMAP::LoginJob::Unencrypted && !QSslSocket::supportsSsl()) { qCWarning(IMAPRESOURCE_LOG) << "Crypto not supported!"; Q_EMIT connectDone(EncryptionError, i18n("You requested TLS/SSL to connect to %1, but your " "system does not seem to be set up for that.", m_account->server())); disconnect(); return; } KIMAP::Session *session = nullptr; if (m_pendingInitialSession) { session = m_pendingInitialSession; } else { session = new KIMAP::Session(m_account->server(), m_account->port(), this); QObject::connect(session, &QObject::destroyed, this, &SessionPool::onSessionDestroyed); session->setUiProxy(m_sessionUiProxy); session->setTimeout(m_account->timeout()); + session->setUseNetworkProxy(m_account->useNetworkProxy()); m_connectingPool << session; } QObject::connect(session, &KIMAP::Session::connectionLost, this, &SessionPool::onConnectionLost); KIMAP::LoginJob *loginJob = new KIMAP::LoginJob(session); loginJob->setUserName(m_account->userName()); loginJob->setPassword(password); loginJob->setEncryptionMode(m_account->encryptionMode()); loginJob->setAuthenticationMode(m_account->authenticationMode()); QObject::connect(loginJob, &KJob::result, this, &SessionPool::onLoginDone); loginJob->start(); } void SessionPool::onLoginDone(KJob *job) { KIMAP::LoginJob *login = static_cast(job); // Can happen if we disconnected meanwhile if (!m_connectingPool.contains(login->session())) { Q_EMIT connectDone(CancelledError, i18n("Disconnected from server during login.")); return; } if (job->error() == 0) { if (m_initialConnectDone) { declareSessionReady(login->session()); } else { // On initial connection we ask for capabilities KIMAP::CapabilitiesJob *capJob = new KIMAP::CapabilitiesJob(login->session()); QObject::connect(capJob, &KIMAP::CapabilitiesJob::result, this, &SessionPool::onCapabilitiesTestDone); capJob->start(); } } else { if (job->error() == KIMAP::LoginJob::ERR_COULD_NOT_CONNECT) { if (m_account) { cancelSessionCreation(login->session(), CouldNotConnectError, i18n("Could not connect to the IMAP-server %1.\n%2", m_account->server(), job->errorString())); } else { // Can happen when we lose all ready connections while trying to login. cancelSessionCreation(login->session(), CouldNotConnectError, i18n("Could not connect to the IMAP-server.\n%1", job->errorString())); } } else { // Connection worked, but login failed -> ask for a different password or ssl settings. m_pendingInitialSession = login->session(); m_passwordRequester->requestPassword(PasswordRequesterInterface::WrongPasswordRequest, job->errorString()); } } } void SessionPool::onCapabilitiesTestDone(KJob *job) { KIMAP::CapabilitiesJob *capJob = qobject_cast(job); // Can happen if we disconnected meanwhile if (!m_connectingPool.contains(capJob->session())) { Q_EMIT connectDone(CancelledError, i18n("Disconnected from server during login.")); return; } if (job->error()) { if (m_account) { cancelSessionCreation(capJob->session(), CapabilitiesTestError, i18n("Could not test the capabilities supported by the " "IMAP server %1.\n%2", m_account->server(), job->errorString())); } else { // Can happen when we lose all ready connections while trying to check capabilities. cancelSessionCreation(capJob->session(), CapabilitiesTestError, i18n("Could not test the capabilities supported by the " "IMAP server.\n%1", job->errorString())); } return; } m_capabilities = capJob->capabilities(); QStringList missing; const QStringList expected = {QStringLiteral("IMAP4REV1")}; for (const QString &capability : expected) { if (!m_capabilities.contains(capability)) { missing << capability; } } if (!missing.isEmpty()) { cancelSessionCreation(capJob->session(), IncompatibleServerError, i18n("Cannot use the IMAP server %1, " "some mandatory capabilities are missing: %2. " "Please ask your sysadmin to upgrade the server.", m_account->server(), missing.join(QStringLiteral(", ")))); return; } // If the extension is supported, grab the namespaces from the server if (m_capabilities.contains(QLatin1String("NAMESPACE"))) { KIMAP::NamespaceJob *nsJob = new KIMAP::NamespaceJob(capJob->session()); QObject::connect(nsJob, &KIMAP::NamespaceJob::result, this, &SessionPool::onNamespacesTestDone); nsJob->start(); return; } else if (m_capabilities.contains(QLatin1String("ID"))) { KIMAP::IdJob *idJob = new KIMAP::IdJob(capJob->session()); idJob->setField("name", m_clientId); QObject::connect(idJob, &KIMAP::IdJob::result, this, &SessionPool::onIdDone); idJob->start(); return; } else { declareSessionReady(capJob->session()); } } void SessionPool::setClientId(const QByteArray &clientId) { m_clientId = clientId; } void SessionPool::onNamespacesTestDone(KJob *job) { KIMAP::NamespaceJob *nsJob = qobject_cast(job); // Can happen if we disconnect meanwhile if (!m_connectingPool.contains(nsJob->session())) { Q_EMIT connectDone(CancelledError, i18n("Disconnected from server during login.")); return; } m_personalNamespaces = nsJob->personalNamespaces(); m_userNamespaces = nsJob->userNamespaces(); m_sharedNamespaces = nsJob->sharedNamespaces(); if (nsJob->containsEmptyNamespace()) { // When we got the empty namespace here, we assume that the other // ones can be freely ignored and that the server will give us all // the mailboxes if we list from the empty namespace itself... m_namespaces.clear(); } else { // ... otherwise we assume that we have to list explicitly each // namespace m_namespaces = nsJob->personalNamespaces() +nsJob->userNamespaces() +nsJob->sharedNamespaces(); } if (m_capabilities.contains(QLatin1String("ID"))) { KIMAP::IdJob *idJob = new KIMAP::IdJob(nsJob->session()); idJob->setField("name", m_clientId); QObject::connect(idJob, &KIMAP::IdJob::result, this, &SessionPool::onIdDone); idJob->start(); return; } else { declareSessionReady(nsJob->session()); } } void SessionPool::onIdDone(KJob *job) { KIMAP::IdJob *idJob = qobject_cast(job); // Can happen if we disconnected meanwhile if (!m_connectingPool.contains(idJob->session())) { Q_EMIT connectDone(CancelledError, i18n("Disconnected during login.")); return; } declareSessionReady(idJob->session()); } void SessionPool::onConnectionLost() { KIMAP::Session *session = static_cast(sender()); m_unusedPool.removeAll(session); m_reservedPool.removeAll(session); m_connectingPool.removeAll(session); if (m_unusedPool.isEmpty() && m_reservedPool.isEmpty()) { m_passwordRequester->cancelPasswordRequests(); delete m_account; m_account = nullptr; m_namespaces.clear(); m_capabilities.clear(); m_initialConnectDone = false; } Q_EMIT connectionLost(session); if (!m_pendingRequests.isEmpty()) { cancelSessionCreation(nullptr, CouldNotConnectError, QString()); } session->deleteLater(); if (session == m_pendingInitialSession) { m_pendingInitialSession = nullptr; } } void SessionPool::onSessionDestroyed(QObject *object) { //Safety net for bugs that cause dangling session pointers KIMAP::Session *session = static_cast(object); bool sessionInPool = false; if (m_unusedPool.contains(session)) { qCWarning(IMAPRESOURCE_LOG) << "Session" << object << "destroyed while still in unused pool!"; m_unusedPool.removeAll(session); sessionInPool = true; } if (m_reservedPool.contains(session)) { qCWarning(IMAPRESOURCE_LOG) << "Session" << object << "destroyed while still in reserved pool!"; m_reservedPool.removeAll(session); sessionInPool = true; } if (m_connectingPool.contains(session)) { qCWarning(IMAPRESOURCE_LOG) << "Session" << object << "destroyed while still in connecting pool!"; m_connectingPool.removeAll(session); sessionInPool = true; } Q_ASSERT(!sessionInPool); } diff --git a/resources/imap/settings.cpp b/resources/imap/settings.cpp index 81454aec5..db297268c 100644 --- a/resources/imap/settings.cpp +++ b/resources/imap/settings.cpp @@ -1,312 +1,313 @@ /* Copyright (c) 2008 Volker Krause Copyright (c) 2008 Omat Holding B.V. 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 "settings.h" #include "settingsadaptor.h" #include "imapaccount.h" #include #include using KWallet::Wallet; #include "imapresource_debug.h" #include #include #include #include /** * Maps the enum used to represent authentication in MailTransport (kdepimlibs) * to the one used by the imap resource. * @param authType the MailTransport auth enum value * @return the corresponding KIMAP auth value. * @note will cause fatal error if there is no mapping, so be careful not to pass invalid auth options (e.g., APOP) to this function. */ KIMAP::LoginJob::AuthenticationMode Settings::mapTransportAuthToKimap(MailTransport::Transport::EnumAuthenticationType::type authType) { // typedef these for readability typedef MailTransport::Transport::EnumAuthenticationType MTAuth; typedef KIMAP::LoginJob KIAuth; switch (authType) { case MTAuth::ANONYMOUS: return KIAuth::Anonymous; case MTAuth::PLAIN: return KIAuth::Plain; case MTAuth::NTLM: return KIAuth::NTLM; case MTAuth::LOGIN: return KIAuth::Login; case MTAuth::GSSAPI: return KIAuth::GSSAPI; case MTAuth::DIGEST_MD5: return KIAuth::DigestMD5; case MTAuth::CRAM_MD5: return KIAuth::CramMD5; case MTAuth::CLEAR: return KIAuth::ClearText; case MTAuth::XOAUTH2: return KIAuth::XOAuth2; default: qFatal("mapping from Transport::EnumAuthenticationType -> KIMAP::LoginJob::AuthenticationMode not possible"); } return KIAuth::ClearText; // dummy value, shouldn't get here. } Settings::Settings(WId winId) : SettingsBase() , m_winId(winId) { load(); new SettingsAdaptor(this); QDBusConnection::sessionBus().registerObject(QStringLiteral("/Settings"), this, QDBusConnection::ExportAdaptors | QDBusConnection::ExportScriptableContents); } void Settings::setWinId(WId winId) { m_winId = winId; } void Settings::clearCachedPassword() { m_password.clear(); } void Settings::cleanup() { Wallet *wallet = Wallet::openWallet(Wallet::NetworkWallet(), m_winId); if (wallet && wallet->isOpen()) { if (wallet->hasFolder(QStringLiteral("imap"))) { wallet->setFolder(QStringLiteral("imap")); wallet->removeEntry(config()->name()); } delete wallet; } } void Settings::requestPassword() { if (!m_password.isEmpty() || (mapTransportAuthToKimap((MailTransport::TransportBase::EnumAuthenticationType::type)authentication()) == KIMAP::LoginJob::GSSAPI)) { Q_EMIT passwordRequestCompleted(m_password, false); } else { Wallet *wallet = Wallet::openWallet(Wallet::NetworkWallet(), m_winId, Wallet::Asynchronous); if (wallet) { connect(wallet, &KWallet::Wallet::walletOpened, this, &Settings::onWalletOpened); } else { QMetaObject::invokeMethod(this, "onWalletOpened", Qt::QueuedConnection, Q_ARG(bool, true)); } } } void Settings::onWalletOpened(bool success) { if (!success) { Q_EMIT passwordRequestCompleted(QString(), true); } else { Wallet *wallet = qobject_cast(sender()); bool passwordNotStoredInWallet = true; if (wallet && wallet->hasFolder(QStringLiteral("imap"))) { wallet->setFolder(QStringLiteral("imap")); wallet->readPassword(config()->name(), m_password); passwordNotStoredInWallet = false; } Q_EMIT passwordRequestCompleted(m_password, passwordNotStoredInWallet); if (wallet) { wallet->deleteLater(); } } } QString Settings::password(bool *userRejected) const { if (userRejected != nullptr) { *userRejected = false; } if (!m_password.isEmpty() || (mapTransportAuthToKimap((MailTransport::TransportBase::EnumAuthenticationType::type)authentication()) == KIMAP::LoginJob::GSSAPI)) { return m_password; } Wallet *wallet = Wallet::openWallet(Wallet::NetworkWallet(), m_winId); if (wallet && wallet->isOpen()) { if (wallet->hasFolder(QStringLiteral("imap"))) { wallet->setFolder(QStringLiteral("imap")); wallet->readPassword(config()->name(), m_password); } else { wallet->createFolder(QStringLiteral("imap")); } } else if (userRejected != nullptr) { *userRejected = true; } delete wallet; return m_password; } QString Settings::sieveCustomPassword(bool *userRejected) const { if (userRejected != nullptr) { *userRejected = false; } if (!m_customSievePassword.isEmpty()) { return m_customSievePassword; } Wallet *wallet = Wallet::openWallet(Wallet::NetworkWallet(), m_winId); if (wallet && wallet->isOpen()) { if (wallet->hasFolder(QStringLiteral("imap"))) { wallet->setFolder(QStringLiteral("imap")); wallet->readPassword(QStringLiteral("custom_sieve_") + config()->name(), m_customSievePassword); } else { wallet->createFolder(QStringLiteral("imap")); } } else if (userRejected != nullptr) { *userRejected = true; } delete wallet; return m_customSievePassword; } void Settings::setSieveCustomPassword(const QString &password) { if (m_customSievePassword == password) { return; } m_customSievePassword = password; Wallet *wallet = Wallet::openWallet(Wallet::NetworkWallet(), m_winId); if (wallet && wallet->isOpen()) { if (!wallet->hasFolder(QStringLiteral("imap"))) { wallet->createFolder(QStringLiteral("imap")); } wallet->setFolder(QStringLiteral("imap")); wallet->writePassword(QLatin1String("custom_sieve_") + config()->name(), password); qCDebug(IMAPRESOURCE_LOG) << "Wallet save: " << wallet->sync(); } delete wallet; } void Settings::setPassword(const QString &password) { if (password == m_password) { return; } if (mapTransportAuthToKimap((MailTransport::TransportBase::EnumAuthenticationType::type)authentication()) == KIMAP::LoginJob::GSSAPI) { return; } m_password = password; Wallet *wallet = Wallet::openWallet(Wallet::NetworkWallet(), m_winId); if (wallet && wallet->isOpen()) { if (!wallet->hasFolder(QStringLiteral("imap"))) { wallet->createFolder(QStringLiteral("imap")); } wallet->setFolder(QStringLiteral("imap")); wallet->writePassword(config()->name(), password); qCDebug(IMAPRESOURCE_LOG) << "Wallet save: " << wallet->sync(); } delete wallet; } void Settings::loadAccount(ImapAccount *account) const { account->setServer(imapServer()); if (imapPort() >= 0) { account->setPort(imapPort()); } account->setUserName(userName()); account->setSubscriptionEnabled(subscriptionEnabled()); + account->setUseNetworkProxy(useProxy()); const QString encryption = safety(); if (encryption == QLatin1String("SSL")) { account->setEncryptionMode(KIMAP::LoginJob::SSLorTLS); } else if (encryption == QLatin1String("STARTTLS")) { account->setEncryptionMode(KIMAP::LoginJob::STARTTLS); } else { account->setEncryptionMode(KIMAP::LoginJob::Unencrypted); } //Some SSL Server fail to advertise an ssl version they support (AnySslVersion), //we therefore allow overriding this in the config //(so we don't have to make the UI unnecessarily complex for properly working servers). const QString overrideEncryptionMode = overrideEncryption(); if (!overrideEncryptionMode.isEmpty()) { qCWarning(IMAPRESOURCE_LOG) << "Overriding encryption mode with: " << overrideEncryptionMode; if (overrideEncryptionMode == QLatin1String("SSLV2")) { account->setEncryptionMode(KIMAP::LoginJob::SSLorTLS); } else if (overrideEncryptionMode == QLatin1String("SSLV3")) { account->setEncryptionMode(KIMAP::LoginJob::SSLorTLS); } else if (overrideEncryptionMode == QLatin1String("TLSV1")) { account->setEncryptionMode(KIMAP::LoginJob::SSLorTLS); } else if (overrideEncryptionMode == QLatin1String("SSL")) { account->setEncryptionMode(KIMAP::LoginJob::SSLorTLS); } else if (overrideEncryptionMode == QLatin1String("STARTTLS")) { account->setEncryptionMode(KIMAP::LoginJob::STARTTLS); } else if (overrideEncryptionMode == QLatin1String("UNENCRYPTED")) { account->setEncryptionMode(KIMAP::LoginJob::Unencrypted); } else { qCWarning(IMAPRESOURCE_LOG) << "Tried to force invalid encryption mode: " << overrideEncryptionMode; } } account->setAuthenticationMode( mapTransportAuthToKimap( (MailTransport::TransportBase::EnumAuthenticationType::type)authentication() ) ); account->setTimeout(sessionTimeout()); } QString Settings::rootRemoteId() const { return QStringLiteral("imap://") + userName() + QLatin1Char('@') + imapServer() + QLatin1Char('/'); } void Settings::renameRootCollection(const QString &newName) { Akonadi::Collection rootCollection; rootCollection.setRemoteId(rootRemoteId()); Akonadi::CollectionFetchJob *fetchJob = new Akonadi::CollectionFetchJob(rootCollection, Akonadi::CollectionFetchJob::Base); fetchJob->setProperty("collectionName", newName); connect(fetchJob, &KJob::result, this, &Settings::onRootCollectionFetched); } void Settings::onRootCollectionFetched(KJob *job) { const QString newName = job->property("collectionName").toString(); Q_ASSERT(!newName.isEmpty()); Akonadi::CollectionFetchJob *fetchJob = static_cast(job); if (fetchJob->collections().size() == 1) { Akonadi::Collection rootCollection = fetchJob->collections().at(0); rootCollection.setName(newName); new Akonadi::CollectionModifyJob(rootCollection); // We don't care about the result here, nothing we can/should do if the renaming fails } } diff --git a/resources/imap/setupserver.cpp b/resources/imap/setupserver.cpp index b666c98a1..8e435bbf9 100644 --- a/resources/imap/setupserver.cpp +++ b/resources/imap/setupserver.cpp @@ -1,717 +1,719 @@ /* This file is part of the KDE project Copyright (c) 2010 Klarälvdalens Datakonsult AB, a KDAB Group company Author: Kevin Ottens Copyright (C) 2010 Casey Link Copyright (c) 2009-2010 Klaralvdalens Datakonsult AB, a KDAB Group company Copyright (C) 2009 Kevin Ottens Copyright (C) 2006-2008 Omat Holding B.V. Copyright (C) 2006 Frode M. Døving Original copied from showfoto: Copyright 2005 by Gilles Caulier This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program 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 General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "setupserver.h" #include "settings.h" #include "imapresource.h" #include "serverinfodialog.h" #include "folderarchivesettingpage.h" #include "utils.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "imapresource_debug.h" #include #include #include #include #include "imapaccount.h" #include "subscriptiondialog.h" #include "ui_setupserverview_desktop.h" /** static helper functions **/ static QString authenticationModeString(MailTransport::Transport::EnumAuthenticationType::type mode) { switch (mode) { case MailTransport::Transport::EnumAuthenticationType::LOGIN: return QStringLiteral("LOGIN"); case MailTransport::Transport::EnumAuthenticationType::PLAIN: return QStringLiteral("PLAIN"); case MailTransport::Transport::EnumAuthenticationType::CRAM_MD5: return QStringLiteral("CRAM-MD5"); case MailTransport::Transport::EnumAuthenticationType::DIGEST_MD5: return QStringLiteral("DIGEST-MD5"); case MailTransport::Transport::EnumAuthenticationType::GSSAPI: return QStringLiteral("GSSAPI"); case MailTransport::Transport::EnumAuthenticationType::NTLM: return QStringLiteral("NTLM"); case MailTransport::Transport::EnumAuthenticationType::CLEAR: return i18nc("Authentication method", "Clear text"); case MailTransport::Transport::EnumAuthenticationType::ANONYMOUS: return i18nc("Authentication method", "Anonymous"); case MailTransport::Transport::EnumAuthenticationType::XOAUTH2: return i18nc("Authentication method", "Gmail"); default: break; } return QString(); } static void setCurrentAuthMode(QComboBox *authCombo, MailTransport::Transport::EnumAuthenticationType::type authtype) { qCDebug(IMAPRESOURCE_LOG) << "setting authcombo: " << authenticationModeString(authtype); int index = authCombo->findData(authtype); if (index == -1) { qCWarning(IMAPRESOURCE_LOG) << "desired authmode not in the combo"; } qCDebug(IMAPRESOURCE_LOG) << "found corresponding index: " << index << "with data" << authenticationModeString((MailTransport::Transport::EnumAuthenticationType::type)authCombo->itemData( index).toInt()); authCombo->setCurrentIndex(index); MailTransport::Transport::EnumAuthenticationType::type t = (MailTransport::Transport::EnumAuthenticationType::type)authCombo->itemData(authCombo->currentIndex()).toInt(); qCDebug(IMAPRESOURCE_LOG) << "selected auth mode:" << authenticationModeString(t); Q_ASSERT(t == authtype); } static MailTransport::Transport::EnumAuthenticationType::type getCurrentAuthMode(QComboBox *authCombo) { MailTransport::Transport::EnumAuthenticationType::type authtype = (MailTransport::Transport::EnumAuthenticationType::type)authCombo->itemData(authCombo->currentIndex()).toInt(); qCDebug(IMAPRESOURCE_LOG) << "current auth mode: " << authenticationModeString(authtype); return authtype; } static void addAuthenticationItem(QComboBox *authCombo, MailTransport::Transport::EnumAuthenticationType::type authtype) { qCDebug(IMAPRESOURCE_LOG) << "adding auth item " << authenticationModeString(authtype); authCombo->addItem(authenticationModeString(authtype), QVariant(authtype)); } SetupServer::SetupServer(ImapResourceBase *parentResource, WId parent) : QDialog() , m_parentResource(parentResource) , m_ui(new Ui::SetupServerView) , mValidator(this) { QNetworkConfigurationManager *networkConfigMgr = new QNetworkConfigurationManager(QCoreApplication::instance()); m_parentResource->settings()->setWinId(parent); QWidget *mainWidget = new QWidget(this); QVBoxLayout *mainLayout = new QVBoxLayout(this); mainLayout->addWidget(mainWidget); QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, this); mOkButton = buttonBox->button(QDialogButtonBox::Ok); mOkButton->setDefault(true); mOkButton->setShortcut(Qt::CTRL | Qt::Key_Return); connect(mOkButton, &QPushButton::clicked, this, &SetupServer::applySettings); connect(buttonBox, &QDialogButtonBox::rejected, this, &SetupServer::reject); mainLayout->addWidget(buttonBox); m_ui->setupUi(mainWidget); m_folderArchiveSettingPage = new FolderArchiveSettingPage(m_parentResource->identifier()); m_ui->tabWidget->addTab(m_folderArchiveSettingPage, i18n("Archive Folder")); m_ui->safeImapGroup->setId(m_ui->noRadio, KIMAP::LoginJob::Unencrypted); m_ui->safeImapGroup->setId(m_ui->sslRadio, KIMAP::LoginJob::SSLorTLS); m_ui->safeImapGroup->setId(m_ui->tlsRadio, KIMAP::LoginJob::STARTTLS); connect(m_ui->noRadio, &QRadioButton::toggled, this, &SetupServer::slotSafetyChanged); connect(m_ui->sslRadio, &QRadioButton::toggled, this, &SetupServer::slotSafetyChanged); connect(m_ui->tlsRadio, &QRadioButton::toggled, this, &SetupServer::slotSafetyChanged); m_ui->testInfo->hide(); m_ui->testProgress->hide(); m_ui->accountName->setFocus(); m_ui->checkInterval->setSuffix(ki18np(" minute", " minutes")); m_ui->checkInterval->setMinimum(Akonadi::ResourceSettings::self()->minimumCheckInterval()); m_ui->checkInterval->setMaximum(10000); m_ui->checkInterval->setSingleStep(1); // regex for evaluating a valid server name/ip mValidator.setRegExp(QRegExp(QLatin1String("[A-Za-z0-9-_:.]*"))); m_ui->imapServer->setValidator(&mValidator); m_ui->folderRequester->setMimeTypeFilter( QStringList() << KMime::Message::mimeType()); m_ui->folderRequester->setAccessRightsFilter(Akonadi::Collection::CanChangeItem | Akonadi::Collection::CanCreateItem | Akonadi::Collection::CanDeleteItem); m_ui->folderRequester->changeCollectionDialogOptions(Akonadi::CollectionDialog::AllowToCreateNewChildCollection); m_identityCombobox = new KIdentityManagement::IdentityCombo(KIdentityManagement::IdentityManager::self(), this); m_ui->identityLabel->setBuddy(m_identityCombobox); m_ui->identityLayout->addWidget(m_identityCombobox, 1); m_ui->identityLabel->setBuddy(m_identityCombobox); connect(m_ui->testButton, &QPushButton::pressed, this, &SetupServer::slotTest); connect(m_ui->imapServer, &KLineEdit::textChanged, this, &SetupServer::slotServerChanged); connect(m_ui->imapServer, &KLineEdit::textChanged, this, &SetupServer::slotTestChanged); connect(m_ui->imapServer, &KLineEdit::textChanged, this, &SetupServer::slotComplete); connect(m_ui->userName, &KLineEdit::textChanged, this, &SetupServer::slotComplete); connect(m_ui->subscriptionEnabled, &QCheckBox::toggled, this, &SetupServer::slotSubcriptionCheckboxChanged); connect(m_ui->subscriptionButton, &QPushButton::pressed, this, &SetupServer::slotManageSubscriptions); connect(m_ui->managesieveCheck, &QCheckBox::toggled, this, &SetupServer::slotEnableWidgets); connect(m_ui->sameConfigCheck, &QCheckBox::toggled, this, &SetupServer::slotEnableWidgets); connect(m_ui->useDefaultIdentityCheck, &QCheckBox::toggled, this, &SetupServer::slotIdentityCheckboxChanged); connect(m_ui->enableMailCheckBox, &QCheckBox::toggled, this, &SetupServer::slotMailCheckboxChanged); connect(m_ui->safeImapGroup, QOverload::of(&QButtonGroup::buttonClicked), this, &SetupServer::slotEncryptionRadioChanged); connect(m_ui->customSieveGroup, QOverload::of(&QButtonGroup::buttonClicked), this, &SetupServer::slotCustomSieveChanged); connect(m_ui->showServerInfo, &QPushButton::pressed, this, &SetupServer::slotShowServerInfo); readSettings(); slotTestChanged(); slotComplete(); slotCustomSieveChanged(); connect(networkConfigMgr, &QNetworkConfigurationManager::onlineStateChanged, this, &SetupServer::slotTestChanged); } SetupServer::~SetupServer() { delete m_ui; } bool SetupServer::shouldClearCache() const { return m_shouldClearCache; } void SetupServer::slotSubcriptionCheckboxChanged() { m_ui->subscriptionButton->setEnabled(m_ui->subscriptionEnabled->isChecked()); } void SetupServer::slotIdentityCheckboxChanged() { m_identityCombobox->setEnabled(!m_ui->useDefaultIdentityCheck->isChecked()); } void SetupServer::slotMailCheckboxChanged() { m_ui->checkInterval->setEnabled(m_ui->enableMailCheckBox->isChecked()); } void SetupServer::slotEncryptionRadioChanged() { // TODO these really should be defined somewhere else switch (m_ui->safeImapGroup->checkedId()) { case KIMAP::LoginJob::Unencrypted: case KIMAP::LoginJob::STARTTLS: m_ui->portSpin->setValue(143); break; case KIMAP::LoginJob::SSLorTLS: m_ui->portSpin->setValue(993); break; default: qFatal("Shouldn't happen"); } } void SetupServer::slotCustomSieveChanged() { QAbstractButton *checkedButton = m_ui->customSieveGroup->checkedButton(); if (checkedButton == m_ui->imapUserPassword || checkedButton == m_ui->noAuthentification) { m_ui->customUsername->setEnabled(false); m_ui->customPassword->setEnabled(false); } else if (checkedButton == m_ui->customUserPassword) { m_ui->customUsername->setEnabled(true); m_ui->customPassword->setEnabled(true); } } void SetupServer::applySettings() { if (!m_parentResource->settings()->imapServer().isEmpty() && m_ui->imapServer->text() != m_parentResource->settings()->imapServer()) { if (KMessageBox::warningContinueCancel( this, i18n("You have changed the address of the server. Even if this is the same server as before " "we will have to re-download all your emails from this account again. " "Are you sure you want to proceed?"), i18n("Server address change")) == KMessageBox::Cancel) { return; } } if (!m_parentResource->settings()->userName().isEmpty() && m_ui->userName->text() != m_parentResource->settings()->userName()) { if (KMessageBox::warningContinueCancel( this, i18n("You have changed the user name. Even if this is a user name for the same account as before " "we will have to re-download all your emails from this account again. " "Are you sure you want to proceed?"), i18n("User name change")) == KMessageBox::Cancel) { return; } } m_folderArchiveSettingPage->writeSettings(); m_shouldClearCache = (m_parentResource->settings()->imapServer() != m_ui->imapServer->text()) || (m_parentResource->settings()->userName() != m_ui->userName->text()); const MailTransport::Transport::EnumAuthenticationType::type authtype = getCurrentAuthMode(m_ui->authenticationCombo); if (!m_ui->userName->text().contains(QLatin1Char('@')) && authtype == MailTransport::Transport::EnumAuthenticationType::XOAUTH2 && m_ui->imapServer->text().contains(QLatin1String("gmail.com"))) { // Normalize gmail username so that it matches the JSON account info returned by GMail authentication. // If we don't do this, we will look up cached auth without @gmail.com and save it with @gmail.com => very frequent auth dialog popping up. qCDebug(IMAPRESOURCE_LOG) << "Fixing up username" << m_ui->userName->text() << "by adding @gmail.com"; m_ui->userName->setText(m_ui->userName->text() + QLatin1String("@gmail.com")); } m_parentResource->setName(m_ui->accountName->text()); m_parentResource->settings()->setImapServer(m_ui->imapServer->text()); m_parentResource->settings()->setImapPort(m_ui->portSpin->value()); m_parentResource->settings()->setUserName(m_ui->userName->text()); QString encryption; switch (m_ui->safeImapGroup->checkedId()) { case KIMAP::LoginJob::Unencrypted: encryption = QStringLiteral("None"); break; case KIMAP::LoginJob::SSLorTLS: encryption = QStringLiteral("SSL"); break; case KIMAP::LoginJob::STARTTLS: encryption = QStringLiteral("STARTTLS"); break; default: qFatal("Shouldn't happen"); } m_parentResource->settings()->setSafety(encryption); qCDebug(IMAPRESOURCE_LOG) << "saving IMAP auth mode: " << authenticationModeString(authtype); m_parentResource->settings()->setAuthentication(authtype); m_parentResource->settings()->setPassword(m_ui->password->password()); m_parentResource->settings()->setSubscriptionEnabled(m_ui->subscriptionEnabled->isChecked()); m_parentResource->settings()->setIntervalCheckTime(m_ui->checkInterval->value()); m_parentResource->settings()->setDisconnectedModeEnabled(m_ui->disconnectedModeEnabled->isChecked()); + m_parentResource->settings()->setUseProxy(m_ui->useProxyCheck->isChecked()); MailTransport::Transport::EnumAuthenticationType::type alternateAuthtype = getCurrentAuthMode(m_ui->authenticationAlternateCombo); qCDebug(IMAPRESOURCE_LOG) << "saving Alternate server sieve auth mode: " << authenticationModeString(alternateAuthtype); m_parentResource->settings()->setAlternateAuthentication(alternateAuthtype); m_parentResource->settings()->setSieveSupport(m_ui->managesieveCheck->isChecked()); m_parentResource->settings()->setSieveReuseConfig(m_ui->sameConfigCheck->isChecked()); m_parentResource->settings()->setSievePort(m_ui->sievePortSpin->value()); m_parentResource->settings()->setSieveAlternateUrl(m_ui->alternateURL->text()); m_parentResource->settings()->setSieveVacationFilename(m_vacationFileName); m_parentResource->settings()->setTrashCollection(m_ui->folderRequester->collection().id()); Akonadi::Collection trash = m_ui->folderRequester->collection(); Akonadi::SpecialMailCollections::self()->registerCollection(Akonadi::SpecialMailCollections::Trash, trash); Akonadi::EntityDisplayAttribute *attribute = trash.attribute(Akonadi::Collection::AddIfMissing); attribute->setIconName(QStringLiteral("user-trash")); new Akonadi::CollectionModifyJob(trash); if (mOldTrash != trash) { Akonadi::SpecialMailCollections::self()->unregisterCollection(mOldTrash); } m_parentResource->settings()->setAutomaticExpungeEnabled(m_ui->autoExpungeCheck->isChecked()); m_parentResource->settings()->setUseDefaultIdentity(m_ui->useDefaultIdentityCheck->isChecked()); if (!m_ui->useDefaultIdentityCheck->isChecked()) { m_parentResource->settings()->setAccountIdentity(m_identityCombobox->currentIdentity()); } m_parentResource->settings()->setIntervalCheckEnabled(m_ui->enableMailCheckBox->isChecked()); if (m_ui->enableMailCheckBox->isChecked()) { m_parentResource->settings()->setIntervalCheckTime(m_ui->checkInterval->value()); } m_parentResource->settings()->setSieveCustomUsername(m_ui->customUsername->text()); QAbstractButton *checkedButton = m_ui->customSieveGroup->checkedButton(); if (checkedButton == m_ui->imapUserPassword) { m_parentResource->settings()->setSieveCustomAuthentification(QStringLiteral("ImapUserPassword")); } else if (checkedButton == m_ui->noAuthentification) { m_parentResource->settings()->setSieveCustomAuthentification(QStringLiteral("NoAuthentification")); } else if (checkedButton == m_ui->customUserPassword) { m_parentResource->settings()->setSieveCustomAuthentification(QStringLiteral("CustomUserPassword")); } m_parentResource->settings()->setSieveCustomPassword(m_ui->customPassword->password()); m_parentResource->settings()->save(); qCDebug(IMAPRESOURCE_LOG) << "wrote" << m_ui->imapServer->text() << m_ui->userName->text() << m_ui->safeImapGroup->checkedId(); if (m_oldResourceName != m_ui->accountName->text() && !m_ui->accountName->text().isEmpty()) { m_parentResource->settings()->renameRootCollection(m_ui->accountName->text()); } accept(); } void SetupServer::readSettings() { m_folderArchiveSettingPage->loadSettings(); m_ui->accountName->setText(m_parentResource->name()); m_oldResourceName = m_ui->accountName->text(); KUser *currentUser = new KUser(); KEMailSettings esetting; m_ui->imapServer->setText( !m_parentResource->settings()->imapServer().isEmpty() ? m_parentResource->settings()->imapServer() : esetting.getSetting(KEMailSettings::InServer)); m_ui->portSpin->setValue(m_parentResource->settings()->imapPort()); m_ui->userName->setText( !m_parentResource->settings()->userName().isEmpty() ? m_parentResource->settings()->userName() : currentUser->loginName()); const QString safety = m_parentResource->settings()->safety(); int i = 0; if (safety == QLatin1String("SSL")) { i = KIMAP::LoginJob::SSLorTLS; } else if (safety == QLatin1String("STARTTLS")) { i = KIMAP::LoginJob::STARTTLS; } else { i = KIMAP::LoginJob::Unencrypted; } QAbstractButton *safetyButton = m_ui->safeImapGroup->button(i); if (safetyButton) { safetyButton->setChecked(true); } populateDefaultAuthenticationOptions(); i = m_parentResource->settings()->authentication(); qCDebug(IMAPRESOURCE_LOG) << "read IMAP auth mode: " << authenticationModeString((MailTransport::Transport::EnumAuthenticationType::type)i); setCurrentAuthMode(m_ui->authenticationCombo, (MailTransport::Transport::EnumAuthenticationType::type)i); i = m_parentResource->settings()->alternateAuthentication(); setCurrentAuthMode(m_ui->authenticationAlternateCombo, (MailTransport::Transport::EnumAuthenticationType::type)i); bool rejected = false; const QString password = m_parentResource->settings()->password(&rejected); if (rejected) { m_ui->password->setEnabled(false); KMessageBox::information(nullptr, i18n("Could not access KWallet. " "If you want to store the password permanently then you have to " "activate it. If you do not " "want to use KWallet, check the box below, but note that you will be " "prompted for your password when needed."), i18n("Do not use KWallet"), QStringLiteral("warning_kwallet_disabled")); } else { m_ui->password->lineEdit()->insert(password); } m_ui->subscriptionEnabled->setChecked(m_parentResource->settings()->subscriptionEnabled()); m_ui->checkInterval->setValue(m_parentResource->settings()->intervalCheckTime()); m_ui->disconnectedModeEnabled->setChecked(m_parentResource->settings()->disconnectedModeEnabled()); + m_ui->useProxyCheck->setChecked(m_parentResource->settings()->useProxy()); m_ui->managesieveCheck->setChecked(m_parentResource->settings()->sieveSupport()); m_ui->sameConfigCheck->setChecked(m_parentResource->settings()->sieveReuseConfig()); m_ui->sievePortSpin->setValue(m_parentResource->settings()->sievePort()); m_ui->alternateURL->setText(m_parentResource->settings()->sieveAlternateUrl()); m_vacationFileName = m_parentResource->settings()->sieveVacationFilename(); Akonadi::Collection trashCollection(m_parentResource->settings()->trashCollection()); if (trashCollection.isValid()) { Akonadi::CollectionFetchJob *fetchJob = new Akonadi::CollectionFetchJob(trashCollection, Akonadi::CollectionFetchJob::Base, this); connect(fetchJob, &Akonadi::CollectionFetchJob::collectionsReceived, this, &SetupServer::targetCollectionReceived); } else { Akonadi::SpecialMailCollectionsRequestJob *requestJob = new Akonadi::SpecialMailCollectionsRequestJob(this); connect(requestJob, &Akonadi::SpecialMailCollectionsRequestJob::result, this, &SetupServer::localFolderRequestJobFinished); requestJob->requestDefaultCollection(Akonadi::SpecialMailCollections::Trash); requestJob->start(); } m_ui->useDefaultIdentityCheck->setChecked(m_parentResource->settings()->useDefaultIdentity()); if (!m_ui->useDefaultIdentityCheck->isChecked()) { m_identityCombobox->setCurrentIdentity(m_parentResource->settings()->accountIdentity()); } m_ui->enableMailCheckBox->setChecked(m_parentResource->settings()->intervalCheckEnabled()); if (m_ui->enableMailCheckBox->isChecked()) { m_ui->checkInterval->setValue(m_parentResource->settings()->intervalCheckTime()); } else { m_ui->checkInterval->setEnabled(false); } m_ui->autoExpungeCheck->setChecked(m_parentResource->settings()->automaticExpungeEnabled()); if (m_vacationFileName.isEmpty()) { m_vacationFileName = QStringLiteral("kmail-vacation.siv"); } m_ui->customUsername->setText(m_parentResource->settings()->sieveCustomUsername()); rejected = false; const QString customPassword = m_parentResource->settings()->sieveCustomPassword(&rejected); if (rejected) { m_ui->customPassword->setEnabled(false); KMessageBox::information(nullptr, i18n("Could not access KWallet. " "If you want to store the password permanently then you have to " "activate it. If you do not " "want to use KWallet, check the box below, but note that you will be " "prompted for your password when needed."), i18n("Do not use KWallet"), QStringLiteral("warning_kwallet_disabled")); } else { m_ui->customPassword->lineEdit()->insert(customPassword); } const QString sieverCustomAuth(m_parentResource->settings()->sieveCustomAuthentification()); if (sieverCustomAuth == QLatin1String("ImapUserPassword")) { m_ui->imapUserPassword->setChecked(true); } else if (sieverCustomAuth == QLatin1String("NoAuthentification")) { m_ui->noAuthentification->setChecked(true); } else if (sieverCustomAuth == QLatin1String("CustomUserPassword")) { m_ui->customUserPassword->setChecked(true); } delete currentUser; } void SetupServer::slotTest() { qCDebug(IMAPRESOURCE_LOG) << m_ui->imapServer->text(); m_ui->testButton->setEnabled(false); m_ui->safeImap->setEnabled(false); m_ui->authenticationCombo->setEnabled(false); m_ui->testInfo->clear(); m_ui->testInfo->hide(); delete m_serverTest; m_serverTest = new MailTransport::ServerTest(this); #ifndef QT_NO_CURSOR qApp->setOverrideCursor(Qt::BusyCursor); #endif const QString server = m_ui->imapServer->text(); const int port = m_ui->portSpin->value(); qCDebug(IMAPRESOURCE_LOG) << "server: " << server << "port: " << port; m_serverTest->setServer(server); if (port != 143 && port != 993) { m_serverTest->setPort(MailTransport::Transport::EnumEncryption::None, port); m_serverTest->setPort(MailTransport::Transport::EnumEncryption::SSL, port); } m_serverTest->setProtocol(QStringLiteral("imap")); m_serverTest->setProgressBar(m_ui->testProgress); connect(m_serverTest, &MailTransport::ServerTest::finished, this, &SetupServer::slotFinished); mOkButton->setEnabled(false); m_serverTest->start(); } void SetupServer::slotFinished(const QVector &testResult) { qCDebug(IMAPRESOURCE_LOG) << testResult; #ifndef QT_NO_CURSOR qApp->restoreOverrideCursor(); #endif mOkButton->setEnabled(true); using namespace MailTransport; if (!m_serverTest->isNormalPossible() && !m_serverTest->isSecurePossible()) { KMessageBox::sorry(this, i18n("Unable to connect to the server, please verify the server address.")); } m_ui->testInfo->show(); m_ui->sslRadio->setEnabled(testResult.contains(Transport::EnumEncryption::SSL)); m_ui->tlsRadio->setEnabled(testResult.contains(Transport::EnumEncryption::TLS)); m_ui->noRadio->setEnabled(testResult.contains(Transport::EnumEncryption::None)); QString text; if (testResult.contains(Transport::EnumEncryption::TLS)) { m_ui->tlsRadio->setChecked(true); text = i18n("STARTTLS is supported and recommended."); } else if (testResult.contains(Transport::EnumEncryption::SSL)) { m_ui->sslRadio->setChecked(true); text = i18n("SSL/TLS is supported and recommended."); } else if (testResult.contains(Transport::EnumEncryption::None)) { m_ui->noRadio->setChecked(true); text = i18n("No security is supported. It is not " "recommended to connect to this server."); } else { text = i18n("It is not possible to use this server."); } m_ui->testInfo->setText(text); m_ui->testButton->setEnabled(true); m_ui->safeImap->setEnabled(true); m_ui->authenticationCombo->setEnabled(true); slotEncryptionRadioChanged(); slotSafetyChanged(); } void SetupServer::slotTestChanged() { delete m_serverTest; m_serverTest = nullptr; slotSafetyChanged(); // do not use imapConnectionPossible, as the data is not yet saved. m_ui->testButton->setEnabled(true /* TODO && Global::connectionPossible() || m_ui->imapServer->text() == "localhost"*/); } void SetupServer::slotEnableWidgets() { const bool haveSieve = m_ui->managesieveCheck->isChecked(); const bool reuseConfig = m_ui->sameConfigCheck->isChecked(); m_ui->sameConfigCheck->setEnabled(haveSieve); m_ui->sievePortSpin->setEnabled(haveSieve); m_ui->alternateURL->setEnabled(haveSieve && !reuseConfig); m_ui->authentification->setEnabled(haveSieve && !reuseConfig); } void SetupServer::slotComplete() { const bool ok = !m_ui->imapServer->text().isEmpty() && !m_ui->userName->text().isEmpty(); mOkButton->setEnabled(ok); } void SetupServer::slotSafetyChanged() { if (m_serverTest == nullptr) { return; } QVector protocols; switch (m_ui->safeImapGroup->checkedId()) { case KIMAP::LoginJob::Unencrypted: qCDebug(IMAPRESOURCE_LOG) << "safeImapGroup: unencrypted"; protocols = m_serverTest->normalProtocols(); break; case KIMAP::LoginJob::SSLorTLS: protocols = m_serverTest->secureProtocols(); qCDebug(IMAPRESOURCE_LOG) << "safeImapGroup: SSL"; break; case KIMAP::LoginJob::STARTTLS: protocols = m_serverTest->tlsProtocols(); qCDebug(IMAPRESOURCE_LOG) << "safeImapGroup: starttls"; break; default: qFatal("Shouldn't happen"); } m_ui->authenticationCombo->clear(); addAuthenticationItem(m_ui->authenticationCombo, MailTransport::Transport::EnumAuthenticationType::CLEAR); for (int prot : qAsConst(protocols)) { addAuthenticationItem(m_ui->authenticationCombo, (MailTransport::Transport::EnumAuthenticationType::type)prot); } if (protocols.isEmpty()) { qCDebug(IMAPRESOURCE_LOG) << "no authmodes found"; } else { setCurrentAuthMode(m_ui->authenticationCombo, (MailTransport::Transport::EnumAuthenticationType::type)protocols.first()); } } void SetupServer::slotManageSubscriptions() { qCDebug(IMAPRESOURCE_LOG) << "manage subscripts"; ImapAccount account; account.setServer(m_ui->imapServer->text()); account.setPort(m_ui->portSpin->value()); account.setUserName(m_ui->userName->text()); account.setSubscriptionEnabled(m_ui->subscriptionEnabled->isChecked()); account.setEncryptionMode( static_cast(m_ui->safeImapGroup->checkedId()) ); account.setAuthenticationMode(Settings::mapTransportAuthToKimap(getCurrentAuthMode(m_ui->authenticationCombo))); QPointer subscriptions = new SubscriptionDialog(this); subscriptions->setWindowTitle(i18n("Serverside Subscription")); subscriptions->setWindowIcon(QIcon::fromTheme(QStringLiteral("network-server"))); subscriptions->connectAccount(account, m_ui->password->password()); m_subscriptionsChanged = subscriptions->isSubscriptionChanged(); subscriptions->exec(); delete subscriptions; m_ui->subscriptionEnabled->setChecked(account.isSubscriptionEnabled()); } void SetupServer::slotShowServerInfo() { ServerInfoDialog *dialog = new ServerInfoDialog(m_parentResource, this); dialog->show(); } void SetupServer::targetCollectionReceived(const Akonadi::Collection::List &collections) { m_ui->folderRequester->setCollection(collections.first()); mOldTrash = collections.first(); } void SetupServer::localFolderRequestJobFinished(KJob *job) { if (!job->error()) { Akonadi::Collection targetCollection = Akonadi::SpecialMailCollections::self()->defaultCollection(Akonadi::SpecialMailCollections::Trash); Q_ASSERT(targetCollection.isValid()); m_ui->folderRequester->setCollection(targetCollection); mOldTrash = targetCollection; } } void SetupServer::populateDefaultAuthenticationOptions() { populateDefaultAuthenticationOptions(m_ui->authenticationCombo); populateDefaultAuthenticationOptions(m_ui->authenticationAlternateCombo); } void SetupServer::populateDefaultAuthenticationOptions(QComboBox *combo) { combo->clear(); addAuthenticationItem(combo, MailTransport::Transport::EnumAuthenticationType::CLEAR); addAuthenticationItem(combo, MailTransport::Transport::EnumAuthenticationType::LOGIN); addAuthenticationItem(combo, MailTransport::Transport::EnumAuthenticationType::PLAIN); addAuthenticationItem(combo, MailTransport::Transport::EnumAuthenticationType::CRAM_MD5); addAuthenticationItem(combo, MailTransport::Transport::EnumAuthenticationType::DIGEST_MD5); addAuthenticationItem(combo, MailTransport::Transport::EnumAuthenticationType::NTLM); addAuthenticationItem(combo, MailTransport::Transport::EnumAuthenticationType::GSSAPI); addAuthenticationItem(combo, MailTransport::Transport::EnumAuthenticationType::ANONYMOUS); addAuthenticationItem(combo, MailTransport::Transport::EnumAuthenticationType::XOAUTH2); } void SetupServer::slotServerChanged() { populateDefaultAuthenticationOptions(m_ui->authenticationCombo); } diff --git a/resources/imap/setupserverview_desktop.ui b/resources/imap/setupserverview_desktop.ui index fc3b5fb4b..c6a9e2f80 100644 --- a/resources/imap/setupserverview_desktop.ui +++ b/resources/imap/setupserverview_desktop.ui @@ -1,695 +1,702 @@ SetupServerView 0 0 467 582 0 0 0 0 0 General Account Information Account Name: true Indicate the IMAP server. If you want to connect to a non-standard port for a specific encryption scheme, you can add ":port" to indicate that. For example: "imap.foo.com:144". I&MAP Server: imapServer true The username. Use&rname: userName true The password. Password: password Mail Checking Options &Download all messages for offline use Enable &interval mail checking Check mail interval: 0 1 Qt::Vertical 20 40 Filtering Server supports Sieve Reuse host and login configuration The server port changed when ManageSieve turned into a full RFC Standard. Old server implementations still use port 2000, while newer standard conform server can only be accessed via port 4190. true Managesieve port: 65535 Alternate Server: true Authentication true No authentication customSieveGroup &Username and Password customSieveGroup I&MAP Username and Password true customSieveGroup Password: Username: Authentication: Clear text LOGIN PLAIN CRAM-MD5 DIGEST-MD5 NTLM GSSAPI Anonymous Qt::Vertical 20 40 Advanced IMAP Settings Enable server-side subscriptions false Serverside Subscription... Automaticall&y compact folders (expunges deleted messages) Trash folder: Identity Settings Use the default identity for this account Use &default identity Select the KMail identity used for this account Identity: <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN" "http://www.w3.org/TR/REC-html40/strict.dtd"> <html><head><meta name="qrichtext" content="1" /><style type="text/css"> p, li { white-space: pre-wrap; } </style></head><body style=" font-family:'HandelGotDLig'; font-size:10pt; font-weight:400; font-style:normal;"> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-weight:600;">SSL/TLS</span><span style=" font-family:'Sans Serif';"> is safe IMAP over port 993;</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-weight:600;">STARTTLS</span><span style=" font-family:'Sans Serif';"> will operate on port 143 and switch to a secure connection directly after connecting;</span></p> <p style=" margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><span style=" font-family:'Sans Serif'; font-weight:600;">None</span><span style=" font-family:'Sans Serif';"> will connect to port 143 but not switch to a secure connection. This setting is not recommended.</span></p></body></html> Connection Settings Auto Detect QFormLayout::ExpandingFieldsGrow Encryption: None true safeImapGroup SSL/TLS safeImapGroup STARTTLS safeImapGroup Port: 1 65534 143 Authentication: Clear text LOGIN PLAIN CRAM-MD5 DIGEST-MD5 NTLM GSSAPI Anonymous + + + + Connect using the system proxy settings + + + 75 true Empty Qt::AlignCenter true 24 Server Info Qt::Vertical 20 40 KLineEdit QLineEdit
klineedit.h
1
KPluralHandlingSpinBox QSpinBox
kpluralhandlingspinbox.h
Akonadi::CollectionRequester QFrame
CollectionRequester
1
KPasswordLineEdit QWidget
kpasswordlineedit.h