File indexing completed on 2024-11-24 04:53:09

0001 /* Copyright (C) 2006 - 2014 Jan Kundrát <jkt@flaska.net>
0002 
0003    This file is part of the Trojita Qt IMAP e-mail client,
0004    http://trojita.flaska.net/
0005 
0006    This program is free software; you can redistribute it and/or
0007    modify it under the terms of the GNU General Public License as
0008    published by the Free Software Foundation; either version 2 of
0009    the License or (at your option) version 3 or any later version
0010    accepted by the membership of KDE e.V. (or its successor approved
0011    by the membership of KDE e.V.), which shall act as a proxy
0012    defined in Section 14 of version 3 of the license.
0013 
0014    This program is distributed in the hope that it will be useful,
0015    but WITHOUT ANY WARRANTY; without even the implied warranty of
0016    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0017    GNU General Public License for more details.
0018 
0019    You should have received a copy of the GNU General Public License
0020    along with this program.  If not, see <http://www.gnu.org/licenses/>.
0021 */
0022 
0023 #include "ImapAccess.h"
0024 #include <QDir>
0025 #include <QFileInfo>
0026 #include <QSslKey>
0027 #include <QSettings>
0028 #include "Common/MetaTypes.h"
0029 #include "Common/Paths.h"
0030 #include "Common/PortNumbers.h"
0031 #include "Common/SettingsNames.h"
0032 #include "Imap/Model/CombinedCache.h"
0033 #include "Imap/Model/DummyNetworkWatcher.h"
0034 #include "Imap/Model/MailboxModel.h"
0035 #include "Imap/Model/MemoryCache.h"
0036 #include "Imap/Model/Model.h"
0037 #include "Imap/Model/MsgListModel.h"
0038 #include "Imap/Model/NetworkWatcher.h"
0039 #include "Imap/Model/OneMessageModel.h"
0040 #include "Imap/Model/SubtreeModel.h"
0041 #include "Imap/Model/SystemNetworkWatcher.h"
0042 #include "Imap/Model/ThreadingMsgListModel.h"
0043 #include "Imap/Model/Utils.h"
0044 #include "Imap/Model/VisibleTasksModel.h"
0045 #include "Imap/Network/MsgPartNetAccessManager.h"
0046 #include "Streams/SocketFactory.h"
0047 #include "UiUtils/PasswordWatcher.h"
0048 
0049 namespace Imap {
0050 
0051 ImapAccess::ImapAccess(QObject *parent, QSettings *settings, Plugins::PluginManager *pluginManager, const QString &accountName) :
0052     QObject(parent), m_settings(settings), m_imapModel(0), m_mailboxModel(0), m_mailboxSubtreeModel(0), m_msgListModel(0),
0053     m_threadingMsgListModel(0), m_visibleTasksModel(0), m_oneMessageModel(0), m_netWatcher(0), m_msgQNAM(0),
0054     m_pluginManager(pluginManager), m_passwordWatcher(0), m_port(0),
0055     m_connectionMethod(Common::ConnectionMethod::Invalid),
0056     m_sslInfoIcon(UiUtils::Formatting::IconType::NoIcon),
0057     m_accountName(accountName)
0058 {
0059     Imap::migrateSettings(m_settings);
0060     reloadConfiguration();
0061     m_cacheDir = Common::writablePath(Common::LOCATION_CACHE) + m_accountName + QLatin1Char('/');;
0062     m_passwordWatcher = new UiUtils::PasswordWatcher(this, m_pluginManager,
0063                                                      // FIXME: this can be removed when support for multiple accounts is implemented
0064                                                      accountName.isEmpty() ? QStringLiteral("account-0") : accountName,
0065                                                      QStringLiteral("imap"));
0066 }
0067 
0068 void ImapAccess::reloadConfiguration()
0069 {
0070     m_server = m_settings->value(Common::SettingsNames::imapHostKey).toString();
0071     m_username = m_settings->value(Common::SettingsNames::imapUserKey).toString();
0072     if (m_settings->value(Common::SettingsNames::imapMethodKey).toString() == Common::SettingsNames::methodSSL) {
0073         m_connectionMethod = Common::ConnectionMethod::NetDedicatedTls;
0074     } else if (m_settings->value(Common::SettingsNames::imapMethodKey).toString() == Common::SettingsNames::methodTCP) {
0075         m_connectionMethod = m_settings->value(Common::SettingsNames::imapStartTlsKey).toBool() ?
0076                     Common::ConnectionMethod::NetStartTls : Common::ConnectionMethod::NetCleartext;
0077     } else if (m_settings->value(Common::SettingsNames::imapMethodKey).toString() == Common::SettingsNames::methodProcess) {
0078         m_connectionMethod = Common::ConnectionMethod::Process;
0079     }
0080     m_port = m_settings->value(Common::SettingsNames::imapPortKey, QVariant(0)).toInt();
0081     if (!m_port) {
0082         switch (m_connectionMethod) {
0083         case Common::ConnectionMethod::NetCleartext:
0084         case Common::ConnectionMethod::NetStartTls:
0085             m_port = Common::PORT_IMAP;
0086             break;
0087         case Common::ConnectionMethod::NetDedicatedTls:
0088             m_port = Common::PORT_IMAPS;
0089             break;
0090         case Common::ConnectionMethod::Process:
0091         case Common::ConnectionMethod::Invalid:
0092             // do nothing
0093             break;
0094         }
0095     }
0096 }
0097 
0098 void ImapAccess::alertReceived(const QString &message)
0099 {
0100     qDebug() << "alertReceived" << message;
0101 }
0102 
0103 void ImapAccess::imapError(const QString &message)
0104 {
0105     qDebug() << "imapError" << message;
0106 }
0107 
0108 void ImapAccess::networkError(const QString &message)
0109 {
0110     qDebug() << "networkError" << message;
0111 }
0112 
0113 void ImapAccess::slotLogged(uint parserId, const Common::LogMessage &message)
0114 {
0115     if (message.kind != Common::LOG_IO_READ) {
0116         qDebug() << "LOG" << parserId << message.timestamp << message.kind << message.source << message.message;
0117     }
0118 }
0119 
0120 QString ImapAccess::server() const
0121 {
0122     return m_server;
0123 }
0124 
0125 void ImapAccess::setServer(const QString &server)
0126 {
0127     m_server = server;
0128     m_settings->setValue(Common::SettingsNames::imapHostKey, m_server);
0129     emit serverChanged();
0130 }
0131 
0132 QString ImapAccess::username() const
0133 {
0134     return m_username;
0135 }
0136 
0137 void ImapAccess::setUsername(const QString &username)
0138 {
0139     m_username = username;
0140     m_settings->setValue(Common::SettingsNames::imapUserKey, m_username);
0141     emit usernameChanged();;
0142 }
0143 
0144 QString ImapAccess::password() const
0145 {
0146     return m_password;
0147 }
0148 
0149 void ImapAccess::setPassword(const QString &password)
0150 {
0151     m_password = password;
0152 }
0153 
0154 int ImapAccess::port() const
0155 {
0156     return m_port;
0157 }
0158 
0159 void ImapAccess::setPort(const int port)
0160 {
0161     m_port = port;
0162     m_settings->setValue(Common::SettingsNames::imapPortKey, m_port);
0163     emit portChanged();
0164 }
0165 
0166 QString ImapAccess::sslMode() const
0167 {
0168     switch (m_connectionMethod) {
0169     case Common::ConnectionMethod::NetCleartext:
0170         return QStringLiteral("No");
0171     case Common::ConnectionMethod::NetStartTls:
0172         return QStringLiteral("StartTLS");
0173     case Common::ConnectionMethod::NetDedicatedTls:
0174         return QStringLiteral("SSL");
0175     case Common::ConnectionMethod::Invalid:
0176     case Common::ConnectionMethod::Process:
0177         return QString();
0178     }
0179 
0180     Q_ASSERT(false);
0181     return QString();
0182 }
0183 
0184 void ImapAccess::setSslMode(const QString &sslMode)
0185 {
0186     if (sslMode == QLatin1String("No")) {
0187         setConnectionMethod(Common::ConnectionMethod::NetCleartext);
0188     } else if (sslMode == QLatin1String("SSL")) {
0189         setConnectionMethod(Common::ConnectionMethod::NetDedicatedTls);
0190     } else if (sslMode == QLatin1String("StartTLS")) {
0191         setConnectionMethod(Common::ConnectionMethod::NetStartTls);
0192     } else {
0193         Q_ASSERT(false);
0194     }
0195 }
0196 
0197 Common::ConnectionMethod ImapAccess::connectionMethod() const
0198 {
0199     return m_connectionMethod;
0200 }
0201 
0202 void ImapAccess::setConnectionMethod(const Common::ConnectionMethod mode)
0203 {
0204     m_connectionMethod = mode;
0205     switch (m_connectionMethod) {
0206     case Common::ConnectionMethod::Invalid:
0207         break;
0208     case Common::ConnectionMethod::NetCleartext:
0209     case Common::ConnectionMethod::NetStartTls:
0210         m_settings->setValue(Common::SettingsNames::imapMethodKey, Common::SettingsNames::methodTCP);
0211         m_settings->setValue(Common::SettingsNames::imapStartTlsKey, m_connectionMethod == Common::ConnectionMethod::NetStartTls);
0212         break;
0213     case Common::ConnectionMethod::NetDedicatedTls:
0214         m_settings->setValue(Common::SettingsNames::imapMethodKey, Common::SettingsNames::methodSSL);
0215         // Trying to communicate the fact that this is going to be an encrypted connection, even though
0216         // that settings bit is not actually used
0217         m_settings->setValue(Common::SettingsNames::imapStartTlsKey, true);
0218         break;
0219     case Common::ConnectionMethod::Process:
0220         m_settings->setValue(Common::SettingsNames::imapMethodKey, Common::SettingsNames::methodProcess);
0221         break;
0222     }
0223     emit connMethodChanged();
0224 }
0225 
0226 Imap::Mailbox::NetworkPolicy ImapAccess::preferredNetworkPolicy() const
0227 {
0228     auto val = m_settings->value(Common::SettingsNames::imapStartMode).toString();
0229     if (val == Common::SettingsNames::netOffline) {
0230         return Imap::Mailbox::NETWORK_OFFLINE;
0231     } else if (val == Common::SettingsNames::netExpensive) {
0232         return Imap::Mailbox::NETWORK_EXPENSIVE;
0233     } else {
0234         return Imap::Mailbox::NETWORK_ONLINE;
0235     }
0236 }
0237 
0238 QString ImapAccess::accountIconName() const
0239 {
0240     return m_settings->value(Common::SettingsNames::imapAccountIcon).toString();
0241 }
0242 
0243 void ImapAccess::setAccountIconName(const QString &iconName)
0244 {
0245     m_settings->setValue(Common::SettingsNames::imapAccountIcon, iconName);
0246 }
0247 
0248 void ImapAccess::doConnect()
0249 {
0250     if (m_netWatcher) {
0251         // We're temporarily "disabling" this connection. Otherwise this "offline preference"
0252         // would get saved into the config file, which would be bad.
0253         disconnect(m_netWatcher, &Mailbox::NetworkWatcher::desiredNetworkPolicyChanged, this, &ImapAccess::desiredNetworkPolicyChanged);
0254     }
0255 
0256     if (m_imapModel) {
0257         // Disconnect from network, nuke the models
0258         Q_ASSERT(m_netWatcher);
0259         m_netWatcher->setNetworkOffline();
0260         delete m_threadingMsgListModel;
0261         m_threadingMsgListModel = 0;
0262         delete m_msgQNAM;
0263         m_msgQNAM = 0;
0264         delete m_oneMessageModel;
0265         m_oneMessageModel = 0;
0266         delete m_visibleTasksModel;
0267         m_visibleTasksModel = 0;
0268         delete m_msgListModel;
0269         m_msgListModel = 0;
0270         delete m_mailboxSubtreeModel;
0271         m_mailboxSubtreeModel = 0;
0272         delete m_mailboxModel;
0273         m_mailboxModel = 0;
0274         delete m_netWatcher;
0275         m_netWatcher = 0;
0276         delete m_imapModel;
0277         m_imapModel = 0;
0278     }
0279 
0280     Q_ASSERT(!m_imapModel);
0281 
0282     Imap::Mailbox::SocketFactoryPtr factory;
0283     Imap::Mailbox::TaskFactoryPtr taskFactory(new Imap::Mailbox::TaskFactory());
0284 
0285     Streams::ProxySettings proxySettings = m_settings->value(Common::SettingsNames::imapUseSystemProxy, true).toBool() ?
0286                 Streams::ProxySettings::RespectSystemProxy : Streams::ProxySettings::DirectConnect;
0287 
0288     switch (m_connectionMethod) {
0289     case Common::ConnectionMethod::Invalid:
0290         factory.reset(new Streams::FakeSocketFactory(Imap::CONN_STATE_LOGOUT));
0291         break;
0292     case Common::ConnectionMethod::NetCleartext:
0293     case Common::ConnectionMethod::NetStartTls:
0294         factory.reset(new Streams::TlsAbleSocketFactory(server(), port()));
0295         factory->setStartTlsRequired(m_connectionMethod == Common::ConnectionMethod::NetStartTls);
0296         factory->setProxySettings(proxySettings, QStringLiteral("imap"));
0297         break;
0298     case Common::ConnectionMethod::NetDedicatedTls:
0299         factory.reset(new Streams::SslSocketFactory(server(), port()));
0300         factory->setProxySettings(proxySettings, QStringLiteral("imap"));
0301         break;
0302     case Common::ConnectionMethod::Process:
0303         QStringList args = m_settings->value(Common::SettingsNames::imapProcessKey).toString().split(QLatin1Char(' '));
0304         if (args.isEmpty()) {
0305             // it's going to fail anyway
0306             args << QLatin1String("");
0307         }
0308         QString appName = args.takeFirst();
0309         factory.reset(new Streams::ProcessSocketFactory(appName, args));
0310         break;
0311     }
0312 
0313     bool shouldUsePersistentCache =
0314             m_settings->value(Common::SettingsNames::cacheOfflineKey).toString() != Common::SettingsNames::cacheOfflineNone;
0315 
0316     if (shouldUsePersistentCache && !QDir().mkpath(m_cacheDir)) {
0317         onCacheError(tr("Failed to create directory %1").arg(m_cacheDir));
0318         shouldUsePersistentCache = false;
0319     }
0320 
0321     if (shouldUsePersistentCache) {
0322         QFile::Permissions expectedPerms = QFile::ReadOwner | QFile::WriteOwner | QFile::ExeOwner;
0323         if (QFileInfo(m_cacheDir).permissions() != expectedPerms) {
0324             if (!QFile::setPermissions(m_cacheDir, expectedPerms)) {
0325 #ifndef Q_OS_WIN32
0326                 onCacheError(tr("Failed to set safe permissions on cache directory %1").arg(m_cacheDir));
0327                 shouldUsePersistentCache = false;
0328 #endif
0329             }
0330         }
0331     }
0332 
0333     std::shared_ptr<Imap::Mailbox::AbstractCache> cache;
0334 
0335     if (!shouldUsePersistentCache) {
0336         cache.reset(new Imap::Mailbox::MemoryCache());
0337     } else {
0338         cache.reset(new Imap::Mailbox::CombinedCache(QStringLiteral("trojita-imap-cache"), m_cacheDir));
0339         cache->setErrorHandler([this](const QString &e) { this->onCacheError(e); });
0340         if (! static_cast<Imap::Mailbox::CombinedCache *>(cache.get())->open()) {
0341             // Error message was already shown by the cacheError() slot
0342             cache.reset(new Imap::Mailbox::MemoryCache());
0343         } else {
0344             if (m_settings->value(Common::SettingsNames::cacheOfflineKey).toString() == Common::SettingsNames::cacheOfflineAll) {
0345                 cache->setRenewalThreshold(0);
0346             } else {
0347                 const int defaultCacheLifetime = 30;
0348                 bool ok;
0349                 int num = m_settings->value(Common::SettingsNames::cacheOfflineNumberDaysKey, defaultCacheLifetime).toInt(&ok);
0350                 if (!ok)
0351                     num = defaultCacheLifetime;
0352                 cache->setRenewalThreshold(num);
0353             }
0354         }
0355     }
0356 
0357     m_imapModel = new Imap::Mailbox::Model(this, cache, std::move(factory), std::move(taskFactory));
0358     m_imapModel->setObjectName(QStringLiteral("imapModel-%1").arg(m_accountName));
0359     m_imapModel->setCapabilitiesBlacklist(m_settings->value(Common::SettingsNames::imapBlacklistedCapabilities).toStringList());
0360     m_imapModel->setProperty("trojita-imap-id-no-versions", !m_settings->value(Common::SettingsNames::interopRevealVersions, true).toBool());
0361     m_imapModel->setProperty("trojita-imap-idle-renewal", m_settings->value(Common::SettingsNames::imapIdleRenewal).toUInt() * 60 * 1000);
0362     m_imapModel->setNumberRefreshInterval(numberRefreshInterval());
0363     connect(m_imapModel, &Mailbox::Model::alertReceived, this, &ImapAccess::alertReceived);
0364     connect(m_imapModel, &Mailbox::Model::imapError, this, &ImapAccess::imapError);
0365     connect(m_imapModel, &Mailbox::Model::networkError, this, &ImapAccess::networkError);
0366     //connect(m_imapModel, &Mailbox::Model::logged, this, &ImapAccess::slotLogged);
0367     connect(m_imapModel, &Mailbox::Model::needsSslDecision, this, &ImapAccess::slotSslErrors);
0368     connect(m_imapModel, &Mailbox::Model::requireStartTlsInFuture, this, &ImapAccess::onRequireStartTlsInFuture);
0369 
0370     if (m_settings->value(Common::SettingsNames::imapNeedsNetwork, true).toBool()) {
0371         m_netWatcher = new Imap::Mailbox::SystemNetworkWatcher(this, m_imapModel);
0372     } else {
0373         m_netWatcher = new Imap::Mailbox::DummyNetworkWatcher(this, m_imapModel);
0374     }
0375     connect(m_netWatcher, &Mailbox::NetworkWatcher::desiredNetworkPolicyChanged, this, &ImapAccess::desiredNetworkPolicyChanged);
0376     switch (preferredNetworkPolicy()) {
0377     case Imap::Mailbox::NETWORK_OFFLINE:
0378         QMetaObject::invokeMethod(m_netWatcher, "setNetworkOffline", Qt::QueuedConnection);
0379         break;
0380     case Imap::Mailbox::NETWORK_EXPENSIVE:
0381         QMetaObject::invokeMethod(m_netWatcher, "setNetworkExpensive", Qt::QueuedConnection);
0382         break;
0383     case Imap::Mailbox::NETWORK_ONLINE:
0384         QMetaObject::invokeMethod(m_netWatcher, "setNetworkOnline", Qt::QueuedConnection);
0385         break;
0386     }
0387 
0388     m_imapModel->setImapUser(username());
0389     if (!m_password.isNull()) {
0390         // Really; the idea is to wait before it has been set for the first time
0391         m_imapModel->setImapPassword(password());
0392     }
0393 
0394     m_mailboxModel = new Imap::Mailbox::MailboxModel(this, m_imapModel);
0395     m_mailboxModel->setObjectName(QStringLiteral("mailboxModel-%1").arg(m_accountName));
0396     m_mailboxSubtreeModel = new Imap::Mailbox::SubtreeModelOfMailboxModel(this);
0397     m_mailboxSubtreeModel->setObjectName(QStringLiteral("mailboxSubtreeModel-%1").arg(m_accountName));
0398     m_mailboxSubtreeModel->setSourceModel(m_mailboxModel);
0399     m_mailboxSubtreeModel->setOriginalRoot();
0400     m_msgListModel = new Imap::Mailbox::MsgListModel(this, m_imapModel);
0401     m_msgListModel->setObjectName(QStringLiteral("msgListModel-%1").arg(m_accountName));
0402     m_visibleTasksModel = new Imap::Mailbox::VisibleTasksModel(this, m_imapModel->taskModel());
0403     m_visibleTasksModel->setObjectName(QStringLiteral("visibleTasksModel-%1").arg(m_accountName));
0404     m_oneMessageModel = new Imap::Mailbox::OneMessageModel(m_imapModel);
0405     m_oneMessageModel->setObjectName(QStringLiteral("oneMessageModel-%1").arg(m_accountName));
0406     m_msgQNAM = new Imap::Network::MsgPartNetAccessManager(this);
0407     m_msgQNAM->setObjectName(QStringLiteral("m_msgQNAM-%1").arg(m_accountName));
0408     m_threadingMsgListModel = new Imap::Mailbox::ThreadingMsgListModel(this);
0409     m_threadingMsgListModel->setObjectName(QStringLiteral("threadingMsgListModel-%1").arg(m_accountName));
0410     m_threadingMsgListModel->setSourceModel(m_msgListModel);
0411     emit modelsChanged();
0412 }
0413 
0414 void ImapAccess::onCacheError(const QString &message)
0415 {
0416     if (m_imapModel) {
0417         m_imapModel->setCache(std::make_shared<Imap::Mailbox::MemoryCache>());
0418     }
0419     emit cacheError(message);
0420 }
0421 
0422 QAbstractItemModel *ImapAccess::imapModel() const
0423 {
0424     return m_imapModel;
0425 }
0426 
0427 QAbstractItemModel *ImapAccess::mailboxModel() const
0428 {
0429     return m_mailboxSubtreeModel;
0430 }
0431 
0432 QAbstractItemModel *ImapAccess::msgListModel() const
0433 {
0434     return m_msgListModel;
0435 }
0436 
0437 QAbstractItemModel *ImapAccess::visibleTasksModel() const
0438 {
0439     return m_visibleTasksModel;
0440 }
0441 
0442 QObject *ImapAccess::oneMessageModel() const
0443 {
0444     return m_oneMessageModel;
0445 }
0446 
0447 QObject *ImapAccess::networkWatcher() const
0448 {
0449     return m_netWatcher;
0450 }
0451 
0452 QObject *ImapAccess::msgQNAM() const
0453 {
0454     return m_msgQNAM;
0455 }
0456 
0457 QAbstractItemModel *ImapAccess::threadingMsgListModel() const
0458 {
0459     return m_threadingMsgListModel;
0460 }
0461 
0462 UiUtils::PasswordWatcher *ImapAccess::passwordWatcher() const
0463 {
0464     return m_passwordWatcher;
0465 }
0466 
0467 void ImapAccess::openMessage(const QString &mailboxName, const uint uid)
0468 {
0469     QModelIndex msgIndex = m_imapModel->messageIndexByUid(mailboxName, uid);
0470     m_oneMessageModel->setMessage(msgIndex);
0471     static_cast<Imap::Network::MsgPartNetAccessManager*>(m_msgQNAM)->setModelMessage(msgIndex);
0472 }
0473 
0474 void ImapAccess::slotSslErrors(const QList<QSslCertificate> &sslCertificateChain, const QList<QSslError> &sslErrors)
0475 {
0476     m_sslChain = sslCertificateChain;
0477     m_sslErrors = sslErrors;
0478 
0479     QByteArray lastKnownPubKey = m_settings->value(Common::SettingsNames::imapSslPemPubKey).toByteArray();
0480     if (!m_sslChain.isEmpty() && !lastKnownPubKey.isEmpty() && lastKnownPubKey == m_sslChain[0].publicKey().toPem()) {
0481         // This certificate chain contains the same public keys as the last time; we should accept that
0482         m_imapModel->setSslPolicy(m_sslChain, m_sslErrors, true);
0483     } else {
0484         UiUtils::Formatting::formatSslState(
0485                     m_sslChain, lastKnownPubKey, m_sslErrors, &m_sslInfoTitle, &m_sslInfoMessage, &m_sslInfoIcon);
0486         emit checkSslPolicy();
0487     }
0488 }
0489 
0490 /** @short Remember to use STARTTLS during the next connection
0491 
0492 Once a first STARTTLS attempt succeeds, change the preferences to require STARTTLS in future. This is needed
0493 to prevent a possible SSL stripping attack by a malicious proxy during subsequent connections.
0494 */
0495 void ImapAccess::onRequireStartTlsInFuture()
0496 {
0497     // It's possible that we're called after the user has already changed their preferences.
0498     // In order to not change stuff which was not supposed to be changed, let's make sure that we won't undo their changes.
0499     if (connectionMethod() == Common::ConnectionMethod::NetCleartext) {
0500         setConnectionMethod(Common::ConnectionMethod::NetStartTls);
0501     }
0502 }
0503 
0504 void ImapAccess::desiredNetworkPolicyChanged(const Mailbox::NetworkPolicy policy)
0505 {
0506     switch (policy) {
0507     case Mailbox::NETWORK_OFFLINE:
0508         m_settings->setValue(Common::SettingsNames::imapStartMode, Common::SettingsNames::netOffline);
0509         break;
0510     case Mailbox::NETWORK_EXPENSIVE:
0511         m_settings->setValue(Common::SettingsNames::imapStartMode, Common::SettingsNames::netExpensive);
0512         break;
0513     case Mailbox::NETWORK_ONLINE:
0514         m_settings->setValue(Common::SettingsNames::imapStartMode, Common::SettingsNames::netOnline);
0515         break;
0516     }
0517 }
0518 
0519 void ImapAccess::setSslPolicy(bool accept)
0520 {
0521     if (accept && !m_sslChain.isEmpty()) {
0522         m_settings->setValue(Common::SettingsNames::imapSslPemPubKey, m_sslChain[0].publicKey().toPem());
0523     }
0524     m_imapModel->setSslPolicy(m_sslChain, m_sslErrors, accept);
0525 }
0526 
0527 void ImapAccess::forgetSslCertificate()
0528 {
0529     m_settings->remove(Common::SettingsNames::imapSslPemPubKey);
0530 }
0531 
0532 QString ImapAccess::sslInfoTitle() const
0533 {
0534     return m_sslInfoTitle;
0535 }
0536 
0537 QString ImapAccess::sslInfoMessage() const
0538 {
0539     return m_sslInfoMessage;
0540 }
0541 
0542 UiUtils::Formatting::IconType ImapAccess::sslInfoIcon() const
0543 {
0544     return m_sslInfoIcon;
0545 }
0546 
0547 QString ImapAccess::mailboxListMailboxName() const
0548 {
0549     return m_mailboxSubtreeModel->rootIndex().data(Imap::Mailbox::RoleMailboxName).toString();
0550 }
0551 
0552 QString ImapAccess::mailboxListShortMailboxName() const
0553 {
0554     return m_mailboxSubtreeModel->rootIndex().data(Imap::Mailbox::RoleShortMailboxName).toString();
0555 }
0556 
0557 /** @short Persistently remove the local cache of IMAP data
0558 
0559 This method should be called by the UI when the user changes its connection details, i.e. when there's a big chance that we are
0560 connecting to a completely different server since the last time.
0561 */
0562 void ImapAccess::nukeCache()
0563 {
0564     Imap::removeRecursively(m_cacheDir);
0565 }
0566 
0567 QModelIndex ImapAccess::deproxifiedIndex(const QModelIndex index)
0568 {
0569     return Imap::deproxifiedIndex(index);
0570 }
0571 
0572 void ImapAccess::markMessageDeleted(const QModelIndex &message, bool marked)
0573 {
0574     Q_ASSERT(message.isValid());
0575     m_imapModel->markMessagesDeleted(QModelIndexList() << message, marked ? Imap::Mailbox::FLAG_ADD : Imap::Mailbox::FLAG_REMOVE);
0576 }
0577 
0578 int ImapAccess::numberRefreshInterval() const
0579 {
0580     int interval = m_settings->value(Common::SettingsNames::imapNumberRefreshInterval, QVariant(300)).toInt();
0581     if (interval < 30)
0582         interval = 30;
0583     else if (interval > 29*60)
0584         interval = 29*60;
0585     return interval;
0586 }
0587 
0588 void ImapAccess::setNumberRefreshInterval(const int interval)
0589 {
0590     m_settings->setValue(Common::SettingsNames::imapNumberRefreshInterval, interval);
0591     if (m_imapModel)
0592         m_imapModel->setNumberRefreshInterval(interval);
0593 }
0594 
0595 QString ImapAccess::accountName() const
0596 {
0597     return m_accountName;
0598 }
0599 
0600 bool ImapAccess::isConfigured() const
0601 {
0602     return m_settings->contains(Common::SettingsNames::imapMethodKey);
0603 }
0604 
0605 }