9#include "transport_p.h"
10#include "transportmanager.h"
11#include "transporttype_p.h"
13#include "mailtransport_debug.h"
14#include <KConfigGroup>
15#include <KLocalizedString>
17#include <KStringHandler>
19#include <qt6keychain/keychain.h>
20using namespace QKeychain;
21using namespace MailTransport;
24 : TransportBase(cfgGroup)
25 , d(new TransportPrivate)
27 qCDebug(MAILTRANSPORT_LOG) << cfgGroup;
28 d->passwordLoaded =
false;
29 d->passwordDirty =
false;
30 d->storePasswordInFile =
false;
31 d->needsWalletMigration =
false;
40 return (
id() > 0) && !host().isEmpty() && port() <= 65536;
43void Transport::loadPassword()
45 if (!d->passwordLoaded && requiresAuthentication() && storePassword() && d->password.isEmpty()) {
57 d->passwordLoaded =
true;
58 if (d->password == passwd) {
61 d->passwordDirty =
true;
71 if (t->id() !=
id()) {
72 existingNames << t->name();
77 while (existingNames.
contains(name())) {
79 i18nc(
"%1: name; %2: number appended to it to make "
80 "it unique among a list of names",
91 if (original ==
this) {
92 qCWarning(MAILTRANSPORT_LOG) <<
"Tried to update password state of non-cloned transport.";
96 d->password = original->d->password;
97 d->passwordLoaded = original->d->passwordLoaded;
98 d->passwordDirty = original->d->passwordDirty;
101 qCWarning(MAILTRANSPORT_LOG) <<
"Transport with this ID not managed by transport manager.";
107 return !requiresAuthentication() || !storePassword() || d->passwordLoaded;
118 case EnumAuthenticationType::LOGIN:
119 return QStringLiteral(
"LOGIN");
120 case EnumAuthenticationType::PLAIN:
121 return QStringLiteral(
"PLAIN");
122 case EnumAuthenticationType::CRAM_MD5:
123 return QStringLiteral(
"CRAM-MD5");
124 case EnumAuthenticationType::DIGEST_MD5:
125 return QStringLiteral(
"DIGEST-MD5");
126 case EnumAuthenticationType::NTLM:
127 return QStringLiteral(
"NTLM");
128 case EnumAuthenticationType::GSSAPI:
129 return QStringLiteral(
"GSSAPI");
130 case EnumAuthenticationType::CLEAR:
131 return i18nc(
"Authentication method",
"Clear text");
132 case EnumAuthenticationType::APOP:
133 return QStringLiteral(
"APOP");
134 case EnumAuthenticationType::ANONYMOUS:
135 return i18nc(
"Authentication method",
"Anonymous");
136 case EnumAuthenticationType::XOAUTH2:
137 return QStringLiteral(
"XOAUTH2");
143void Transport::usrRead()
145 TransportBase::usrRead();
147 setHost(host().trimmed());
149 if (d->oldName.isEmpty()) {
156 d->transportType.d->mIdentifier = identifier();
161 int index = types.
indexOf(d->transportType);
163 d->transportType = types[index];
165 qCWarning(MAILTRANSPORT_LOG) <<
"Type unknown to manager.";
166 d->transportType.d->mName =
i18nc(
"An unknown transport type",
"Unknown");
172 if (!storePassword()) {
176 if (d->passwordLoaded) {
182 if (group.hasKey(
"password")) {
186 if (!d->password.isEmpty()) {
187 d->passwordLoaded =
true;
188 if (QKeychain::isAvailable()) {
192 d->needsWalletMigration =
true;
194 d->storePasswordInFile =
true;
199bool Transport::usrSave()
201 if (requiresAuthentication() && storePassword() && d->passwordDirty) {
202 const QString storePassword = d->password;
203 auto writeJob =
new WritePasswordJob(WALLET_FOLDER,
this);
204 connect(writeJob, &Job::finished,
this, [
this, writeJob, storePassword] {
205 if (writeJob->error()) {
206 qWarning(MAILTRANSPORT_LOG()) <<
"WritePasswordJob failed with: " << writeJob->errorString();
208 if (d->storePasswordInFile
210 i18n(
"QKeychain not found a backend for storing your password. "
211 "It is strongly recommended to use strong backend for managing your passwords.\n"
212 "However, the password can be stored in the configuration "
213 "file instead. The password is stored in an obfuscated format, "
214 "but should not be considered secure from decryption efforts "
215 "if access to the configuration file is obtained.\n"
216 "Do you want to store the password for server '%1' in the "
217 "configuration file?",
219 i18nc(
"@title:window",
"KWallet Not Available"),
222 == KMessageBox::ButtonCode::PrimaryAction) {
226 d->storePasswordInFile =
true;
232 writeJob->setTextData(storePassword);
237 d->passwordDirty =
false;
240 if (!TransportBase::usrSave()) {
244 if (
name() != d->oldName) {
252void Transport::readPassword()
255 if (!requiresAuthentication()) {
258 d->passwordLoaded =
true;
260 auto readJob =
new ReadPasswordJob(WALLET_FOLDER,
this);
261 connect(readJob, &Job::finished,
this, &Transport::readTransportPasswordFinished);
266void Transport::readTransportPasswordFinished(QKeychain::Job *baseJob)
268 auto job = qobject_cast<ReadPasswordJob *>(baseJob);
272 d->passwordLoaded =
false;
273 qCWarning(MAILTRANSPORT_LOG) <<
"We have an error during reading password for" << id() << job->errorString();
283 return d->needsWalletMigration;
288 qCDebug(MAILTRANSPORT_LOG) <<
"migrating" << id() <<
"to wallet";
289 d->needsWalletMigration =
false;
292 d->passwordDirty =
true;
293 d->storePasswordInFile =
false;
305 if (!d->transportType.isValid()) {
306 qCWarning(MAILTRANSPORT_LOG) <<
"Invalid transport type.";
308 return d->transportType;
311#include "moc_transport.cpp"
void deleteEntry(const char *key, WriteConfigFlags pFlags=Normal)
TransportType::List types() const
Returns a list of all available transport types.
Transport * transportById(Transport::Id id, bool def=true) const
Returns the Transport object with the given id.
static TransportManager * self()
Returns the TransportManager instance.
QList< Transport * > transports() const
Returns a list of all available transports.
A representation of a transport type.
Represents the settings of a specific mail transport.
void migrateToWallet()
Try to migrate the password from the config file to the wallet.
void passwordLoaded()
Emitted when passwords have been loaded from QKeyChain.
void passwordChanged()
Emitted when the password is changed.
void forceUniqueName()
Makes sure the transport has a unique name.
bool needsWalletMigration() const
Returns true if the password was not stored in the wallet.
void transportTypeChanged()
Emitted when the transport type is changed.
void setPassword(const QString &passwd)
Sets the password of this transport.
QString authenticationTypeString() const
Returns a string representation of the authentication type.
bool isComplete() const
Returns true if all settings have been loaded.
Transport * clone() const
Returns a deep copy of this Transport object which will no longer be automatically updated.
void updatePasswordState()
This function synchronizes the password of this transport with the password of the transport with the...
~Transport() override
Destructor.
Q_INVOKABLE bool isValid() const
Returns true if this transport is valid, ie.
Transport(const QString &cfgGroup)
Creates a Transport object.
QString i18nc(const char *context, const char *text, const TYPE &arg...)
QString i18n(const char *text, const TYPE &arg...)
Internal file containing constant definitions etc.
ButtonCode warningTwoActions(QWidget *parent, const QString &text, const QString &title, const KGuiItem &primaryAction, const KGuiItem &secondaryAction, const QString &dontAskAgainName=QString(), Options options=Options(Notify|Dangerous))
QString name(StandardAction id)
KCOREADDONS_EXPORT QString obscure(const QString &str)
int exec(ProcessEventsFlags flags)
qsizetype indexOf(const AT &value, qsizetype from) const const
QString mid(qsizetype position, qsizetype n) const const
QString number(double n, char format, int precision)
bool contains(QLatin1StringView str, Qt::CaseSensitivity cs) const const
QFuture< ArgsType< Signal > > connect(Sender *sender, Signal signal)