1 /* Copyright (C) 2006 - 2014 Jan Kundrát <jkt@flaska.net>
2
3 This file is part of the Trojita Qt IMAP e-mail client,
4 http://trojita.flaska.net/
5
6 This program is free software; you can redistribute it and/or
7 modify it under the terms of the GNU General Public License as
8 published by the Free Software Foundation; either version 2 of
9 the License or (at your option) version 3 or any later version
10 accepted by the membership of KDE e.V. (or its successor approved
11 by the membership of KDE e.V.), which shall act as a proxy
12 defined in Section 14 of version 3 of the license.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
21 */
22
23 #include "ImapAccess.h"
24 #include <QDir>
25 #include <QFileInfo>
26 #include <QSslKey>
27 #include <QSettings>
28 #include "Common/MetaTypes.h"
29 #include "Common/Paths.h"
30 #include "Common/PortNumbers.h"
31 #include "Common/SettingsNames.h"
32 #include "Imap/Model/CombinedCache.h"
33 #include "Imap/Model/DummyNetworkWatcher.h"
34 #include "Imap/Model/MailboxModel.h"
35 #include "Imap/Model/MemoryCache.h"
36 #include "Imap/Model/Model.h"
37 #include "Imap/Model/MsgListModel.h"
38 #include "Imap/Model/NetworkWatcher.h"
39 #include "Imap/Model/OneMessageModel.h"
40 #include "Imap/Model/SubtreeModel.h"
41 #include "Imap/Model/SystemNetworkWatcher.h"
42 #include "Imap/Model/ThreadingMsgListModel.h"
43 #include "Imap/Model/Utils.h"
44 #include "Imap/Model/VisibleTasksModel.h"
45 #include "Imap/Network/MsgPartNetAccessManager.h"
46 #include "Streams/SocketFactory.h"
47 #include "UiUtils/PasswordWatcher.h"
48
49 namespace Imap {
50
ImapAccess(QObject * parent,QSettings * settings,Plugins::PluginManager * pluginManager,const QString & accountName)51 ImapAccess::ImapAccess(QObject *parent, QSettings *settings, Plugins::PluginManager *pluginManager, const QString &accountName) :
52 QObject(parent), m_settings(settings), m_imapModel(0), m_mailboxModel(0), m_mailboxSubtreeModel(0), m_msgListModel(0),
53 m_threadingMsgListModel(0), m_visibleTasksModel(0), m_oneMessageModel(0), m_netWatcher(0), m_msgQNAM(0),
54 m_pluginManager(pluginManager), m_passwordWatcher(0), m_port(0),
55 m_connectionMethod(Common::ConnectionMethod::Invalid),
56 m_sslInfoIcon(UiUtils::Formatting::IconType::NoIcon),
57 m_accountName(accountName)
58 {
59 Imap::migrateSettings(m_settings);
60 reloadConfiguration();
61 m_cacheDir = Common::writablePath(Common::LOCATION_CACHE) + m_accountName + QLatin1Char('/');;
62 m_passwordWatcher = new UiUtils::PasswordWatcher(this, m_pluginManager,
63 // FIXME: this can be removed when support for multiple accounts is implemented
64 accountName.isEmpty() ? QStringLiteral("account-0") : accountName,
65 QStringLiteral("imap"));
66 }
67
reloadConfiguration()68 void ImapAccess::reloadConfiguration()
69 {
70 m_server = m_settings->value(Common::SettingsNames::imapHostKey).toString();
71 m_username = m_settings->value(Common::SettingsNames::imapUserKey).toString();
72 if (m_settings->value(Common::SettingsNames::imapMethodKey).toString() == Common::SettingsNames::methodSSL) {
73 m_connectionMethod = Common::ConnectionMethod::NetDedicatedTls;
74 } else if (m_settings->value(Common::SettingsNames::imapMethodKey).toString() == Common::SettingsNames::methodTCP) {
75 m_connectionMethod = m_settings->value(Common::SettingsNames::imapStartTlsKey).toBool() ?
76 Common::ConnectionMethod::NetStartTls : Common::ConnectionMethod::NetCleartext;
77 } else if (m_settings->value(Common::SettingsNames::imapMethodKey).toString() == Common::SettingsNames::methodProcess) {
78 m_connectionMethod = Common::ConnectionMethod::Process;
79 }
80 m_port = m_settings->value(Common::SettingsNames::imapPortKey, QVariant(0)).toInt();
81 if (!m_port) {
82 switch (m_connectionMethod) {
83 case Common::ConnectionMethod::NetCleartext:
84 case Common::ConnectionMethod::NetStartTls:
85 m_port = Common::PORT_IMAP;
86 break;
87 case Common::ConnectionMethod::NetDedicatedTls:
88 m_port = Common::PORT_IMAPS;
89 break;
90 case Common::ConnectionMethod::Process:
91 case Common::ConnectionMethod::Invalid:
92 // do nothing
93 break;
94 }
95 }
96 }
97
alertReceived(const QString & message)98 void ImapAccess::alertReceived(const QString &message)
99 {
100 qDebug() << "alertReceived" << message;
101 }
102
imapError(const QString & message)103 void ImapAccess::imapError(const QString &message)
104 {
105 qDebug() << "imapError" << message;
106 }
107
networkError(const QString & message)108 void ImapAccess::networkError(const QString &message)
109 {
110 qDebug() << "networkError" << message;
111 }
112
slotLogged(uint parserId,const Common::LogMessage & message)113 void ImapAccess::slotLogged(uint parserId, const Common::LogMessage &message)
114 {
115 if (message.kind != Common::LOG_IO_READ) {
116 qDebug() << "LOG" << parserId << message.timestamp << message.kind << message.source << message.message;
117 }
118 }
119
server() const120 QString ImapAccess::server() const
121 {
122 return m_server;
123 }
124
setServer(const QString & server)125 void ImapAccess::setServer(const QString &server)
126 {
127 m_server = server;
128 m_settings->setValue(Common::SettingsNames::imapHostKey, m_server);
129 emit serverChanged();
130 }
131
username() const132 QString ImapAccess::username() const
133 {
134 return m_username;
135 }
136
setUsername(const QString & username)137 void ImapAccess::setUsername(const QString &username)
138 {
139 m_username = username;
140 m_settings->setValue(Common::SettingsNames::imapUserKey, m_username);
141 emit usernameChanged();;
142 }
143
password() const144 QString ImapAccess::password() const
145 {
146 return m_password;
147 }
148
setPassword(const QString & password)149 void ImapAccess::setPassword(const QString &password)
150 {
151 m_password = password;
152 }
153
port() const154 int ImapAccess::port() const
155 {
156 return m_port;
157 }
158
setPort(const int port)159 void ImapAccess::setPort(const int port)
160 {
161 m_port = port;
162 m_settings->setValue(Common::SettingsNames::imapPortKey, m_port);
163 emit portChanged();
164 }
165
sslMode() const166 QString ImapAccess::sslMode() const
167 {
168 switch (m_connectionMethod) {
169 case Common::ConnectionMethod::NetCleartext:
170 return QStringLiteral("No");
171 case Common::ConnectionMethod::NetStartTls:
172 return QStringLiteral("StartTLS");
173 case Common::ConnectionMethod::NetDedicatedTls:
174 return QStringLiteral("SSL");
175 case Common::ConnectionMethod::Invalid:
176 case Common::ConnectionMethod::Process:
177 return QString();
178 }
179
180 Q_ASSERT(false);
181 return QString();
182 }
183
setSslMode(const QString & sslMode)184 void ImapAccess::setSslMode(const QString &sslMode)
185 {
186 if (sslMode == QLatin1String("No")) {
187 setConnectionMethod(Common::ConnectionMethod::NetCleartext);
188 } else if (sslMode == QLatin1String("SSL")) {
189 setConnectionMethod(Common::ConnectionMethod::NetDedicatedTls);
190 } else if (sslMode == QLatin1String("StartTLS")) {
191 setConnectionMethod(Common::ConnectionMethod::NetStartTls);
192 } else {
193 Q_ASSERT(false);
194 }
195 }
196
connectionMethod() const197 Common::ConnectionMethod ImapAccess::connectionMethod() const
198 {
199 return m_connectionMethod;
200 }
201
setConnectionMethod(const Common::ConnectionMethod mode)202 void ImapAccess::setConnectionMethod(const Common::ConnectionMethod mode)
203 {
204 m_connectionMethod = mode;
205 switch (m_connectionMethod) {
206 case Common::ConnectionMethod::Invalid:
207 break;
208 case Common::ConnectionMethod::NetCleartext:
209 case Common::ConnectionMethod::NetStartTls:
210 m_settings->setValue(Common::SettingsNames::imapMethodKey, Common::SettingsNames::methodTCP);
211 m_settings->setValue(Common::SettingsNames::imapStartTlsKey, m_connectionMethod == Common::ConnectionMethod::NetStartTls);
212 break;
213 case Common::ConnectionMethod::NetDedicatedTls:
214 m_settings->setValue(Common::SettingsNames::imapMethodKey, Common::SettingsNames::methodSSL);
215 // Trying to communicate the fact that this is going to be an encrypted connection, even though
216 // that settings bit is not actually used
217 m_settings->setValue(Common::SettingsNames::imapStartTlsKey, true);
218 break;
219 case Common::ConnectionMethod::Process:
220 m_settings->setValue(Common::SettingsNames::imapMethodKey, Common::SettingsNames::methodProcess);
221 break;
222 }
223 emit connMethodChanged();
224 }
225
preferredNetworkPolicy() const226 Imap::Mailbox::NetworkPolicy ImapAccess::preferredNetworkPolicy() const
227 {
228 auto val = m_settings->value(Common::SettingsNames::imapStartMode).toString();
229 if (val == Common::SettingsNames::netOffline) {
230 return Imap::Mailbox::NETWORK_OFFLINE;
231 } else if (val == Common::SettingsNames::netExpensive) {
232 return Imap::Mailbox::NETWORK_EXPENSIVE;
233 } else {
234 return Imap::Mailbox::NETWORK_ONLINE;
235 }
236 }
237
doConnect()238 void ImapAccess::doConnect()
239 {
240 if (m_netWatcher) {
241 // We're temporarily "disabling" this connection. Otherwise this "offline preference"
242 // would get saved into the config file, which would be bad.
243 disconnect(m_netWatcher, &Mailbox::NetworkWatcher::desiredNetworkPolicyChanged, this, &ImapAccess::desiredNetworkPolicyChanged);
244 }
245
246 if (m_imapModel) {
247 // Disconnect from network, nuke the models
248 Q_ASSERT(m_netWatcher);
249 m_netWatcher->setNetworkOffline();
250 delete m_threadingMsgListModel;
251 m_threadingMsgListModel = 0;
252 delete m_msgQNAM;
253 m_msgQNAM = 0;
254 delete m_oneMessageModel;
255 m_oneMessageModel = 0;
256 delete m_visibleTasksModel;
257 m_visibleTasksModel = 0;
258 delete m_msgListModel;
259 m_msgListModel = 0;
260 delete m_mailboxSubtreeModel;
261 m_mailboxSubtreeModel = 0;
262 delete m_mailboxModel;
263 m_mailboxModel = 0;
264 delete m_netWatcher;
265 m_netWatcher = 0;
266 delete m_imapModel;
267 m_imapModel = 0;
268 }
269
270 Q_ASSERT(!m_imapModel);
271
272 Imap::Mailbox::SocketFactoryPtr factory;
273 Imap::Mailbox::TaskFactoryPtr taskFactory(new Imap::Mailbox::TaskFactory());
274
275 Streams::ProxySettings proxySettings = m_settings->value(Common::SettingsNames::imapUseSystemProxy, true).toBool() ?
276 Streams::ProxySettings::RespectSystemProxy : Streams::ProxySettings::DirectConnect;
277
278 switch (m_connectionMethod) {
279 case Common::ConnectionMethod::Invalid:
280 factory.reset(new Streams::FakeSocketFactory(Imap::CONN_STATE_LOGOUT));
281 break;
282 case Common::ConnectionMethod::NetCleartext:
283 case Common::ConnectionMethod::NetStartTls:
284 factory.reset(new Streams::TlsAbleSocketFactory(server(), port()));
285 factory->setStartTlsRequired(m_connectionMethod == Common::ConnectionMethod::NetStartTls);
286 factory->setProxySettings(proxySettings, QStringLiteral("imap"));
287 break;
288 case Common::ConnectionMethod::NetDedicatedTls:
289 factory.reset(new Streams::SslSocketFactory(server(), port()));
290 factory->setProxySettings(proxySettings, QStringLiteral("imap"));
291 break;
292 case Common::ConnectionMethod::Process:
293 QStringList args = m_settings->value(Common::SettingsNames::imapProcessKey).toString().split(QLatin1Char(' '));
294 if (args.isEmpty()) {
295 // it's going to fail anyway
296 args << QLatin1String("");
297 }
298 QString appName = args.takeFirst();
299 factory.reset(new Streams::ProcessSocketFactory(appName, args));
300 break;
301 }
302
303 bool shouldUsePersistentCache =
304 m_settings->value(Common::SettingsNames::cacheOfflineKey).toString() != Common::SettingsNames::cacheOfflineNone;
305
306 if (shouldUsePersistentCache && !QDir().mkpath(m_cacheDir)) {
307 onCacheError(tr("Failed to create directory %1").arg(m_cacheDir));
308 shouldUsePersistentCache = false;
309 }
310
311 if (shouldUsePersistentCache) {
312 QFile::Permissions expectedPerms = QFile::ReadOwner | QFile::WriteOwner | QFile::ExeOwner;
313 if (QFileInfo(m_cacheDir).permissions() != expectedPerms) {
314 if (!QFile::setPermissions(m_cacheDir, expectedPerms)) {
315 #ifndef Q_OS_WIN32
316 onCacheError(tr("Failed to set safe permissions on cache directory %1").arg(m_cacheDir));
317 shouldUsePersistentCache = false;
318 #endif
319 }
320 }
321 }
322
323 Imap::Mailbox::AbstractCache *cache = 0;
324
325 if (!shouldUsePersistentCache) {
326 cache = new Imap::Mailbox::MemoryCache(this);
327 } else {
328 cache = new Imap::Mailbox::CombinedCache(this, QStringLiteral("trojita-imap-cache"), m_cacheDir);
329 connect(cache, &Mailbox::AbstractCache::error, this, &ImapAccess::onCacheError);
330 if (! static_cast<Imap::Mailbox::CombinedCache *>(cache)->open()) {
331 // Error message was already shown by the cacheError() slot
332 cache->deleteLater();
333 cache = new Imap::Mailbox::MemoryCache(this);
334 } else {
335 if (m_settings->value(Common::SettingsNames::cacheOfflineKey).toString() == Common::SettingsNames::cacheOfflineAll) {
336 cache->setRenewalThreshold(0);
337 } else {
338 const int defaultCacheLifetime = 30;
339 bool ok;
340 int num = m_settings->value(Common::SettingsNames::cacheOfflineNumberDaysKey, defaultCacheLifetime).toInt(&ok);
341 if (!ok)
342 num = defaultCacheLifetime;
343 cache->setRenewalThreshold(num);
344 }
345 }
346 }
347
348 m_imapModel = new Imap::Mailbox::Model(this, cache, std::move(factory), std::move(taskFactory));
349 m_imapModel->setObjectName(QStringLiteral("imapModel-%1").arg(m_accountName));
350 m_imapModel->setCapabilitiesBlacklist(m_settings->value(Common::SettingsNames::imapBlacklistedCapabilities).toStringList());
351 m_imapModel->setProperty("trojita-imap-id-no-versions", !m_settings->value(Common::SettingsNames::interopRevealVersions, true).toBool());
352 m_imapModel->setProperty("trojita-imap-idle-renewal", m_settings->value(Common::SettingsNames::imapIdleRenewal).toUInt() * 60 * 1000);
353 m_imapModel->setNumberRefreshInterval(numberRefreshInterval());
354 connect(m_imapModel, &Mailbox::Model::alertReceived, this, &ImapAccess::alertReceived);
355 connect(m_imapModel, &Mailbox::Model::imapError, this, &ImapAccess::imapError);
356 connect(m_imapModel, &Mailbox::Model::networkError, this, &ImapAccess::networkError);
357 //connect(m_imapModel, &Mailbox::Model::logged, this, &ImapAccess::slotLogged);
358 connect(m_imapModel, &Mailbox::Model::needsSslDecision, this, &ImapAccess::slotSslErrors);
359 connect(m_imapModel, &Mailbox::Model::requireStartTlsInFuture, this, &ImapAccess::onRequireStartTlsInFuture);
360
361 if (m_settings->value(Common::SettingsNames::imapNeedsNetwork, true).toBool()) {
362 m_netWatcher = new Imap::Mailbox::SystemNetworkWatcher(this, m_imapModel);
363 } else {
364 m_netWatcher = new Imap::Mailbox::DummyNetworkWatcher(this, m_imapModel);
365 }
366 connect(m_netWatcher, &Mailbox::NetworkWatcher::desiredNetworkPolicyChanged, this, &ImapAccess::desiredNetworkPolicyChanged);
367 switch (preferredNetworkPolicy()) {
368 case Imap::Mailbox::NETWORK_OFFLINE:
369 QMetaObject::invokeMethod(m_netWatcher, "setNetworkOffline", Qt::QueuedConnection);
370 break;
371 case Imap::Mailbox::NETWORK_EXPENSIVE:
372 QMetaObject::invokeMethod(m_netWatcher, "setNetworkExpensive", Qt::QueuedConnection);
373 break;
374 case Imap::Mailbox::NETWORK_ONLINE:
375 QMetaObject::invokeMethod(m_netWatcher, "setNetworkOnline", Qt::QueuedConnection);
376 break;
377 }
378
379 m_imapModel->setImapUser(username());
380 if (!m_password.isNull()) {
381 // Really; the idea is to wait before it has been set for the first time
382 m_imapModel->setImapPassword(password());
383 }
384
385 m_mailboxModel = new Imap::Mailbox::MailboxModel(this, m_imapModel);
386 m_mailboxModel->setObjectName(QStringLiteral("mailboxModel-%1").arg(m_accountName));
387 m_mailboxSubtreeModel = new Imap::Mailbox::SubtreeModelOfMailboxModel(this);
388 m_mailboxSubtreeModel->setObjectName(QStringLiteral("mailboxSubtreeModel-%1").arg(m_accountName));
389 m_mailboxSubtreeModel->setSourceModel(m_mailboxModel);
390 m_mailboxSubtreeModel->setOriginalRoot();
391 m_msgListModel = new Imap::Mailbox::MsgListModel(this, m_imapModel);
392 m_msgListModel->setObjectName(QStringLiteral("msgListModel-%1").arg(m_accountName));
393 m_visibleTasksModel = new Imap::Mailbox::VisibleTasksModel(this, m_imapModel->taskModel());
394 m_visibleTasksModel->setObjectName(QStringLiteral("visibleTasksModel-%1").arg(m_accountName));
395 m_oneMessageModel = new Imap::Mailbox::OneMessageModel(m_imapModel);
396 m_oneMessageModel->setObjectName(QStringLiteral("oneMessageModel-%1").arg(m_accountName));
397 m_msgQNAM = new Imap::Network::MsgPartNetAccessManager(this);
398 m_msgQNAM->setObjectName(QStringLiteral("m_msgQNAM-%1").arg(m_accountName));
399 m_threadingMsgListModel = new Imap::Mailbox::ThreadingMsgListModel(this);
400 m_threadingMsgListModel->setObjectName(QStringLiteral("threadingMsgListModel-%1").arg(m_accountName));
401 m_threadingMsgListModel->setSourceModel(m_msgListModel);
402 emit modelsChanged();
403 }
404
onCacheError(const QString & message)405 void ImapAccess::onCacheError(const QString &message)
406 {
407 if (m_imapModel) {
408 m_imapModel->setCache(new Imap::Mailbox::MemoryCache(m_imapModel));
409 }
410 emit cacheError(message);
411 }
412
imapModel() const413 QAbstractItemModel *ImapAccess::imapModel() const
414 {
415 return m_imapModel;
416 }
417
mailboxModel() const418 QAbstractItemModel *ImapAccess::mailboxModel() const
419 {
420 return m_mailboxSubtreeModel;
421 }
422
msgListModel() const423 QAbstractItemModel *ImapAccess::msgListModel() const
424 {
425 return m_msgListModel;
426 }
427
visibleTasksModel() const428 QAbstractItemModel *ImapAccess::visibleTasksModel() const
429 {
430 return m_visibleTasksModel;
431 }
432
oneMessageModel() const433 QObject *ImapAccess::oneMessageModel() const
434 {
435 return m_oneMessageModel;
436 }
437
networkWatcher() const438 QObject *ImapAccess::networkWatcher() const
439 {
440 return m_netWatcher;
441 }
442
msgQNAM() const443 QObject *ImapAccess::msgQNAM() const
444 {
445 return m_msgQNAM;
446 }
447
threadingMsgListModel() const448 QAbstractItemModel *ImapAccess::threadingMsgListModel() const
449 {
450 return m_threadingMsgListModel;
451 }
452
passwordWatcher() const453 UiUtils::PasswordWatcher *ImapAccess::passwordWatcher() const
454 {
455 return m_passwordWatcher;
456 }
457
openMessage(const QString & mailboxName,const uint uid)458 void ImapAccess::openMessage(const QString &mailboxName, const uint uid)
459 {
460 QModelIndex msgIndex = m_imapModel->messageIndexByUid(mailboxName, uid);
461 m_oneMessageModel->setMessage(msgIndex);
462 static_cast<Imap::Network::MsgPartNetAccessManager*>(m_msgQNAM)->setModelMessage(msgIndex);
463 }
464
slotSslErrors(const QList<QSslCertificate> & sslCertificateChain,const QList<QSslError> & sslErrors)465 void ImapAccess::slotSslErrors(const QList<QSslCertificate> &sslCertificateChain, const QList<QSslError> &sslErrors)
466 {
467 m_sslChain = sslCertificateChain;
468 m_sslErrors = sslErrors;
469
470 QByteArray lastKnownPubKey = m_settings->value(Common::SettingsNames::imapSslPemPubKey).toByteArray();
471 if (!m_sslChain.isEmpty() && !lastKnownPubKey.isEmpty() && lastKnownPubKey == m_sslChain[0].publicKey().toPem()) {
472 // This certificate chain contains the same public keys as the last time; we should accept that
473 m_imapModel->setSslPolicy(m_sslChain, m_sslErrors, true);
474 } else {
475 UiUtils::Formatting::formatSslState(
476 m_sslChain, lastKnownPubKey, m_sslErrors, &m_sslInfoTitle, &m_sslInfoMessage, &m_sslInfoIcon);
477 emit checkSslPolicy();
478 }
479 }
480
481 /** @short Remember to use STARTTLS during the next connection
482
483 Once a first STARTTLS attempt succeeds, change the preferences to require STARTTLS in future. This is needed
484 to prevent a possible SSL stripping attack by a malicious proxy during subsequent connections.
485 */
onRequireStartTlsInFuture()486 void ImapAccess::onRequireStartTlsInFuture()
487 {
488 // It's possible that we're called after the user has already changed their preferences.
489 // In order to not change stuff which was not supposed to be changed, let's make sure that we won't undo their changes.
490 if (connectionMethod() == Common::ConnectionMethod::NetCleartext) {
491 setConnectionMethod(Common::ConnectionMethod::NetStartTls);
492 }
493 }
494
desiredNetworkPolicyChanged(const Mailbox::NetworkPolicy policy)495 void ImapAccess::desiredNetworkPolicyChanged(const Mailbox::NetworkPolicy policy)
496 {
497 switch (policy) {
498 case Mailbox::NETWORK_OFFLINE:
499 m_settings->setValue(Common::SettingsNames::imapStartMode, Common::SettingsNames::netOffline);
500 break;
501 case Mailbox::NETWORK_EXPENSIVE:
502 m_settings->setValue(Common::SettingsNames::imapStartMode, Common::SettingsNames::netExpensive);
503 break;
504 case Mailbox::NETWORK_ONLINE:
505 m_settings->setValue(Common::SettingsNames::imapStartMode, Common::SettingsNames::netOnline);
506 break;
507 }
508 }
509
setSslPolicy(bool accept)510 void ImapAccess::setSslPolicy(bool accept)
511 {
512 if (accept && !m_sslChain.isEmpty()) {
513 m_settings->setValue(Common::SettingsNames::imapSslPemPubKey, m_sslChain[0].publicKey().toPem());
514 }
515 m_imapModel->setSslPolicy(m_sslChain, m_sslErrors, accept);
516 }
517
forgetSslCertificate()518 void ImapAccess::forgetSslCertificate()
519 {
520 m_settings->remove(Common::SettingsNames::imapSslPemPubKey);
521 }
522
sslInfoTitle() const523 QString ImapAccess::sslInfoTitle() const
524 {
525 return m_sslInfoTitle;
526 }
527
sslInfoMessage() const528 QString ImapAccess::sslInfoMessage() const
529 {
530 return m_sslInfoMessage;
531 }
532
sslInfoIcon() const533 UiUtils::Formatting::IconType ImapAccess::sslInfoIcon() const
534 {
535 return m_sslInfoIcon;
536 }
537
mailboxListMailboxName() const538 QString ImapAccess::mailboxListMailboxName() const
539 {
540 return m_mailboxSubtreeModel->rootIndex().data(Imap::Mailbox::RoleMailboxName).toString();
541 }
542
mailboxListShortMailboxName() const543 QString ImapAccess::mailboxListShortMailboxName() const
544 {
545 return m_mailboxSubtreeModel->rootIndex().data(Imap::Mailbox::RoleShortMailboxName).toString();
546 }
547
548 /** @short Persistently remove the local cache of IMAP data
549
550 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
551 connecting to a completely different server since the last time.
552 */
nukeCache()553 void ImapAccess::nukeCache()
554 {
555 Imap::removeRecursively(m_cacheDir);
556 }
557
deproxifiedIndex(const QModelIndex index)558 QModelIndex ImapAccess::deproxifiedIndex(const QModelIndex index)
559 {
560 return Imap::deproxifiedIndex(index);
561 }
562
markMessageDeleted(const QModelIndex & message,bool marked)563 void ImapAccess::markMessageDeleted(const QModelIndex &message, bool marked)
564 {
565 Q_ASSERT(message.isValid());
566 m_imapModel->markMessagesDeleted(QModelIndexList() << message, marked ? Imap::Mailbox::FLAG_ADD : Imap::Mailbox::FLAG_REMOVE);
567 }
568
numberRefreshInterval() const569 int ImapAccess::numberRefreshInterval() const
570 {
571 int interval = m_settings->value(Common::SettingsNames::imapNumberRefreshInterval, QVariant(300)).toInt();
572 if (interval < 30)
573 interval = 30;
574 else if (interval > 29*60)
575 interval = 29*60;
576 return interval;
577 }
578
setNumberRefreshInterval(const int interval)579 void ImapAccess::setNumberRefreshInterval(const int interval)
580 {
581 m_settings->setValue(Common::SettingsNames::imapNumberRefreshInterval, interval);
582 if (m_imapModel)
583 m_imapModel->setNumberRefreshInterval(interval);
584 }
585
accountName() const586 QString ImapAccess::accountName() const
587 {
588 return m_accountName;
589 }
590
isConfigured() const591 bool ImapAccess::isConfigured() const
592 {
593 return m_settings->contains(Common::SettingsNames::imapMethodKey);
594 }
595
596 }
597