diff --git a/src/kmailtransport/mailtransport.kcfg b/src/kmailtransport/mailtransport.kcfg
index 1242b2b..466ebc9 100644
--- a/src/kmailtransport/mailtransport.kcfg
+++ b/src/kmailtransport/mailtransport.kcfg
@@ -1,103 +1,108 @@
0The name that will be used when referring to this server.i18n("Unnamed")SMTPThe domain name or numerical address of the SMTP server.The port number that the SMTP server is listening on. The default port is 25.25The user name to send to the server for authorization.A command to run locally, prior to sending email. This can be used to set up SSH tunnels, for example. Leave it empty if no command should be run.Check this option if your SMTP server requires authentication before accepting mail. This is known as 'Authenticated SMTP' or simply ASMTP.falseCheck this option to have your password stored.
If KWallet is available the password will be stored there, which is considered safe.
However, if KWallet is not available, the password will be stored in the configuration file. The password is stored in an obfuscated format, but should not be considered secure from decryption efforts if access to the configuration file is obtained.falsePLAINCheck this option to use a custom hostname when identifying to the mail server. This is useful when your system's hostname may not be set correctly or to mask your system's true hostname.falseEnter the hostname that should be used when identifying to the server.Check this option to use a custom sender address when identifying to the mail server. If not checked, the address from the identity is used.falseEnter the address that should be used to overwrite the default sender address.
+
+
+ If checked, the system proxy settings will be used to connect to the mail server.
+ false
+
diff --git a/src/kmailtransport/plugins/smtp/smtpjob.cpp b/src/kmailtransport/plugins/smtp/smtpjob.cpp
index 1e57f1d..2f7f1da 100644
--- a/src/kmailtransport/plugins/smtp/smtpjob.cpp
+++ b/src/kmailtransport/plugins/smtp/smtpjob.cpp
@@ -1,359 +1,360 @@
/*
Copyright (c) 2007 Volker Krause
Based on KMail code by:
Copyright (c) 1996-1998 Stefan Taferner
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 "smtpjob.h"
#include "transport.h"
#include "mailtransport_defs.h"
#include "precommandjob.h"
#include "sessionuiproxy.h"
#include "mailtransportplugin_smtp_debug.h"
#include
#include
#include
#include
#include "mailtransport_debug.h"
#include
#include
#include
#include
using namespace MailTransport;
class SessionPool
{
public:
SessionPool() : ref(0)
{
}
int ref;
QHash sessions;
void removeSession(KSmtp::Session *session)
{
qCDebug(MAILTRANSPORT_SMTP_LOG) << "Removing session" << session << "from the pool";
int key = sessions.key(session);
if (key > 0) {
QObject::connect(session, &KSmtp::Session::stateChanged,
[session](KSmtp::Session::State state) {
if (state == KSmtp::Session::Disconnected) {
session->deleteLater();
}
});
session->quit();
sessions.remove(key);
}
}
};
Q_GLOBAL_STATIC(SessionPool, s_sessionPool)
/**
* Private class that helps to provide binary compatibility between releases.
* @internal
*/
class SmtpJobPrivate
{
public:
SmtpJobPrivate(SmtpJob *parent) : q(parent)
{
}
SmtpJob *q;
KSmtp::Session *session = nullptr;
KSmtp::SessionUiProxy::Ptr uiProxy;
enum State {
Idle, Precommand, Smtp
} currentState;
bool finished;
};
SmtpJob::SmtpJob(Transport *transport, QObject *parent)
: TransportJob(transport, parent)
, d(new SmtpJobPrivate(this))
{
d->currentState = SmtpJobPrivate::Idle;
d->session = nullptr;
d->finished = false;
d->uiProxy = KSmtp::SessionUiProxy::Ptr(new SmtpSessionUiProxy);
if (!s_sessionPool.isDestroyed()) {
s_sessionPool->ref++;
}
}
SmtpJob::~SmtpJob()
{
if (!s_sessionPool.isDestroyed()) {
s_sessionPool->ref--;
if (s_sessionPool->ref == 0) {
qCDebug(MAILTRANSPORT_SMTP_LOG) << "clearing SMTP session pool" << s_sessionPool->sessions.count();
while (!s_sessionPool->sessions.isEmpty()) {
s_sessionPool->removeSession(*(s_sessionPool->sessions.begin()));
}
}
}
delete d;
}
void SmtpJob::doStart()
{
if (s_sessionPool.isDestroyed()) {
return;
}
if ((!s_sessionPool->sessions.isEmpty()
&& s_sessionPool->sessions.contains(transport()->id()))
|| transport()->precommand().isEmpty()) {
d->currentState = SmtpJobPrivate::Smtp;
startSmtpJob();
} else {
d->currentState = SmtpJobPrivate::Precommand;
PrecommandJob *job = new PrecommandJob(transport()->precommand(), this);
addSubjob(job);
job->start();
}
}
void SmtpJob::startSmtpJob()
{
if (s_sessionPool.isDestroyed()) {
return;
}
d->session = s_sessionPool->sessions.value(transport()->id());
if (!d->session) {
d->session = new KSmtp::Session(transport()->host(), transport()->port());
+ d->session->setUseNetworkProxy(transport()->useProxy());
d->session->setUiProxy(d->uiProxy);
if (transport()->specifyHostname()) {
d->session->setCustomHostname(transport()->localHostname());
}
s_sessionPool->sessions.insert(transport()->id(), d->session);
}
connect(d->session, &KSmtp::Session::stateChanged,
this, &SmtpJob::sessionStateChanged, Qt::UniqueConnection);
connect(d->session, &KSmtp::Session::connectionError,
this, [this](const QString &err) {
setError(KJob::UserDefinedError);
setErrorText(err);
s_sessionPool->removeSession(d->session);
emitResult();
});
if (d->session->state() == KSmtp::Session::Disconnected) {
d->session->open();
} else {
if (d->session->state() != KSmtp::Session::Authenticated) {
startLoginJob();
}
startSendJob();
}
}
void SmtpJob::sessionStateChanged(KSmtp::Session::State state)
{
if (state == KSmtp::Session::Ready) {
startLoginJob();
} else if (state == KSmtp::Session::Authenticated) {
startSendJob();
}
}
void SmtpJob::startLoginJob()
{
if (!transport()->requiresAuthentication()) {
startSendJob();
return;
}
auto login = new KSmtp::LoginJob(d->session);
auto user = transport()->userName();
auto passwd = transport()->password();
if ((user.isEmpty() || passwd.isEmpty())
&& transport()->authenticationType() != Transport::EnumAuthenticationType::GSSAPI) {
QPointer dlg
= new KPasswordDialog(
nullptr,
KPasswordDialog::ShowUsernameLine
|KPasswordDialog::ShowKeepPassword);
dlg->setPrompt(i18n("You need to supply a username and a password "
"to use this SMTP server."));
dlg->setKeepPassword(transport()->storePassword());
dlg->addCommentLine(QString(), transport()->name());
dlg->setUsername(user);
dlg->setPassword(passwd);
bool gotIt = false;
if (dlg->exec()) {
transport()->setUserName(dlg->username());
transport()->setPassword(dlg->password());
transport()->setStorePassword(dlg->keepPassword());
transport()->save();
gotIt = true;
}
delete dlg;
if (!gotIt) {
setError(KilledJobError);
emitResult();
return;
}
}
login->setUserName(transport()->userName());
login->setPassword(transport()->password());
switch (transport()->authenticationType()) {
case TransportBase::EnumAuthenticationType::PLAIN:
login->setPreferedAuthMode(KSmtp::LoginJob::Plain);
break;
case TransportBase::EnumAuthenticationType::LOGIN:
login->setPreferedAuthMode(KSmtp::LoginJob::Login);
break;
case TransportBase::EnumAuthenticationType::CRAM_MD5:
login->setPreferedAuthMode(KSmtp::LoginJob::CramMD5);
break;
case TransportBase::EnumAuthenticationType::XOAUTH2:
login->setPreferedAuthMode(KSmtp::LoginJob::XOAuth);
break;
case TransportBase::EnumAuthenticationType::DIGEST_MD5:
login->setPreferedAuthMode(KSmtp::LoginJob::DigestMD5);
break;
case TransportBase::EnumAuthenticationType::NTLM:
login->setPreferedAuthMode(KSmtp::LoginJob::NTLM);
break;
case TransportBase::EnumAuthenticationType::GSSAPI:
login->setPreferedAuthMode(KSmtp::LoginJob::GSSAPI);
break;
default:
qCWarning(MAILTRANSPORT_SMTP_LOG) << "Unknown authentication mode" << transport()->authenticationTypeString();
break;
}
switch (transport()->encryption()) {
case Transport::EnumEncryption::None:
login->setEncryptionMode(KSmtp::LoginJob::Unencrypted);
break;
case Transport::EnumEncryption::TLS:
login->setEncryptionMode(KSmtp::LoginJob::TlsV1);
break;
case Transport::EnumEncryption::SSL:
login->setEncryptionMode(KSmtp::LoginJob::AnySslVersion);
break;
default:
qCWarning(MAILTRANSPORT_SMTP_LOG) << "Unknown encryption mode" << transport()->encryption();
break;
}
connect(login, &KJob::result, this, &SmtpJob::slotResult);
addSubjob(login);
login->start();
qCDebug(MAILTRANSPORT_SMTP_LOG) << "Login started";
}
void SmtpJob::startSendJob()
{
auto send = new KSmtp::SendJob(d->session);
send->setFrom(sender());
send->setTo(to());
send->setCc(cc());
send->setBcc(bcc());
send->setData(data());
addSubjob(send);
send->start();
qCDebug(MAILTRANSPORT_SMTP_LOG) << "Send started";
}
bool SmtpJob::doKill()
{
if (s_sessionPool.isDestroyed()) {
return false;
}
if (!hasSubjobs()) {
return true;
}
if (d->currentState == SmtpJobPrivate::Precommand) {
return subjobs().first()->kill();
} else if (d->currentState == SmtpJobPrivate::Smtp) {
clearSubjobs();
s_sessionPool->removeSession(d->session);
return true;
}
return false;
}
void SmtpJob::slotResult(KJob *job)
{
if (s_sessionPool.isDestroyed()) {
return;
}
// The job has finished, so we don't care about any further errors. Set
// d->finished to true, so slaveError() knows about this and doesn't call
// emitResult() anymore.
// Sometimes, the SMTP slave emits more than one error
//
// The first error causes slotResult() to be called, but not slaveError(), since
// the scheduler doesn't emit errors for connected slaves.
//
// The second error then causes slaveError() to be called (as the slave is no
// longer connected), which does emitResult() a second time, which is invalid
// (and triggers an assert in KMail).
d->finished = true;
// Normally, calling TransportJob::slotResult() whould set the proper error code
// for error() via KComposite::slotResult(). However, we can't call that here,
// since that also emits the result signal.
// In KMail, when there are multiple mails in the outbox, KMail tries to send
// the next mail when it gets the result signal, which then would reuse the
// old broken slave from the slave pool if there was an error.
// To prevent that, we call TransportJob::slotResult() only after removing the
// slave from the pool and calculate the error code ourselves.
int errorCode = error();
if (!errorCode) {
errorCode = job->error();
}
if (errorCode && d->currentState == SmtpJobPrivate::Smtp) {
s_sessionPool->removeSession(d->session);
TransportJob::slotResult(job);
return;
}
TransportJob::slotResult(job);
if (!error() && d->currentState == SmtpJobPrivate::Precommand) {
d->currentState = SmtpJobPrivate::Smtp;
startSmtpJob();
return;
}
if (!error() && !hasSubjobs()) {
emitResult();
}
}
#include "moc_smtpjob.cpp"
diff --git a/src/kmailtransport/plugins/smtp/smtpsettings.ui b/src/kmailtransport/plugins/smtp/smtpsettings.ui
index c66256b..9841f37 100644
--- a/src/kmailtransport/plugins/smtp/smtpsettings.ui
+++ b/src/kmailtransport/plugins/smtp/smtpsettings.ui
@@ -1,572 +1,579 @@
Volker Krause <vkrause@kde.org>, KovoKs <tomalbers@kde.nl>SMTPSettings0041147400000GeneralAccount InformationOutgoing &mail server:Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenterkcfg_hosttruefalse&Login:Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenterkcfg_userNamefalsetruefalseP&assword:Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenterpasswordfalsefalse&Store SMTP passwordServer &requires authenticationQt::Vertical2040AdvancedtrueConnection Settings0Auto Detect0falseQFrame::BoxQFrame::Plain0This server does not support authenticationQt::AlignCenterQFormLayout::ExpandingFieldsGrowEncryption:&None&SSL&TLS&Port:Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenterkcfg_port16553525Authentication:
+
+
+
+ Connect using the system proxy settings
+
+
+ SMTP SettingsSen&d custom hostname to serverfalseHostna&me:Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenterkcfg_localHostnamefalsetrueUse custom sender addressfalseSender Address:falsetruePrecommand:Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCentertrueQt::Vertical200KLineEditQLineEditklineedit.hKPasswordLineEditQWidgetkpasswordlineedit.htabWidgetkcfg_hostkcfg_requiresAuthenticationkcfg_userNamepasswordkcfg_storePasswordcheckCapabilitiesencryptionNoneencryptionSslencryptionTlsauthCombokcfg_specifyHostnamekcfg_localHostnamekcfg_specifySenderOverwriteAddresskcfg_senderOverwriteAddresskcfg_precommandkcfg_specifyHostnametoggled(bool)hostnameLabelsetEnabled(bool)10124983277kcfg_specifyHostnametoggled(bool)kcfg_localHostnamesetEnabled(bool)196249199277kcfg_requiresAuthenticationtoggled(bool)kcfg_userNamesetEnabled(bool)372110372137kcfg_requiresAuthenticationtoggled(bool)usernameLabelsetEnabled(bool)372110141137kcfg_requiresAuthenticationtoggled(bool)passwordLabelsetEnabled(bool)372110128164kcfg_requiresAuthenticationtoggled(bool)passwordsetEnabled(bool)372110372164kcfg_requiresAuthenticationtoggled(bool)kcfg_storePasswordsetEnabled(bool)372110372189kcfg_specifySenderOverwriteAddresstoggled(bool)label_2setEnabled(bool)5929978312kcfg_specifySenderOverwriteAddresstoggled(bool)kcfg_senderOverwriteAddresssetEnabled(bool)152297169318