1 /* This file is part of the KDE project
2 
3    SPDX-FileCopyrightText: 2010 Klarälvdalens Datakonsult AB, a KDAB Group company <info@kdab.com>
4    SPDX-FileContributor: Kevin Ottens <kevin@kdab.com>
5 
6    SPDX-FileCopyrightText: 2010 Casey Link <unnamedrambler@gmail.com>
7    SPDX-FileCopyrightText: 2009-2010 Klaralvdalens Datakonsult AB, a KDAB Group company <info@kdab.net>
8    SPDX-FileCopyrightText: 2009 Kevin Ottens <ervin@kde.org>
9    SPDX-FileCopyrightText: 2006-2008 Omat Holding B.V. <info@omat.nl>
10    SPDX-FileCopyrightText: 2006 Frode M. Døving <frode@lnix.net>
11 
12    Original copied from showfoto:
13     SPDX-FileCopyrightText: 2005 Gilles Caulier <caulier.gilles@free.fr>
14 
15    SPDX-License-Identifier: GPL-2.0-or-later
16 */
17 
18 #include "setupserver.h"
19 #include "folderarchivesettingpage.h"
20 #include "imapresource.h"
21 #include "serverinfodialog.h"
22 #include "settings.h"
23 #include "utils.h"
24 #include <config-imap.h>
25 
26 #include <Libkdepim/LineEditCatchReturnKey>
27 #include <MailTransport/ServerTest>
28 #include <MailTransport/Transport>
29 
30 #include <KMime/Message>
31 
32 #include "imapresource_debug.h"
33 #include <Akonadi/CollectionFetchJob>
34 #include <Akonadi/CollectionModifyJob>
35 #include <Akonadi/EntityDisplayAttribute>
36 #include <Akonadi/KMime/SpecialMailCollections>
37 #include <Akonadi/KMime/SpecialMailCollectionsRequestJob>
38 #include <Akonadi/ResourceSettings>
39 #include <KAuthorized>
40 #include <KEMailSettings>
41 #include <KLocalizedString>
42 #include <KMessageBox>
43 #include <KUser>
44 #include <QNetworkConfigurationManager>
45 #include <QPushButton>
46 
47 #include <KIdentityManagement/IdentityCombo>
48 #include <KIdentityManagement/IdentityManager>
49 #include <QFontDatabase>
50 #include <QPointer>
51 #include <QVBoxLayout>
52 
53 #include "imapaccount.h"
54 #include "subscriptiondialog.h"
55 
56 #include "ui_setupserverview_desktop.h"
57 
58 /** static helper functions **/
authenticationModeString(MailTransport::Transport::EnumAuthenticationType::type mode)59 static QString authenticationModeString(MailTransport::Transport::EnumAuthenticationType::type mode)
60 {
61     switch (mode) {
62     case MailTransport::Transport::EnumAuthenticationType::LOGIN:
63         return QStringLiteral("LOGIN");
64     case MailTransport::Transport::EnumAuthenticationType::PLAIN:
65         return QStringLiteral("PLAIN");
66     case MailTransport::Transport::EnumAuthenticationType::CRAM_MD5:
67         return QStringLiteral("CRAM-MD5");
68     case MailTransport::Transport::EnumAuthenticationType::DIGEST_MD5:
69         return QStringLiteral("DIGEST-MD5");
70     case MailTransport::Transport::EnumAuthenticationType::GSSAPI:
71         return QStringLiteral("GSSAPI");
72     case MailTransport::Transport::EnumAuthenticationType::NTLM:
73         return QStringLiteral("NTLM");
74     case MailTransport::Transport::EnumAuthenticationType::CLEAR:
75         return i18nc("Authentication method", "Clear text");
76     case MailTransport::Transport::EnumAuthenticationType::ANONYMOUS:
77         return i18nc("Authentication method", "Anonymous");
78     case MailTransport::Transport::EnumAuthenticationType::XOAUTH2:
79         return i18nc("Authentication method", "Gmail");
80     default:
81         break;
82     }
83     return QString();
84 }
85 
setCurrentAuthMode(QComboBox * authCombo,MailTransport::Transport::EnumAuthenticationType::type authtype)86 static void setCurrentAuthMode(QComboBox *authCombo, MailTransport::Transport::EnumAuthenticationType::type authtype)
87 {
88     qCDebug(IMAPRESOURCE_LOG) << "setting authcombo: " << authenticationModeString(authtype);
89     int index = authCombo->findData(authtype);
90     if (index == -1) {
91         qCWarning(IMAPRESOURCE_LOG) << "desired authmode not in the combo";
92     }
93     qCDebug(IMAPRESOURCE_LOG) << "found corresponding index: " << index << "with data"
94                               << authenticationModeString((MailTransport::Transport::EnumAuthenticationType::type)authCombo->itemData(index).toInt());
95     authCombo->setCurrentIndex(index);
96     MailTransport::Transport::EnumAuthenticationType::type t =
97         (MailTransport::Transport::EnumAuthenticationType::type)authCombo->itemData(authCombo->currentIndex()).toInt();
98     qCDebug(IMAPRESOURCE_LOG) << "selected auth mode:" << authenticationModeString(t);
99     Q_ASSERT(t == authtype);
100 }
101 
getCurrentAuthMode(QComboBox * authCombo)102 static MailTransport::Transport::EnumAuthenticationType::type getCurrentAuthMode(QComboBox *authCombo)
103 {
104     MailTransport::Transport::EnumAuthenticationType::type authtype =
105         (MailTransport::Transport::EnumAuthenticationType::type)authCombo->itemData(authCombo->currentIndex()).toInt();
106     qCDebug(IMAPRESOURCE_LOG) << "current auth mode: " << authenticationModeString(authtype);
107     return authtype;
108 }
109 
addAuthenticationItem(QComboBox * authCombo,MailTransport::Transport::EnumAuthenticationType::type authtype)110 static void addAuthenticationItem(QComboBox *authCombo, MailTransport::Transport::EnumAuthenticationType::type authtype)
111 {
112     qCDebug(IMAPRESOURCE_LOG) << "adding auth item " << authenticationModeString(authtype);
113     authCombo->addItem(authenticationModeString(authtype), QVariant(authtype));
114 }
115 
SetupServer(ImapResourceBase * parentResource,WId parent)116 SetupServer::SetupServer(ImapResourceBase *parentResource, WId parent)
117     : QDialog()
118     , m_parentResource(parentResource)
119     , m_ui(new Ui::SetupServerView)
120     , mValidator(this)
121 {
122     auto networkConfigMgr = new QNetworkConfigurationManager(QCoreApplication::instance());
123 
124     m_parentResource->settings()->setWinId(parent);
125     auto mainWidget = new QWidget(this);
126     auto mainLayout = new QVBoxLayout(this);
127     mainLayout->addWidget(mainWidget);
128     auto buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, this);
129     mOkButton = buttonBox->button(QDialogButtonBox::Ok);
130     mOkButton->setDefault(true);
131     mOkButton->setShortcut(Qt::CTRL | Qt::Key_Return);
132     connect(mOkButton, &QPushButton::clicked, this, &SetupServer::applySettings);
133     connect(buttonBox, &QDialogButtonBox::rejected, this, &SetupServer::reject);
134     mainLayout->addWidget(buttonBox);
135 
136     m_ui->setupUi(mainWidget);
137     m_ui->password->setRevealPasswordAvailable(KAuthorized::authorize(QStringLiteral("lineedit_reveal_password")));
138     m_ui->customPassword->setRevealPasswordAvailable(KAuthorized::authorize(QStringLiteral("lineedit_reveal_password")));
139     new KPIM::LineEditCatchReturnKey(m_ui->accountName, this);
140     new KPIM::LineEditCatchReturnKey(m_ui->imapServer, this);
141     new KPIM::LineEditCatchReturnKey(m_ui->userName, this);
142     new KPIM::LineEditCatchReturnKey(m_ui->alternateURL, this);
143     new KPIM::LineEditCatchReturnKey(m_ui->customUsername, this);
144 
145     m_folderArchiveSettingPage = new FolderArchiveSettingPage(m_parentResource->identifier());
146     m_ui->tabWidget->addTab(m_folderArchiveSettingPage, i18n("Archive Folder"));
147     m_ui->safeImapGroup->setId(m_ui->noRadio, KIMAP::LoginJob::Unencrypted);
148     m_ui->safeImapGroup->setId(m_ui->sslRadio, KIMAP::LoginJob::SSLorTLS);
149     m_ui->safeImapGroup->setId(m_ui->tlsRadio, KIMAP::LoginJob::STARTTLS);
150 
151     connect(m_ui->noRadio, &QRadioButton::toggled, this, &SetupServer::slotSafetyChanged);
152     connect(m_ui->sslRadio, &QRadioButton::toggled, this, &SetupServer::slotSafetyChanged);
153     connect(m_ui->tlsRadio, &QRadioButton::toggled, this, &SetupServer::slotSafetyChanged);
154 
155     m_ui->testInfo->hide();
156     m_ui->testProgress->hide();
157     m_ui->accountName->setFocus();
158     m_ui->checkInterval->setSuffix(ki18np(" minute", " minutes"));
159     m_ui->checkInterval->setMinimum(Akonadi::ResourceSettings::self()->minimumCheckInterval());
160     m_ui->checkInterval->setMaximum(10000);
161     m_ui->checkInterval->setSingleStep(1);
162     m_ui->imapInfo->setFont(QFontDatabase::systemFont(QFontDatabase::SmallestReadableFont));
163 
164     // regex for evaluating a valid server name/ip
165     mValidator.setRegularExpression(QRegularExpression(QStringLiteral("[A-Za-z0-9_:.-]*")));
166     m_ui->imapServer->setValidator(&mValidator);
167 
168     m_ui->folderRequester->setMimeTypeFilter(QStringList() << KMime::Message::mimeType());
169     m_ui->folderRequester->setAccessRightsFilter(Akonadi::Collection::CanChangeItem | Akonadi::Collection::CanCreateItem | Akonadi::Collection::CanDeleteItem);
170     m_ui->folderRequester->changeCollectionDialogOptions(Akonadi::CollectionDialog::AllowToCreateNewChildCollection);
171     m_identityCombobox = new KIdentityManagement::IdentityCombo(KIdentityManagement::IdentityManager::self(), this);
172     m_identityCombobox->setShowDefault(true);
173     m_ui->formLayoutAdvanced->insertRow(3, i18n("Identity:"), m_identityCombobox);
174 
175     connect(m_ui->testButton, &QPushButton::pressed, this, &SetupServer::slotTest);
176 
177     connect(m_ui->imapServer, &QLineEdit::textChanged, this, &SetupServer::slotServerChanged);
178     connect(m_ui->imapServer, &QLineEdit::textChanged, this, &SetupServer::slotTestChanged);
179     connect(m_ui->imapServer, &QLineEdit::textChanged, this, &SetupServer::slotComplete);
180     connect(m_ui->userName, &QLineEdit::textChanged, this, &SetupServer::slotComplete);
181     connect(m_ui->subscriptionEnabled, &QCheckBox::toggled, this, &SetupServer::slotSubcriptionCheckboxChanged);
182     connect(m_ui->subscriptionButton, &QPushButton::pressed, this, &SetupServer::slotManageSubscriptions);
183 
184     connect(m_ui->managesieveCheck, &QCheckBox::toggled, this, &SetupServer::slotEnableWidgets);
185     connect(m_ui->sameConfigCheck, &QCheckBox::toggled, this, &SetupServer::slotEnableWidgets);
186 
187     connect(m_ui->enableMailCheckBox, &QCheckBox::toggled, this, &SetupServer::slotMailCheckboxChanged);
188     connect(m_ui->safeImapGroup, qOverload<QAbstractButton *>(&QButtonGroup::buttonClicked), this, &SetupServer::slotEncryptionRadioChanged);
189     connect(m_ui->customSieveGroup, qOverload<QAbstractButton *>(&QButtonGroup::buttonClicked), this, &SetupServer::slotCustomSieveChanged);
190     connect(m_ui->showServerInfo, &QPushButton::pressed, this, &SetupServer::slotShowServerInfo);
191 
192     readSettings();
193     slotTestChanged();
194     slotComplete();
195     slotCustomSieveChanged();
196     connect(networkConfigMgr, &QNetworkConfigurationManager::onlineStateChanged, this, &SetupServer::slotTestChanged);
197 }
198 
~SetupServer()199 SetupServer::~SetupServer()
200 {
201     delete m_ui;
202 }
203 
shouldClearCache() const204 bool SetupServer::shouldClearCache() const
205 {
206     return m_shouldClearCache;
207 }
208 
slotSubcriptionCheckboxChanged()209 void SetupServer::slotSubcriptionCheckboxChanged()
210 {
211     m_ui->subscriptionButton->setEnabled(m_ui->subscriptionEnabled->isChecked());
212 }
213 
slotMailCheckboxChanged()214 void SetupServer::slotMailCheckboxChanged()
215 {
216     m_ui->checkInterval->setEnabled(m_ui->enableMailCheckBox->isChecked());
217 }
218 
slotEncryptionRadioChanged()219 void SetupServer::slotEncryptionRadioChanged()
220 {
221     // TODO these really should be defined somewhere else
222     switch (m_ui->safeImapGroup->checkedId()) {
223     case KIMAP::LoginJob::Unencrypted:
224     case KIMAP::LoginJob::STARTTLS:
225         m_ui->portSpin->setValue(143);
226         break;
227     case KIMAP::LoginJob::SSLorTLS:
228         m_ui->portSpin->setValue(993);
229         break;
230     default:
231         qFatal("Shouldn't happen");
232     }
233 }
234 
slotCustomSieveChanged()235 void SetupServer::slotCustomSieveChanged()
236 {
237     QAbstractButton *checkedButton = m_ui->customSieveGroup->checkedButton();
238 
239     if (checkedButton == m_ui->imapUserPassword || checkedButton == m_ui->noAuthentification) {
240         m_ui->customUsername->setEnabled(false);
241         m_ui->customPassword->setEnabled(false);
242     } else if (checkedButton == m_ui->customUserPassword) {
243         m_ui->customUsername->setEnabled(true);
244         m_ui->customPassword->setEnabled(true);
245     }
246 }
247 
applySettings()248 void SetupServer::applySettings()
249 {
250     if (!m_parentResource->settings()->imapServer().isEmpty() && m_ui->imapServer->text() != m_parentResource->settings()->imapServer()) {
251         if (KMessageBox::warningContinueCancel(this,
252                                                i18n("You have changed the address of the server. Even if this is the same server as before "
253                                                     "we will have to re-download all your emails from this account again. "
254                                                     "Are you sure you want to proceed?"),
255                                                i18n("Server address change"))
256             == KMessageBox::Cancel) {
257             return;
258         }
259     }
260     if (!m_parentResource->settings()->userName().isEmpty() && m_ui->userName->text() != m_parentResource->settings()->userName()) {
261         if (KMessageBox::warningContinueCancel(this,
262                                                i18n("You have changed the user name. Even if this is a user name for the same account as before "
263                                                     "we will have to re-download all your emails from this account again. "
264                                                     "Are you sure you want to proceed?"),
265                                                i18n("User name change"))
266             == KMessageBox::Cancel) {
267             return;
268         }
269     }
270 
271     m_folderArchiveSettingPage->writeSettings();
272     m_shouldClearCache =
273         (m_parentResource->settings()->imapServer() != m_ui->imapServer->text()) || (m_parentResource->settings()->userName() != m_ui->userName->text());
274 
275     const MailTransport::Transport::EnumAuthenticationType::type authtype = getCurrentAuthMode(m_ui->authenticationCombo);
276     if (!m_ui->userName->text().contains(QLatin1Char('@')) && authtype == MailTransport::Transport::EnumAuthenticationType::XOAUTH2
277         && m_ui->imapServer->text().contains(QLatin1String("gmail.com"))) {
278         // Normalize gmail username so that it matches the JSON account info returned by GMail authentication.
279         // 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.
280         qCDebug(IMAPRESOURCE_LOG) << "Fixing up username" << m_ui->userName->text() << "by adding @gmail.com";
281         m_ui->userName->setText(m_ui->userName->text() + QLatin1String("@gmail.com"));
282     }
283 
284     m_parentResource->setName(m_ui->accountName->text());
285 
286     m_parentResource->settings()->setImapServer(m_ui->imapServer->text());
287     m_parentResource->settings()->setImapPort(m_ui->portSpin->value());
288     m_parentResource->settings()->setUserName(m_ui->userName->text());
289     QString encryption;
290     switch (m_ui->safeImapGroup->checkedId()) {
291     case KIMAP::LoginJob::Unencrypted:
292         encryption = QStringLiteral("None");
293         break;
294     case KIMAP::LoginJob::SSLorTLS:
295         encryption = QStringLiteral("SSL");
296         break;
297     case KIMAP::LoginJob::STARTTLS:
298         encryption = QStringLiteral("STARTTLS");
299         break;
300     default:
301         qFatal("Shouldn't happen");
302     }
303     m_parentResource->settings()->setSafety(encryption);
304 
305     qCDebug(IMAPRESOURCE_LOG) << "saving IMAP auth mode: " << authenticationModeString(authtype);
306     m_parentResource->settings()->setAuthentication(authtype);
307     m_parentResource->settings()->setPassword(m_ui->password->password());
308     m_parentResource->settings()->setSubscriptionEnabled(m_ui->subscriptionEnabled->isChecked());
309     m_parentResource->settings()->setIntervalCheckTime(m_ui->checkInterval->value());
310     m_parentResource->settings()->setDisconnectedModeEnabled(m_ui->disconnectedModeEnabled->isChecked());
311     m_parentResource->settings()->setUseProxy(m_ui->useProxyCheck->isChecked());
312 
313     MailTransport::Transport::EnumAuthenticationType::type alternateAuthtype = getCurrentAuthMode(m_ui->authenticationAlternateCombo);
314     qCDebug(IMAPRESOURCE_LOG) << "saving Alternate server sieve auth mode: " << authenticationModeString(alternateAuthtype);
315     m_parentResource->settings()->setAlternateAuthentication(alternateAuthtype);
316     m_parentResource->settings()->setSieveSupport(m_ui->managesieveCheck->isChecked());
317     m_parentResource->settings()->setSieveReuseConfig(m_ui->sameConfigCheck->isChecked());
318     m_parentResource->settings()->setSievePort(m_ui->sievePortSpin->value());
319     m_parentResource->settings()->setSieveAlternateUrl(m_ui->alternateURL->text());
320     m_parentResource->settings()->setSieveVacationFilename(m_vacationFileName);
321 
322     m_parentResource->settings()->setTrashCollection(m_ui->folderRequester->collection().id());
323     Akonadi::Collection trash = m_ui->folderRequester->collection();
324     Akonadi::SpecialMailCollections::self()->registerCollection(Akonadi::SpecialMailCollections::Trash, trash);
325     auto attribute = trash.attribute<Akonadi::EntityDisplayAttribute>(Akonadi::Collection::AddIfMissing);
326     attribute->setIconName(QStringLiteral("user-trash"));
327     new Akonadi::CollectionModifyJob(trash);
328     if (mOldTrash != trash) {
329         Akonadi::SpecialMailCollections::self()->unregisterCollection(mOldTrash);
330     }
331 
332     m_parentResource->settings()->setAutomaticExpungeEnabled(m_ui->autoExpungeCheck->isChecked());
333     m_parentResource->settings()->setUseDefaultIdentity(m_identityCombobox->isDefaultIdentity());
334 
335     if (!m_identityCombobox->isDefaultIdentity()) {
336         m_parentResource->settings()->setAccountIdentity(m_identityCombobox->currentIdentity());
337     }
338 
339     m_parentResource->settings()->setIntervalCheckEnabled(m_ui->enableMailCheckBox->isChecked());
340     if (m_ui->enableMailCheckBox->isChecked()) {
341         m_parentResource->settings()->setIntervalCheckTime(m_ui->checkInterval->value());
342     }
343 
344     m_parentResource->settings()->setSieveCustomUsername(m_ui->customUsername->text());
345 
346     QAbstractButton *checkedButton = m_ui->customSieveGroup->checkedButton();
347 
348     if (checkedButton == m_ui->imapUserPassword) {
349         m_parentResource->settings()->setSieveCustomAuthentification(QStringLiteral("ImapUserPassword"));
350     } else if (checkedButton == m_ui->noAuthentification) {
351         m_parentResource->settings()->setSieveCustomAuthentification(QStringLiteral("NoAuthentification"));
352     } else if (checkedButton == m_ui->customUserPassword) {
353         m_parentResource->settings()->setSieveCustomAuthentification(QStringLiteral("CustomUserPassword"));
354     }
355 
356     m_parentResource->settings()->setSieveCustomPassword(m_ui->customPassword->password());
357 
358     m_parentResource->settings()->save();
359     qCDebug(IMAPRESOURCE_LOG) << "wrote" << m_ui->imapServer->text() << m_ui->userName->text() << m_ui->safeImapGroup->checkedId();
360 
361     if (m_oldResourceName != m_ui->accountName->text() && !m_ui->accountName->text().isEmpty()) {
362         m_parentResource->settings()->renameRootCollection(m_ui->accountName->text());
363     }
364 
365     accept();
366 }
367 
readSettings()368 void SetupServer::readSettings()
369 {
370     m_folderArchiveSettingPage->loadSettings();
371     m_ui->accountName->setText(m_parentResource->name());
372     m_oldResourceName = m_ui->accountName->text();
373 
374     auto currentUser = new KUser();
375     KEMailSettings esetting;
376 
377     m_ui->imapServer->setText(!m_parentResource->settings()->imapServer().isEmpty() ? m_parentResource->settings()->imapServer()
378                                                                                     : esetting.getSetting(KEMailSettings::InServer));
379 
380     m_ui->portSpin->setValue(m_parentResource->settings()->imapPort());
381 
382     m_ui->userName->setText(!m_parentResource->settings()->userName().isEmpty() ? m_parentResource->settings()->userName() : currentUser->loginName());
383 
384     const QString safety = m_parentResource->settings()->safety();
385     int i = 0;
386     if (safety == QLatin1String("SSL")) {
387         i = KIMAP::LoginJob::SSLorTLS;
388     } else if (safety == QLatin1String("STARTTLS")) {
389         i = KIMAP::LoginJob::STARTTLS;
390     } else {
391         i = KIMAP::LoginJob::Unencrypted;
392     }
393 
394     QAbstractButton *safetyButton = m_ui->safeImapGroup->button(i);
395     if (safetyButton) {
396         safetyButton->setChecked(true);
397     }
398 
399     populateDefaultAuthenticationOptions();
400     i = m_parentResource->settings()->authentication();
401     qCDebug(IMAPRESOURCE_LOG) << "read IMAP auth mode: " << authenticationModeString(static_cast<MailTransport::Transport::EnumAuthenticationType::type>(i));
402     setCurrentAuthMode(m_ui->authenticationCombo, (MailTransport::Transport::EnumAuthenticationType::type)i);
403 
404     i = m_parentResource->settings()->alternateAuthentication();
405     setCurrentAuthMode(m_ui->authenticationAlternateCombo, static_cast<MailTransport::Transport::EnumAuthenticationType::type>(i));
406 
407     bool rejected = false;
408     const QString password = m_parentResource->settings()->password(&rejected);
409     if (rejected) {
410         m_ui->password->setEnabled(false);
411         KMessageBox::information(nullptr,
412                                  i18n("Could not access KWallet. "
413                                       "If you want to store the password permanently then you have to "
414                                       "activate it. If you do not "
415                                       "want to use KWallet, check the box below, but note that you will be "
416                                       "prompted for your password when needed."),
417                                  i18n("Do not use KWallet"),
418                                  QStringLiteral("warning_kwallet_disabled"));
419     } else {
420         m_ui->password->lineEdit()->insert(password);
421     }
422 
423     m_ui->subscriptionEnabled->setChecked(m_parentResource->settings()->subscriptionEnabled());
424 
425     m_ui->checkInterval->setValue(m_parentResource->settings()->intervalCheckTime());
426     m_ui->disconnectedModeEnabled->setChecked(m_parentResource->settings()->disconnectedModeEnabled());
427     m_ui->useProxyCheck->setChecked(m_parentResource->settings()->useProxy());
428 
429     m_ui->managesieveCheck->setChecked(m_parentResource->settings()->sieveSupport());
430     m_ui->sameConfigCheck->setChecked(m_parentResource->settings()->sieveReuseConfig());
431     m_ui->sievePortSpin->setValue(m_parentResource->settings()->sievePort());
432     m_ui->alternateURL->setText(m_parentResource->settings()->sieveAlternateUrl());
433     m_vacationFileName = m_parentResource->settings()->sieveVacationFilename();
434 
435     Akonadi::Collection trashCollection(m_parentResource->settings()->trashCollection());
436     if (trashCollection.isValid()) {
437         auto fetchJob = new Akonadi::CollectionFetchJob(trashCollection, Akonadi::CollectionFetchJob::Base, this);
438         connect(fetchJob, &Akonadi::CollectionFetchJob::collectionsReceived, this, &SetupServer::targetCollectionReceived);
439     } else {
440         auto requestJob = new Akonadi::SpecialMailCollectionsRequestJob(this);
441         connect(requestJob, &Akonadi::SpecialMailCollectionsRequestJob::result, this, &SetupServer::localFolderRequestJobFinished);
442         requestJob->requestDefaultCollection(Akonadi::SpecialMailCollections::Trash);
443         requestJob->start();
444     }
445 
446     m_identityCombobox->setCurrentIdentity(m_parentResource->settings()->accountIdentity());
447 
448     m_ui->enableMailCheckBox->setChecked(m_parentResource->settings()->intervalCheckEnabled());
449     if (m_ui->enableMailCheckBox->isChecked()) {
450         m_ui->checkInterval->setValue(m_parentResource->settings()->intervalCheckTime());
451     } else {
452         m_ui->checkInterval->setEnabled(false);
453     }
454 
455     m_ui->autoExpungeCheck->setChecked(m_parentResource->settings()->automaticExpungeEnabled());
456 
457     if (m_vacationFileName.isEmpty()) {
458         m_vacationFileName = QStringLiteral("kmail-vacation.siv");
459     }
460 
461     m_ui->customUsername->setText(m_parentResource->settings()->sieveCustomUsername());
462 
463     rejected = false;
464     const QString customPassword = m_parentResource->settings()->sieveCustomPassword(&rejected);
465     if (rejected) {
466         m_ui->customPassword->setEnabled(false);
467         KMessageBox::information(nullptr,
468                                  i18n("Could not access KWallet. "
469                                       "If you want to store the password permanently then you have to "
470                                       "activate it. If you do not "
471                                       "want to use KWallet, check the box below, but note that you will be "
472                                       "prompted for your password when needed."),
473                                  i18n("Do not use KWallet"),
474                                  QStringLiteral("warning_kwallet_disabled"));
475     } else {
476         m_ui->customPassword->lineEdit()->insert(customPassword);
477     }
478 
479     const QString sieverCustomAuth(m_parentResource->settings()->sieveCustomAuthentification());
480     if (sieverCustomAuth == QLatin1String("ImapUserPassword")) {
481         m_ui->imapUserPassword->setChecked(true);
482     } else if (sieverCustomAuth == QLatin1String("NoAuthentification")) {
483         m_ui->noAuthentification->setChecked(true);
484     } else if (sieverCustomAuth == QLatin1String("CustomUserPassword")) {
485         m_ui->customUserPassword->setChecked(true);
486     }
487 
488     delete currentUser;
489 }
490 
slotTest()491 void SetupServer::slotTest()
492 {
493     qCDebug(IMAPRESOURCE_LOG) << m_ui->imapServer->text();
494 
495     m_ui->testButton->setEnabled(false);
496     m_ui->advancedTab->setEnabled(false);
497     m_ui->authenticationCombo->setEnabled(false);
498 
499     m_ui->testInfo->clear();
500     m_ui->testInfo->hide();
501 
502     delete m_serverTest;
503     m_serverTest = new MailTransport::ServerTest(this);
504 #ifndef QT_NO_CURSOR
505     qApp->setOverrideCursor(Qt::BusyCursor);
506 #endif
507 
508     const QString server = m_ui->imapServer->text();
509     const int port = m_ui->portSpin->value();
510     qCDebug(IMAPRESOURCE_LOG) << "server: " << server << "port: " << port;
511 
512     m_serverTest->setServer(server);
513 
514     if (port != 143 && port != 993) {
515         m_serverTest->setPort(MailTransport::Transport::EnumEncryption::None, port);
516         m_serverTest->setPort(MailTransport::Transport::EnumEncryption::SSL, port);
517     }
518 
519     m_serverTest->setProtocol(QStringLiteral("imap"));
520     m_serverTest->setProgressBar(m_ui->testProgress);
521     connect(m_serverTest, &MailTransport::ServerTest::finished, this, &SetupServer::slotFinished);
522     mOkButton->setEnabled(false);
523     m_serverTest->start();
524 }
525 
slotFinished(const QVector<int> & testResult)526 void SetupServer::slotFinished(const QVector<int> &testResult)
527 {
528     qCDebug(IMAPRESOURCE_LOG) << testResult;
529 
530 #ifndef QT_NO_CURSOR
531     qApp->restoreOverrideCursor();
532 #endif
533     mOkButton->setEnabled(true);
534 
535     using namespace MailTransport;
536 
537     if (!m_serverTest->isNormalPossible() && !m_serverTest->isSecurePossible()) {
538         KMessageBox::sorry(this, i18n("Unable to connect to the server, please verify the server address."));
539     }
540 
541     m_ui->testInfo->show();
542 
543     m_ui->sslRadio->setEnabled(testResult.contains(Transport::EnumEncryption::SSL));
544     m_ui->tlsRadio->setEnabled(testResult.contains(Transport::EnumEncryption::TLS));
545     m_ui->noRadio->setEnabled(testResult.contains(Transport::EnumEncryption::None));
546 
547     QString text;
548     if (testResult.contains(Transport::EnumEncryption::TLS)) {
549         m_ui->tlsRadio->setChecked(true);
550         text = i18n("<qt><b>STARTTLS is supported and recommended.</b></qt>");
551     } else if (testResult.contains(Transport::EnumEncryption::SSL)) {
552         m_ui->sslRadio->setChecked(true);
553         text = i18n("<qt><b>SSL/TLS is supported and recommended.</b></qt>");
554     } else if (testResult.contains(Transport::EnumEncryption::None)) {
555         m_ui->noRadio->setChecked(true);
556         text = i18n(
557             "<qt><b>No security is supported. It is not "
558             "recommended to connect to this server.</b></qt>");
559     } else {
560         text = i18n("<qt><b>It is not possible to use this server.</b></qt>");
561     }
562     m_ui->testInfo->setText(text);
563 
564     m_ui->testButton->setEnabled(true);
565     m_ui->advancedTab->setEnabled(true);
566     m_ui->authenticationCombo->setEnabled(true);
567     slotEncryptionRadioChanged();
568     slotSafetyChanged();
569 }
570 
slotTestChanged()571 void SetupServer::slotTestChanged()
572 {
573     delete m_serverTest;
574     m_serverTest = nullptr;
575     slotSafetyChanged();
576 
577     // do not use imapConnectionPossible, as the data is not yet saved.
578     m_ui->testButton->setEnabled(true /* TODO && Global::connectionPossible() ||
579                                                 m_ui->imapServer->text() == "localhost"*/);
580 }
581 
slotEnableWidgets()582 void SetupServer::slotEnableWidgets()
583 {
584     const bool haveSieve = m_ui->managesieveCheck->isChecked();
585     const bool reuseConfig = m_ui->sameConfigCheck->isChecked();
586 
587     m_ui->sameConfigCheck->setEnabled(haveSieve);
588     m_ui->sievePortSpin->setEnabled(haveSieve);
589     m_ui->alternateURL->setEnabled(haveSieve && !reuseConfig);
590     m_ui->authentication->setEnabled(haveSieve && !reuseConfig);
591 }
592 
slotComplete()593 void SetupServer::slotComplete()
594 {
595     const bool ok = !m_ui->imapServer->text().isEmpty() && !m_ui->userName->text().isEmpty();
596     mOkButton->setEnabled(ok);
597 }
598 
slotSafetyChanged()599 void SetupServer::slotSafetyChanged()
600 {
601     if (m_serverTest == nullptr) {
602         return;
603     }
604     QVector<int> protocols;
605 
606     switch (m_ui->safeImapGroup->checkedId()) {
607     case KIMAP::LoginJob::Unencrypted:
608         qCDebug(IMAPRESOURCE_LOG) << "safeImapGroup: unencrypted";
609         protocols = m_serverTest->normalProtocols();
610         break;
611     case KIMAP::LoginJob::SSLorTLS:
612         protocols = m_serverTest->secureProtocols();
613         qCDebug(IMAPRESOURCE_LOG) << "safeImapGroup: SSL";
614         break;
615     case KIMAP::LoginJob::STARTTLS:
616         protocols = m_serverTest->tlsProtocols();
617         qCDebug(IMAPRESOURCE_LOG) << "safeImapGroup: starttls";
618         break;
619     default:
620         qFatal("Shouldn't happen");
621     }
622 
623     m_ui->authenticationCombo->clear();
624     addAuthenticationItem(m_ui->authenticationCombo, MailTransport::Transport::EnumAuthenticationType::CLEAR);
625     for (int prot : std::as_const(protocols)) {
626         addAuthenticationItem(m_ui->authenticationCombo, (MailTransport::Transport::EnumAuthenticationType::type)prot);
627     }
628     if (protocols.isEmpty()) {
629         qCDebug(IMAPRESOURCE_LOG) << "no authmodes found";
630     } else {
631         setCurrentAuthMode(m_ui->authenticationCombo, (MailTransport::Transport::EnumAuthenticationType::type)protocols.first());
632     }
633 }
634 
slotManageSubscriptions()635 void SetupServer::slotManageSubscriptions()
636 {
637     qCDebug(IMAPRESOURCE_LOG) << "manage subscripts";
638     ImapAccount account;
639 
640     account.setServer(m_ui->imapServer->text());
641     account.setPort(m_ui->portSpin->value());
642 
643     account.setUserName(m_ui->userName->text());
644     account.setSubscriptionEnabled(m_ui->subscriptionEnabled->isChecked());
645 
646     account.setEncryptionMode(static_cast<KIMAP::LoginJob::EncryptionMode>(m_ui->safeImapGroup->checkedId()));
647 
648     account.setAuthenticationMode(Settings::mapTransportAuthToKimap(getCurrentAuthMode(m_ui->authenticationCombo)));
649 
650     QPointer<SubscriptionDialog> subscriptions = new SubscriptionDialog(this);
651     subscriptions->setWindowTitle(i18nc("@title:window", "Serverside Subscription"));
652     subscriptions->setWindowIcon(QIcon::fromTheme(QStringLiteral("network-server")));
653     subscriptions->connectAccount(account, m_ui->password->password());
654     m_subscriptionsChanged = subscriptions->isSubscriptionChanged();
655 
656     subscriptions->exec();
657     delete subscriptions;
658 
659     m_ui->subscriptionEnabled->setChecked(account.isSubscriptionEnabled());
660 }
661 
slotShowServerInfo()662 void SetupServer::slotShowServerInfo()
663 {
664     auto dialog = new ServerInfoDialog(m_parentResource, this);
665     dialog->show();
666 }
667 
targetCollectionReceived(const Akonadi::Collection::List & collections)668 void SetupServer::targetCollectionReceived(const Akonadi::Collection::List &collections)
669 {
670     m_ui->folderRequester->setCollection(collections.first());
671     mOldTrash = collections.first();
672 }
673 
localFolderRequestJobFinished(KJob * job)674 void SetupServer::localFolderRequestJobFinished(KJob *job)
675 {
676     if (!job->error()) {
677         Akonadi::Collection targetCollection = Akonadi::SpecialMailCollections::self()->defaultCollection(Akonadi::SpecialMailCollections::Trash);
678         Q_ASSERT(targetCollection.isValid());
679         m_ui->folderRequester->setCollection(targetCollection);
680         mOldTrash = targetCollection;
681     }
682 }
683 
populateDefaultAuthenticationOptions()684 void SetupServer::populateDefaultAuthenticationOptions()
685 {
686     populateDefaultAuthenticationOptions(m_ui->authenticationCombo);
687     populateDefaultAuthenticationOptions(m_ui->authenticationAlternateCombo);
688 }
689 
populateDefaultAuthenticationOptions(QComboBox * combo)690 void SetupServer::populateDefaultAuthenticationOptions(QComboBox *combo)
691 {
692     combo->clear();
693     addAuthenticationItem(combo, MailTransport::Transport::EnumAuthenticationType::CLEAR);
694     addAuthenticationItem(combo, MailTransport::Transport::EnumAuthenticationType::LOGIN);
695     addAuthenticationItem(combo, MailTransport::Transport::EnumAuthenticationType::PLAIN);
696     addAuthenticationItem(combo, MailTransport::Transport::EnumAuthenticationType::CRAM_MD5);
697     addAuthenticationItem(combo, MailTransport::Transport::EnumAuthenticationType::DIGEST_MD5);
698     addAuthenticationItem(combo, MailTransport::Transport::EnumAuthenticationType::NTLM);
699     addAuthenticationItem(combo, MailTransport::Transport::EnumAuthenticationType::GSSAPI);
700     addAuthenticationItem(combo, MailTransport::Transport::EnumAuthenticationType::ANONYMOUS);
701     addAuthenticationItem(combo, MailTransport::Transport::EnumAuthenticationType::XOAUTH2);
702 }
703 
slotServerChanged()704 void SetupServer::slotServerChanged()
705 {
706     populateDefaultAuthenticationOptions(m_ui->authenticationCombo);
707 }
708