MailTransport

servertest.cpp
1 /*
2  SPDX-FileCopyrightText: 2006-2007 Volker Krause <[email protected]>
3  SPDX-FileCopyrightText: 2007 KovoKs <[email protected]>
4  SPDX-FileCopyrightText: 2008 Thomas McGuire <[email protected]>
5 
6  SPDX-License-Identifier: LGPL-2.0-or-later
7 */
8 
9 // Own
10 #include "servertest.h"
11 #include "socket.h"
12 
13 #include <mailtransport_defs.h>
14 #include <transportbase.h>
15 
16 // Qt
17 #include <QHash>
18 #include <QHostInfo>
19 #include <QProgressBar>
20 #include <QRegularExpression>
21 #include <QSet>
22 #include <QTimer>
23 
24 // KDE
25 #include "mailtransport_debug.h"
26 
27 using namespace MailTransport;
28 
29 namespace MailTransport
30 {
31 class ServerTestPrivate
32 {
33 public:
34  ServerTestPrivate(ServerTest *test);
35 
36  ServerTest *const q;
37  QString server;
38  QString fakeHostname;
39  QString testProtocol;
40 
41  MailTransport::Socket *normalSocket = nullptr;
42  MailTransport::Socket *secureSocket = nullptr;
43 
44  QSet<int> connectionResults;
45  QHash<int, QVector<int>> authenticationResults;
46  QSet<ServerTest::Capability> capabilityResults;
47  QHash<int, uint> customPorts;
48  QTimer *normalSocketTimer = nullptr;
49  QTimer *secureSocketTimer = nullptr;
50  QTimer *progressTimer = nullptr;
51 
52  QProgressBar *testProgress = nullptr;
53 
54  bool secureSocketFinished = false;
55  bool normalSocketFinished = false;
56  bool tlsFinished = false;
57  bool popSupportsTLS;
58  int normalStage;
59  int secureStage;
60  int encryptionMode;
61 
62  bool normalPossible = true;
63  bool securePossible = true;
64 
65  void finalResult();
66  void handleSMTPIMAPResponse(int type, const QString &text);
67  void sendInitialCapabilityQuery(MailTransport::Socket *socket);
68  bool handlePopConversation(MailTransport::Socket *socket, int type, int stage, const QString &response, bool *shouldStartTLS);
69  bool handleNntpConversation(MailTransport::Socket *socket, int type, int *stage, const QString &response, bool *shouldStartTLS);
70  QVector<int> parseAuthenticationList(const QStringList &authentications);
71 
72  Q_REQUIRED_RESULT inline bool isGmail(const QString &server) const
73  {
74  return server.endsWith(QLatin1String("gmail.com")) || server.endsWith(QLatin1String("googlemail.com"));
75  }
76 
77  // slots
78  void slotNormalPossible();
79  void slotNormalNotPossible();
80  void slotSslPossible();
81  void slotSslNotPossible();
82  void slotTlsDone();
83  void slotReadNormal(const QString &text);
84  void slotReadSecure(const QString &text);
85  void slotUpdateProgress();
86 };
87 }
88 
89 ServerTestPrivate::ServerTestPrivate(ServerTest *test)
90  : q(test)
91 {
92 }
93 
94 void ServerTestPrivate::finalResult()
95 {
96  if (!secureSocketFinished || !normalSocketFinished || !tlsFinished) {
97  return;
98  }
99 
100  qCDebug(MAILTRANSPORT_LOG) << "Modes:" << connectionResults;
101  qCDebug(MAILTRANSPORT_LOG) << "Capabilities:" << capabilityResults;
102  qCDebug(MAILTRANSPORT_LOG) << "Normal:" << q->normalProtocols();
103  qCDebug(MAILTRANSPORT_LOG) << "SSL:" << q->secureProtocols();
104  qCDebug(MAILTRANSPORT_LOG) << "TLS:" << q->tlsProtocols();
105 
106  if (testProgress) {
107  testProgress->hide();
108  }
109  progressTimer->stop();
110  secureSocketFinished = false;
111  normalSocketFinished = false;
112  tlsFinished = false;
113 
114  QVector<int> resultsAsVector;
115  resultsAsVector.reserve(connectionResults.size());
116  for (int res : std::as_const(connectionResults)) {
117  resultsAsVector.append(res);
118  }
119 
120  Q_EMIT q->finished(resultsAsVector);
121 }
122 
123 QVector<int> ServerTestPrivate::parseAuthenticationList(const QStringList &authentications)
124 {
125  QVector<int> result;
126  for (QStringList::ConstIterator it = authentications.begin(); it != authentications.end(); ++it) {
127  QString current = (*it).toUpper();
128  if (current == QLatin1String("LOGIN")) {
129  result << Transport::EnumAuthenticationType::LOGIN;
130  } else if (current == QLatin1String("PLAIN")) {
131  result << Transport::EnumAuthenticationType::PLAIN;
132  } else if (current == QLatin1String("CRAM-MD5")) {
133  result << Transport::EnumAuthenticationType::CRAM_MD5;
134  } else if (current == QLatin1String("DIGEST-MD5")) {
135  result << Transport::EnumAuthenticationType::DIGEST_MD5;
136  } else if (current == QLatin1String("NTLM")) {
137  result << Transport::EnumAuthenticationType::NTLM;
138  } else if (current == QLatin1String("GSSAPI")) {
139  result << Transport::EnumAuthenticationType::GSSAPI;
140  } else if (current == QLatin1String("ANONYMOUS")) {
141  result << Transport::EnumAuthenticationType::ANONYMOUS;
142  } else if (current == QLatin1String("XOAUTH2")) {
143  if (isGmail(server)) {
144  result << Transport::EnumAuthenticationType::XOAUTH2;
145  }
146  }
147  // APOP is handled by handlePopConversation()
148  }
149  qCDebug(MAILTRANSPORT_LOG) << authentications << result;
150 
151  // LOGIN doesn't offer anything over PLAIN, requires more server
152  // roundtrips and is not an official SASL mechanism, but a MS-ism,
153  // so only enable it if PLAIN isn't available:
154  if (result.contains(Transport::EnumAuthenticationType::PLAIN)) {
155  result.removeAll(Transport::EnumAuthenticationType::LOGIN);
156  }
157 
158  return result;
159 }
160 
161 void ServerTestPrivate::handleSMTPIMAPResponse(int type, const QString &text)
162 {
163  if (!text.contains(QLatin1String("AUTH"), Qt::CaseInsensitive)) {
164  qCDebug(MAILTRANSPORT_LOG) << "No authentication possible";
165  return;
166  }
167 
168  QStringList protocols;
169  if (isGmail(server)) {
170  protocols << QStringLiteral("XOAUTH2");
171  }
172 
173  protocols << QStringLiteral("LOGIN") << QStringLiteral("PLAIN") << QStringLiteral("CRAM-MD5") << QStringLiteral("DIGEST-MD5") << QStringLiteral("NTLM")
174  << QStringLiteral("GSSAPI") << QStringLiteral("ANONYMOUS");
175 
176  QStringList results;
177  for (int i = 0; i < protocols.count(); ++i) {
178  if (text.contains(protocols.at(i), Qt::CaseInsensitive)) {
179  results.append(protocols.at(i));
180  }
181  }
182 
183  authenticationResults[type] = parseAuthenticationList(results);
184 
185  // if we couldn't parse any authentication modes, default to clear-text
186  if (authenticationResults[type].isEmpty()) {
187  authenticationResults[type] << Transport::EnumAuthenticationType::CLEAR;
188  }
189 
190  qCDebug(MAILTRANSPORT_LOG) << "For type" << type << ", we have:" << authenticationResults[type];
191 }
192 
193 void ServerTestPrivate::slotNormalPossible()
194 {
195  normalSocketTimer->stop();
196  connectionResults << Transport::EnumEncryption::None;
197 }
198 
199 void ServerTestPrivate::sendInitialCapabilityQuery(MailTransport::Socket *socket)
200 {
201  if (testProtocol == IMAP_PROTOCOL) {
202  socket->write(QStringLiteral("1 CAPABILITY"));
203  } else if (testProtocol == SMTP_PROTOCOL) {
204  // Detect the hostname which we send with the EHLO command.
205  // If there is a fake one set, use that, otherwise use the
206  // local host name (and make sure it contains a domain, so the
207  // server thinks it is valid).
209  if (!fakeHostname.isNull()) {
210  hostname = fakeHostname;
211  } else {
213  if (hostname.isEmpty()) {
214  hostname = QStringLiteral("localhost.invalid");
215  } else if (!hostname.contains(QChar::fromLatin1('.'))) {
216  hostname += QLatin1String(".localnet");
217  }
218  }
219  qCDebug(MAILTRANSPORT_LOG) << "Hostname for EHLO is" << hostname;
220 
221  socket->write(QLatin1String("EHLO ") + hostname);
222  }
223 }
224 
225 void ServerTestPrivate::slotTlsDone()
226 {
227  // The server will not send a response after starting TLS. Therefore, we have to manually
228  // call slotReadNormal(), because this is not triggered by a data received signal this time.
229  slotReadNormal(QString());
230 }
231 
232 bool ServerTestPrivate::handlePopConversation(MailTransport::Socket *socket, int type, int stage, const QString &response, bool *shouldStartTLS)
233 {
234  Q_ASSERT(shouldStartTLS != nullptr);
235 
236  // Initial Greeting
237  if (stage == 0) {
238  // Regexp taken from POP3 ioslave
239  const QString responseWithoutCRLF = response.isEmpty() ? response : response.chopped(2);
240  static const QRegularExpression re(QStringLiteral("<[A-Za-z0-9\\.\\-_][email protected][A-Za-z0-9\\.\\-_]+>$"), QRegularExpression::CaseInsensitiveOption);
241  if (responseWithoutCRLF.indexOf(re) != -1) {
242  authenticationResults[type] << Transport::EnumAuthenticationType::APOP;
243  }
244 
245  // Each server is supposed to support clear text login
246  authenticationResults[type] << Transport::EnumAuthenticationType::CLEAR;
247 
248  // If we are in TLS stage, the server does not send the initial greeting.
249  // Assume that the APOP availability is the same as with an unsecured connection.
250  if (type == Transport::EnumEncryption::TLS
251  && authenticationResults[Transport::EnumEncryption::None].contains(Transport::EnumAuthenticationType::APOP)) {
252  authenticationResults[Transport::EnumEncryption::TLS] << Transport::EnumAuthenticationType::APOP;
253  }
254 
255  socket->write(QStringLiteral("CAPA"));
256  return true;
257  }
258  // CAPA result
259  else if (stage == 1) {
260  // Example:
261  // CAPA
262  // +OK
263  // TOP
264  // USER
265  // SASL LOGIN CRAM-MD5
266  // UIDL
267  // RESP-CODES
268  // .
269  if (response.contains(QLatin1String("TOP"))) {
270  capabilityResults += ServerTest::Top;
271  }
272  if (response.contains(QLatin1String("PIPELINING"))) {
273  capabilityResults += ServerTest::Pipelining;
274  }
275  if (response.contains(QLatin1String("UIDL"))) {
276  capabilityResults += ServerTest::UIDL;
277  }
278  if (response.contains(QLatin1String("STLS"))) {
279  connectionResults << Transport::EnumEncryption::TLS;
280  popSupportsTLS = true;
281  }
282  socket->write(QStringLiteral("AUTH"));
283  return true;
284  }
285  // AUTH response
286  else if (stage == 2) {
287  // Example:
288  // C: AUTH
289  // S: +OK List of supported authentication methods follows
290  // S: LOGIN
291  // S: CRAM-MD5
292  // S:.
293  QString formattedReply = response;
294 
295  // Get rid of trailing ".CRLF"
296  formattedReply.chop(3);
297 
298  // Get rid of the first +OK line
299  formattedReply = formattedReply.right(formattedReply.size() - formattedReply.indexOf(QLatin1Char('\n')) - 1);
300  formattedReply = formattedReply.replace(QLatin1Char(' '), QLatin1Char('-')).replace(QLatin1String("\r\n"), QLatin1String(" "));
301 
302  authenticationResults[type] += parseAuthenticationList(formattedReply.split(QLatin1Char(' ')));
303  }
304 
305  *shouldStartTLS = popSupportsTLS;
306  return false;
307 }
308 
309 bool ServerTestPrivate::handleNntpConversation(MailTransport::Socket *socket, int type, int *stage, const QString &response, bool *shouldStartTLS)
310 {
311  Q_ASSERT(shouldStartTLS != nullptr);
312  Q_ASSERT(stage != nullptr);
313 
314  // Initial Greeting
315  if (*stage == 0) {
316  if (response.startsWith(QLatin1String("382 "))) {
317  return true;
318  }
319  if (!response.isEmpty() && !response.startsWith(QLatin1String("200 "))) {
320  return false;
321  }
322 
323  socket->write(QStringLiteral("CAPABILITIES"));
324  return true;
325  }
326  // CAPABILITIES result
327  else if (*stage == 1) {
328  // Check whether we got "500 command 'CAPABILITIES' not recognized"
329  if (response.startsWith(QLatin1String("500 "))) {
330  return false;
331  }
332 
333  // Example:
334  // 101 Capability list:
335  // VERSION 2
336  // IMPLEMENTATION INN 2.5.4
337  // AUTHINFO USER SASL
338  // HDR
339  // LIST ACTIVE [etc]
340  // OVER
341  // POST
342  // READER
343  // SASL DIGEST-MD5 CRAM-MD5 NTLM PLAIN LOGIN
344  // STARTTLS
345  // .
346 #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
347  const QVector<QStringView> lines = QStringView(response).split(QStringLiteral("\r\n"), Qt::SkipEmptyParts);
348  for (const QStringView line : lines) {
349 #else
350  const QVector<QStringRef> lines = response.splitRef(QStringLiteral("\r\n"), Qt::SkipEmptyParts);
351  for (const QStringRef &line : lines) {
352 #endif
353  if (line.compare(QLatin1String("STARTTLS"), Qt::CaseInsensitive) == 0) {
354  *shouldStartTLS = true;
355  } else if (line.startsWith(QLatin1String("AUTHINFO "), Qt::CaseInsensitive)) {
356 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
357  const QVector<QStringRef> authinfos = line.split(QLatin1Char(' '), Qt::SkipEmptyParts);
358 #else
359  const QVector<QStringView> authinfos = QStringView(line).split(QLatin1Char(' '), Qt::SkipEmptyParts);
360 #endif
361  const QString s(QStringLiteral("USER"));
362 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
363  const QStringRef ref(&s);
364 #else
365  const QStringView ref(s);
366 #endif
367  if (authinfos.contains(ref)) {
368  authenticationResults[type].append(Transport::EnumAuthenticationType::CLEAR); // XXX
369  }
370  } else if (line.startsWith(QLatin1String("SASL "), Qt::CaseInsensitive)) {
371  const QStringList auths = line.mid(5).toString().split(QLatin1Char(' '), Qt::SkipEmptyParts);
372  authenticationResults[type] += parseAuthenticationList(auths);
373  } else if (line == QLatin1Char('.')) {
374  return false;
375  }
376  }
377  // We have not hit the end of the capabilities list yet,
378  // so avoid the stage counter to rise without reason.
379  --(*stage);
380  return true;
381  }
382 
383  return false;
384 }
385 
386 // slotReadNormal() handles normal (no) encryption and TLS encryption.
387 // At first, the communication is not encrypted, but if the server supports
388 // the STARTTLS/STLS keyword, the same authentication query is done again
389 // with TLS.
390 void ServerTestPrivate::slotReadNormal(const QString &text)
391 {
392  Q_ASSERT(encryptionMode != Transport::EnumEncryption::SSL);
393  static const int tlsHandshakeStage = 42;
394 
395  qCDebug(MAILTRANSPORT_LOG) << "Stage" << normalStage + 1 << ", Mode" << encryptionMode;
396 
397  // If we are in stage 42, we just do the handshake for TLS encryption and
398  // then reset the stage to -1, so that all authentication modes and
399  // capabilities are queried again for TLS encryption (some servers have
400  // different authentication methods in normal and in TLS mode).
401  if (normalStage == tlsHandshakeStage) {
402  Q_ASSERT(encryptionMode == Transport::EnumEncryption::TLS);
403  normalStage = -1;
404  normalSocket->startTLS();
405  return;
406  }
407 
408  bool shouldStartTLS = false;
409  normalStage++;
410 
411  // Handle the whole POP and NNTP conversations separately, as
412  // they are very different from IMAP and SMTP
413  if (testProtocol == POP_PROTOCOL) {
414  if (handlePopConversation(normalSocket, encryptionMode, normalStage, text, &shouldStartTLS)) {
415  return;
416  }
417  } else if (testProtocol == NNTP_PROTOCOL) {
418  if (handleNntpConversation(normalSocket, encryptionMode, &normalStage, text, &shouldStartTLS)) {
419  return;
420  }
421  } else {
422  // Handle the SMTP/IMAP conversation here. We just send the EHLO command in
423  // sendInitialCapabilityQuery.
424  if (normalStage == 0) {
425  sendInitialCapabilityQuery(normalSocket);
426  return;
427  }
428 
429  if (text.contains(QLatin1String("STARTTLS"), Qt::CaseInsensitive)) {
430  connectionResults << Transport::EnumEncryption::TLS;
431  shouldStartTLS = true;
432  }
433  handleSMTPIMAPResponse(encryptionMode, text);
434  }
435 
436  // If we reach here, the normal authentication/capabilities query is completed.
437  // Now do the same for TLS.
438  normalSocketFinished = true;
439 
440  // If the server announced that STARTTLS/STLS is available, we'll add TLS to the
441  // connection result, do the command and set the stage to 42 to start the handshake.
442  if (shouldStartTLS && encryptionMode == Transport::EnumEncryption::None) {
443  qCDebug(MAILTRANSPORT_LOG) << "Trying TLS...";
444  connectionResults << Transport::EnumEncryption::TLS;
445  if (testProtocol == POP_PROTOCOL) {
446  normalSocket->write(QStringLiteral("STLS"));
447  } else if (testProtocol == IMAP_PROTOCOL) {
448  normalSocket->write(QStringLiteral("2 STARTTLS"));
449  } else {
450  normalSocket->write(QStringLiteral("STARTTLS"));
451  }
452  encryptionMode = Transport::EnumEncryption::TLS;
453  normalStage = tlsHandshakeStage;
454  return;
455  }
456 
457  // If we reach here, either the TLS authentication/capabilities query is finished
458  // or the server does not support the STARTTLS/STLS command.
459  tlsFinished = true;
460  finalResult();
461 }
462 
463 void ServerTestPrivate::slotReadSecure(const QString &text)
464 {
465  secureStage++;
466  if (testProtocol == POP_PROTOCOL) {
467  bool dummy;
468  if (handlePopConversation(secureSocket, Transport::EnumEncryption::SSL, secureStage, text, &dummy)) {
469  return;
470  }
471  } else if (testProtocol == NNTP_PROTOCOL) {
472  bool dummy;
473  if (handleNntpConversation(secureSocket, Transport::EnumEncryption::SSL, &secureStage, text, &dummy)) {
474  return;
475  }
476  } else {
477  if (secureStage == 0) {
478  sendInitialCapabilityQuery(secureSocket);
479  return;
480  }
481  handleSMTPIMAPResponse(Transport::EnumEncryption::SSL, text);
482  }
483  secureSocketFinished = true;
484  finalResult();
485 }
486 
487 void ServerTestPrivate::slotNormalNotPossible()
488 {
489  if (testProtocol == SMTP_PROTOCOL && normalSocket->port() == SMTP_PORT) {
490  // For SMTP, fallback to port 25
491  normalSocket->setPort(SMTP_OLD_PORT);
492  normalSocket->reconnect();
493  normalSocketTimer->start(10000);
494  return;
495  }
496 
497  normalSocketTimer->stop();
498  normalPossible = false;
499  normalSocketFinished = true;
500  tlsFinished = true;
501  finalResult();
502 }
503 
504 void ServerTestPrivate::slotSslPossible()
505 {
506  secureSocketTimer->stop();
507  connectionResults << Transport::EnumEncryption::SSL;
508 }
509 
510 void ServerTestPrivate::slotSslNotPossible()
511 {
512  secureSocketTimer->stop();
513  securePossible = false;
514  secureSocketFinished = true;
515  finalResult();
516 }
517 
518 void ServerTestPrivate::slotUpdateProgress()
519 {
520  if (testProgress) {
521  testProgress->setValue(testProgress->value() + 1);
522  }
523 }
524 
525 //---------------------- end private class -----------------------//
526 
528  : QObject(parent)
529  , d(new ServerTestPrivate(this))
530 {
531  d->normalSocketTimer = new QTimer(this);
532  d->normalSocketTimer->setSingleShot(true);
533  connect(d->normalSocketTimer, SIGNAL(timeout()), SLOT(slotNormalNotPossible()));
534 
535  d->secureSocketTimer = new QTimer(this);
536  d->secureSocketTimer->setSingleShot(true);
537  connect(d->secureSocketTimer, SIGNAL(timeout()), SLOT(slotSslNotPossible()));
538 
539  d->progressTimer = new QTimer(this);
540  connect(d->progressTimer, SIGNAL(timeout()), SLOT(slotUpdateProgress()));
541 }
542 
543 ServerTest::~ServerTest() = default;
544 
546 {
547  qCDebug(MAILTRANSPORT_LOG) << d.get();
548 
549  d->connectionResults.clear();
550  d->authenticationResults.clear();
551  d->capabilityResults.clear();
552  d->popSupportsTLS = false;
553  d->normalStage = -1;
554  d->secureStage = -1;
555  d->encryptionMode = Transport::EnumEncryption::None;
556  d->normalPossible = true;
557  d->securePossible = true;
558 
559  if (d->testProgress) {
560  d->testProgress->setMaximum(20);
561  d->testProgress->setValue(0);
562  d->testProgress->setTextVisible(true);
563  d->testProgress->show();
564  d->progressTimer->start(1000);
565  }
566 
567  d->normalSocket = new MailTransport::Socket(this);
568  d->secureSocket = new MailTransport::Socket(this);
569  d->normalSocket->setObjectName(QStringLiteral("normal"));
570  d->normalSocket->setServer(d->server);
571  d->normalSocket->setProtocol(d->testProtocol);
572  if (d->testProtocol == IMAP_PROTOCOL) {
573  d->normalSocket->setPort(IMAP_PORT);
574  d->secureSocket->setPort(IMAPS_PORT);
575  } else if (d->testProtocol == SMTP_PROTOCOL) {
576  d->normalSocket->setPort(SMTP_PORT);
577  d->secureSocket->setPort(SMTPS_PORT);
578  } else if (d->testProtocol == POP_PROTOCOL) {
579  d->normalSocket->setPort(POP_PORT);
580  d->secureSocket->setPort(POPS_PORT);
581  } else if (d->testProtocol == NNTP_PROTOCOL) {
582  d->normalSocket->setPort(NNTP_PORT);
583  d->secureSocket->setPort(NNTPS_PORT);
584  }
585 
586  if (d->customPorts.contains(Transport::EnumEncryption::None)) {
587  d->normalSocket->setPort(d->customPorts.value(Transport::EnumEncryption::None));
588  }
589  if (d->customPorts.contains(Transport::EnumEncryption::SSL)) {
590  d->secureSocket->setPort(d->customPorts.value(Transport::EnumEncryption::SSL));
591  }
592 
593  connect(d->normalSocket, SIGNAL(connected()), SLOT(slotNormalPossible()));
594  connect(d->normalSocket, SIGNAL(failed()), SLOT(slotNormalNotPossible()));
595  connect(d->normalSocket, SIGNAL(data(QString)), SLOT(slotReadNormal(QString)));
596  connect(d->normalSocket, SIGNAL(tlsDone()), SLOT(slotTlsDone()));
597  d->normalSocket->reconnect();
598  d->normalSocketTimer->start(10000);
599 
600  if (d->secureSocket->port() > 0) {
601  d->secureSocket->setObjectName(QStringLiteral("secure"));
602  d->secureSocket->setServer(d->server);
603  d->secureSocket->setProtocol(d->testProtocol + QLatin1Char('s'));
604  d->secureSocket->setSecure(true);
605  connect(d->secureSocket, SIGNAL(connected()), SLOT(slotSslPossible()));
606  connect(d->secureSocket, SIGNAL(failed()), SLOT(slotSslNotPossible()));
607  connect(d->secureSocket, SIGNAL(data(QString)), SLOT(slotReadSecure(QString)));
608  d->secureSocket->reconnect();
609  d->secureSocketTimer->start(10000);
610  } else {
611  d->slotSslNotPossible();
612  }
613 }
614 
615 void ServerTest::setFakeHostname(const QString &fakeHostname)
616 {
617  d->fakeHostname = fakeHostname;
618 }
619 
621 {
622  return d->fakeHostname;
623 }
624 
625 void ServerTest::setServer(const QString &server)
626 {
627  d->server = server;
628 }
629 
630 void ServerTest::setPort(Transport::EnumEncryption::type encryptionMode, uint port)
631 {
632  Q_ASSERT(encryptionMode == Transport::EnumEncryption::None || encryptionMode == Transport::EnumEncryption::SSL);
633  d->customPorts.insert(encryptionMode, port);
634 }
635 
637 {
638  d->testProgress = pb;
639 }
640 
641 void ServerTest::setProtocol(const QString &protocol)
642 {
643  d->testProtocol = protocol;
644  d->customPorts.clear();
645 }
646 
647 QString ServerTest::protocol() const
648 {
649  return d->testProtocol;
650 }
651 
652 QString ServerTest::server() const
653 {
654  return d->server;
655 }
656 
657 int ServerTest::port(TransportBase::EnumEncryption::type encryptionMode) const
658 {
659  Q_ASSERT(encryptionMode == Transport::EnumEncryption::None || encryptionMode == Transport::EnumEncryption::SSL);
660  if (d->customPorts.contains(encryptionMode)) {
661  return d->customPorts.value(static_cast<int>(encryptionMode));
662  } else {
663  return -1;
664  }
665 }
666 
667 QProgressBar *ServerTest::progressBar() const
668 {
669  return d->testProgress;
670 }
671 
673 {
674  return d->authenticationResults[TransportBase::EnumEncryption::None];
675 }
676 
678 {
679  return d->normalPossible;
680 }
681 
683 {
684  return d->authenticationResults[TransportBase::EnumEncryption::TLS];
685 }
686 
688 {
689  return d->authenticationResults[Transport::EnumEncryption::SSL];
690 }
691 
693 {
694  return d->securePossible;
695 }
696 
698 {
699  return d->capabilityResults.values();
700 }
701 
702 #include "moc_servertest.cpp"
void append(const T &value)
bool endsWith(const QString &s, Qt::CaseSensitivity cs) const const
bool isNull() const const
QString fakeHostname() const
Definition: servertest.cpp:620
void setFakeHostname(const QString &fakeHostname)
Sets a fake hostname for the test.
Definition: servertest.cpp:615
QString toUpper() const const
void finished(const QVector< int > &)
This will be emitted when the test is done.
int size() const const
CaseInsensitive
bool isNormalPossible() const
tells you if the normal server is available
Definition: servertest.cpp:677
Type type(const QSqlDatabase &db)
QStringList split(const QString &sep, QString::SplitBehavior behavior, Qt::CaseSensitivity cs) const const
int count(const T &value) const const
void ref()
void append(const T &value)
QString chopped(int len) const const
void chop(int n)
@ UIDL
POP3 only. The server has support for unique identifiers.
Definition: servertest.h:45
virtual void write(const QString &text)
Write text to the socket.
Definition: socket.cpp:155
virtual void reconnect()
Existing connection will be closed and a new connection will be made.
Definition: socket.cpp:129
int size() const const
QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
void hide()
void setPort(Transport::EnumEncryption::type encryptionMode, uint port)
Set a custom port to use.
Definition: servertest.cpp:630
void setProgressBar(QProgressBar *pb)
Makes pb the progressbar to use.
Definition: servertest.cpp:636
KGuiItem test()
void start(int msec)
int port(Transport::EnumEncryption::type encryptionMode) const
Definition: servertest.cpp:657
QVector< int > tlsProtocols() const
Get the protocols for the TLS connections.
Definition: servertest.cpp:682
NETWORKMANAGERQT_EXPORT QString hostname()
@ Top
POP3 only. The server supports fetching only the headers.
Definition: servertest.h:44
SkipEmptyParts
void setServer(const QString &server)
Sets the server to test.
Definition: servertest.cpp:625
QList< T > mid(int pos, int length) const const
bool isEmpty() const const
bool isSecurePossible() const
tells you if the ssl server is available
Definition: servertest.cpp:692
void setProtocol(const QString &protocol)
Sets protocol the protocol to test, currently supported are "smtp", "pop", "imap",...
Definition: servertest.cpp:641
QVector< QStringRef > splitRef(const QString &sep, QString::SplitBehavior behavior, Qt::CaseSensitivity cs) const const
const T & at(int i) const const
bool contains(const T &value) const const
int port() const
returns the used port.
Definition: socket.cpp:202
QList< Capability > capabilities() const
Get the special capabilities of the server.
Definition: servertest.cpp:697
int indexOf(QChar ch, int from, Qt::CaseSensitivity cs) const const
void setPort(int port)
set the port to use.
Definition: socket.cpp:197
ServerTest(QObject *parent=nullptr)
Creates a new server test.
Definition: servertest.cpp:527
~ServerTest() override
Destroys the server test.
void reserve(int size)
QString & replace(int position, int n, QChar after)
void startTLS()
If you want to start TLS encryption, call this.
Definition: socket.cpp:180
int removeAll(const T &t)
bool startsWith(const QString &s, Qt::CaseSensitivity cs) const const
typedef ConstIterator
QVector< int > normalProtocols() const
Get the protocols for the normal connections.
Definition: servertest.cpp:672
QString localHostName()
QString right(int n) const const
void stop()
QList::iterator begin()
bool contains(QChar ch, Qt::CaseSensitivity cs) const const
void setValue(int value)
QList::iterator end()
@ Pipelining
POP3 only. The server supports pipeplining of commands.
Definition: servertest.h:43
QVector< int > secureProtocols() const
Get the protocols for the SSL connections.
Definition: servertest.cpp:687
void start()
Starts the test.
Definition: servertest.cpp:545
QChar fromLatin1(char c)
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Tue Feb 7 2023 03:58:25 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.