File indexing completed on 2024-05-12 05:17:18
0001 /** 0002 * This file is part of the KDE project 0003 * SPDX-FileCopyrightText: 2009 Kevin Ottens <ervin@kde.org> 0004 * SPDX-FileCopyrightText: 2009 Andras Mantia <amantia@kde.org> 0005 * 0006 * SPDX-License-Identifier: LGPL-2.0-or-later 0007 */ 0008 0009 #include <QCoreApplication> 0010 #include <QDebug> 0011 0012 #include "acl.h" 0013 #include "appendjob.h" 0014 #include "capabilitiesjob.h" 0015 #include "closejob.h" 0016 #include "createjob.h" 0017 #include "deleteacljob.h" 0018 #include "deletejob.h" 0019 #include "expungejob.h" 0020 #include "fetchjob.h" 0021 #include "getacljob.h" 0022 #include "getmetadatajob.h" 0023 #include "listjob.h" 0024 #include "listrightsjob.h" 0025 #include "loginjob.h" 0026 #include "logoutjob.h" 0027 #include "myrightsjob.h" 0028 #include "namespacejob.h" 0029 #include "renamejob.h" 0030 #include "selectjob.h" 0031 #include "session.h" 0032 #include "sessionuiproxy.h" 0033 #include "setacljob.h" 0034 #include "setmetadatajob.h" 0035 #include "storejob.h" 0036 #include "subscribejob.h" 0037 #include "unsubscribejob.h" 0038 0039 using namespace KIMAP; 0040 0041 using PartsReceivedSignal = void (FetchJob::*)(const QString &, const QMap<qint64, qint64> &, const QMap<qint64, MessageParts> &); 0042 0043 using HeadersReceivedSignal = void (FetchJob::*)(const QString &, 0044 const QMap<qint64, qint64> &, 0045 const QMap<qint64, qint64> &, 0046 const QMap<qint64, MessageFlags> &, 0047 const QMap<qint64, MessagePtr> &); 0048 0049 class UiProxy : public SessionUiProxy 0050 { 0051 public: 0052 bool ignoreSslError(const KSslErrorUiData &errorData) override 0053 { 0054 Q_UNUSED(errorData) 0055 return true; 0056 } 0057 }; 0058 0059 void dumpContentHelper(KMime::Content *part, const QString &partId = QString()) 0060 { 0061 if (partId.isEmpty()) { 0062 qDebug() << "** Message root **"; 0063 } else { 0064 qDebug() << "** Part" << partId << "**"; 0065 } 0066 0067 qDebug() << part->head(); 0068 0069 KMime::Content::List children = part->contents(); 0070 for (int i = 0; i < children.size(); i++) { 0071 QString newId = partId; 0072 if (!newId.isEmpty()) { 0073 newId += QLatin1StringView("."); 0074 } 0075 newId += QString::number(i + 1); 0076 dumpContentHelper(children[i], newId); 0077 } 0078 } 0079 0080 void listFolders(Session *session, bool includeUnsubscribed = false, const QString &nameFilter = QLatin1StringView("")) 0081 { 0082 auto list = new ListJob(session); 0083 list->setOption(includeUnsubscribed ? KIMAP::ListJob::IncludeUnsubscribed : KIMAP::ListJob::NoOption); 0084 list->exec(); 0085 Q_ASSERT_X(list->error() == 0, "ListJob", list->errorString().toLocal8Bit().constData()); 0086 int count = list->mailBoxes().size(); 0087 for (int i = 0; i < count; ++i) { 0088 MailBoxDescriptor descriptor = list->mailBoxes()[i]; 0089 if (descriptor.name.endsWith(nameFilter)) { 0090 qDebug() << descriptor.separator << descriptor.name; 0091 } 0092 } 0093 } 0094 0095 void testMetaData(Session *session) 0096 { 0097 qDebug() << "TESTING: METADATA commands"; 0098 auto create = new CreateJob(session); 0099 create->setMailBox(QStringLiteral("INBOX/TestFolder")); 0100 create->exec(); 0101 0102 auto setmetadata = new SetMetaDataJob(session); 0103 setmetadata->setMailBox(QStringLiteral("INBOX/TestFolder")); 0104 setmetadata->setServerCapability(SetMetaDataJob::Annotatemore); 0105 setmetadata->setEntry("/comment"); 0106 setmetadata->addMetaData("value.priv", "My new comment"); 0107 setmetadata->exec(); 0108 0109 setmetadata = new SetMetaDataJob(session); 0110 setmetadata->setMailBox(QStringLiteral("INBOX/TestFolder")); 0111 setmetadata->setServerCapability(SetMetaDataJob::Annotatemore); 0112 setmetadata->setEntry("/check"); 0113 setmetadata->addMetaData("value.priv", "true"); 0114 setmetadata->exec(); 0115 0116 auto getmetadata = new GetMetaDataJob(session); 0117 getmetadata->setMailBox(QStringLiteral("INBOX/TestFolder")); 0118 getmetadata->setServerCapability(SetMetaDataJob::Annotatemore); 0119 getmetadata->addEntry("/*", "value.priv"); 0120 getmetadata->exec(); 0121 Q_ASSERT_X(getmetadata->metaData(QLatin1StringView("INBOX/TestFolder"), "/check", "value.priv") == "true", "", "/check metadata should be true"); 0122 Q_ASSERT_X(getmetadata->metaData(QLatin1StringView("INBOX/TestFolder"), "/comment", "value.priv") == "My new comment", 0123 "", 0124 "/check metadata should be My new comment"); 0125 0126 // cleanup 0127 auto deletejob = new DeleteJob(session); 0128 deletejob->setMailBox(QLatin1StringView("INBOX/TestFolder")); 0129 deletejob->exec(); 0130 } 0131 0132 void testAcl(Session *session, const QString &user) 0133 { 0134 qDebug() << "TESTING: ACL commands"; 0135 auto create = new CreateJob(session); 0136 create->setMailBox(QStringLiteral("INBOX/TestFolder")); 0137 create->exec(); 0138 0139 auto listRights = new ListRightsJob(session); 0140 listRights->setMailBox(QStringLiteral("INBOX/TestFolder")); 0141 listRights->setIdentifier(user.toLatin1()); 0142 listRights->exec(); 0143 qDebug() << "Default rights on INBOX/TestFolder: " << Acl::rightsToString(listRights->defaultRights()); 0144 const QList<Acl::Rights> possible = listRights->possibleRights(); 0145 QStringList strList; 0146 for (Acl::Rights r : std::as_const(possible)) { 0147 strList << QString::fromLatin1(Acl::rightsToString(r)); 0148 } 0149 qDebug() << "Possible rights on INBOX/TestFolder: " << strList; 0150 0151 auto myRights = new MyRightsJob(session); 0152 myRights->setMailBox(QStringLiteral("INBOX/TestFolder")); 0153 myRights->exec(); 0154 0155 Acl::Rights mine = myRights->rights(); 0156 qDebug() << "My rights on INBOX/TestFolder: " << Acl::rightsToString(mine); 0157 qDebug() << "Reading INBOX/TestFolder is possible: " << myRights->hasRightEnabled(Acl::Read); 0158 Q_ASSERT_X(myRights->hasRightEnabled(Acl::Read), "Reading INBOX is NOT possible", ""); 0159 0160 auto getAcl = new GetAclJob(session); 0161 getAcl->setMailBox(QStringLiteral("INBOX/TestFolder")); 0162 getAcl->exec(); 0163 qDebug() << "Anyone rights on INBOX/TestFolder: " << getAcl->rights("anyone"); 0164 Acl::Rights users = getAcl->rights(user.toLatin1()); 0165 qDebug() << user << " rights on INBOX/TestFolder: " << Acl::rightsToString(users); 0166 Q_ASSERT_X(mine == users, "GETACL returns different rights for the same user", ""); 0167 0168 qDebug() << "Removing Delete right "; 0169 mine = Acl::Delete; 0170 auto setAcl = new SetAclJob(session); 0171 setAcl->setMailBox(QStringLiteral("INBOX/TestFolder")); 0172 setAcl->setIdentifier(user.toLatin1()); 0173 setAcl->setRights(AclJobBase::Remove, mine); 0174 setAcl->exec(); 0175 0176 getAcl = new GetAclJob(session); 0177 getAcl->setMailBox(QStringLiteral("INBOX/TestFolder")); 0178 getAcl->exec(); 0179 users = getAcl->rights(user.toLatin1()); 0180 qDebug() << user << " rights on INBOX/TestFolder: " << Acl::rightsToString(users); 0181 0182 qDebug() << "Adding back Delete right "; 0183 mine = Acl::Delete; 0184 setAcl = new SetAclJob(session); 0185 setAcl->setMailBox(QStringLiteral("INBOX/TestFolder")); 0186 setAcl->setIdentifier(user.toLatin1()); 0187 setAcl->setRights(AclJobBase::Add, mine); 0188 setAcl->exec(); 0189 0190 getAcl = new GetAclJob(session); 0191 getAcl->setMailBox(QStringLiteral("INBOX/TestFolder")); 0192 getAcl->exec(); 0193 users = getAcl->rights(user.toLatin1()); 0194 qDebug() << user << " rights on INBOX/TestFolder: " << Acl::rightsToString(users); 0195 0196 // cleanup 0197 auto deletejob = new DeleteJob(session); 0198 deletejob->setMailBox(QStringLiteral("INBOX/TestFolder")); 0199 deletejob->exec(); 0200 } 0201 0202 void testAppendAndStore(Session *session) 0203 { 0204 qDebug() << "TESTING: APPEND and STORE"; 0205 // setup 0206 auto create = new CreateJob(session); 0207 create->setMailBox(QStringLiteral("INBOX/TestFolder")); 0208 create->exec(); 0209 0210 QByteArray testMailContent = 0211 "Date: Mon, 7 Feb 1994 21:52:25 -0800 (PST)\r\n" 0212 "From: Fred Foobar <foobar@Blurdybloop.COM>\r\n" 0213 "Subject: afternoon meeting\r\n" 0214 "To: mooch@owatagu.siam.edu\r\n" 0215 "Message-Id: <B27397-0100000@Blurdybloop.COM>\r\n" 0216 "MIME-Version: 1.0\r\n" 0217 "Content-Type: TEXT/PLAIN; CHARSET=US-ASCII\r\n" 0218 "\r\n" 0219 "Hello Joe, do you think we can meet at 3:30 tomorrow?\r\n"; 0220 0221 qDebug() << "Append a message in INBOX/TestFolder..."; 0222 auto append = new AppendJob(session); 0223 append->setMailBox(QStringLiteral("INBOX/TestFolder")); 0224 append->setContent(testMailContent); 0225 append->exec(); 0226 Q_ASSERT_X(append->error() == 0, "AppendJob", append->errorString().toLocal8Bit().constData()); 0227 0228 qDebug() << "Read the message back and compare..."; 0229 auto select = new SelectJob(session); 0230 select->setMailBox(QStringLiteral("INBOX/TestFolder")); 0231 select->exec(); 0232 0233 auto fetch = new FetchJob(session); 0234 FetchJob::FetchScope scope; 0235 fetch->setSequenceSet(ImapSet(1)); 0236 scope.parts.clear(); 0237 scope.mode = FetchJob::FetchScope::Content; 0238 fetch->setScope(scope); 0239 MessagePtr message; 0240 QObject::connect(fetch, 0241 static_cast<HeadersReceivedSignal>(&FetchJob::headersReceived), 0242 fetch, 0243 [&](const QString &, 0244 const QMap<qint64, qint64> &, 0245 const QMap<qint64, qint64> &, 0246 const QMap<qint64, MessageFlags> &, 0247 const QMap<qint64, MessagePtr> &msgs) { 0248 message = msgs[1]; 0249 }); 0250 fetch->exec(); 0251 Q_ASSERT_X(fetch->error() == 0, "FetchJob", fetch->errorString().toLocal8Bit().constData()); 0252 testMailContent.replace("\r\n", "\n"); 0253 Q_ASSERT_X(testMailContent == message->head() + "\n" + message->body(), 0254 "Message differs from reference", 0255 QByteArray(message->head() + "\n" + message->body()).constData()); 0256 0257 fetch = new FetchJob(session); 0258 fetch->setSequenceSet(ImapSet(1)); 0259 scope.parts.clear(); 0260 scope.mode = FetchJob::FetchScope::Flags; 0261 fetch->setScope(scope); 0262 MessageFlags expectedFlags; 0263 QObject::connect(fetch, 0264 static_cast<HeadersReceivedSignal>(&FetchJob::headersReceived), 0265 fetch, 0266 [&](const QString &, 0267 const QMap<qint64, qint64> &, 0268 const QMap<qint64, qint64> &, 0269 const QMap<qint64, MessageFlags> &flags, 0270 const QMap<qint64, MessagePtr> &) { 0271 expectedFlags = flags[1]; 0272 }); 0273 fetch->exec(); 0274 qDebug() << "Read the message flags:" << expectedFlags; 0275 0276 qDebug() << "Add the \\Deleted flag..."; 0277 expectedFlags << "\\Deleted"; 0278 std::sort(expectedFlags.begin(), expectedFlags.end()); 0279 auto store = new StoreJob(session); 0280 store->setSequenceSet(ImapSet(1)); 0281 store->setMode(StoreJob::AppendFlags); 0282 store->setFlags(QList<QByteArray>() << "\\Deleted"); 0283 store->exec(); 0284 Q_ASSERT_X(store->error() == 0, "StoreJob", store->errorString().toLocal8Bit().constData()); 0285 0286 QList<QByteArray> resultingFlags = store->resultingFlags()[1]; 0287 std::sort(resultingFlags.begin(), resultingFlags.end()); 0288 if (expectedFlags != resultingFlags) { 0289 qDebug() << resultingFlags; 0290 } 0291 Q_ASSERT(expectedFlags == resultingFlags); 0292 0293 select = new SelectJob(session); 0294 select->setMailBox(QStringLiteral("INBOX")); 0295 select->exec(); 0296 0297 // cleanup 0298 auto deletejob = new DeleteJob(session); 0299 deletejob->setMailBox(QStringLiteral("INBOX/TestFolder")); 0300 deletejob->exec(); 0301 deletejob = new DeleteJob(session); 0302 deletejob->setMailBox(QStringLiteral("INBOX/RenamedTestFolder")); 0303 deletejob->exec(); 0304 } 0305 0306 void testRename(Session *session) 0307 { 0308 qDebug() << "TESTING: RENAME"; 0309 // setup 0310 auto create = new CreateJob(session); 0311 create->setMailBox(QStringLiteral("INBOX/TestFolder")); 0312 create->exec(); 0313 0314 qDebug() << "Listing mailboxes with name TestFolder:"; 0315 listFolders(session, true, QStringLiteral("TestFolder")); 0316 0317 // actual tests 0318 qDebug() << "Renaming to RenamedTestFolder"; 0319 auto rename = new RenameJob(session); 0320 rename->setSourceMailBox(QStringLiteral("INBOX/TestFolder")); 0321 rename->setDestinationMailBox(QStringLiteral("INBOX/RenamedTestFolder")); 0322 rename->exec(); 0323 0324 qDebug() << "Listing mailboxes with name TestFolder:"; 0325 listFolders(session, true, QStringLiteral("TestFolder")); 0326 qDebug() << "Listing mailboxes with name RenamedTestFolder:"; 0327 listFolders(session, true, QStringLiteral("RenamedTestFolder")); 0328 0329 // cleanup 0330 auto deletejob = new DeleteJob(session); 0331 deletejob->setMailBox(QStringLiteral("INBOX/TestFolder")); 0332 deletejob->exec(); 0333 deletejob = new DeleteJob(session); 0334 deletejob->setMailBox(QStringLiteral("INBOX/RenamedTestFolder")); 0335 deletejob->exec(); 0336 } 0337 0338 void testSubscribe(Session *session) 0339 { 0340 qDebug() << "TESTING: SUBSCRIBE/UNSUBSCRIBE"; 0341 // setup 0342 auto create = new CreateJob(session); 0343 create->setMailBox(QStringLiteral("INBOX/TestFolder")); 0344 create->exec(); 0345 0346 qDebug() << "Listing subscribed mailboxes with name TestFolder:"; 0347 listFolders(session, false, QStringLiteral("TestFolder")); 0348 0349 // actual tests 0350 qDebug() << "Subscribing to INBOX/TestFolder"; 0351 auto subscribe = new SubscribeJob(session); 0352 subscribe->setMailBox(QStringLiteral("INBOX/TestFolder")); 0353 subscribe->exec(); 0354 0355 qDebug() << "Listing subscribed mailboxes with name TestFolder:"; 0356 listFolders(session, false, QStringLiteral("TestFolder")); 0357 0358 qDebug() << "Unsubscribing from INBOX/TestFolder"; 0359 auto unsubscribe = new UnsubscribeJob(session); 0360 unsubscribe->setMailBox(QStringLiteral("INBOX/TestFolder")); 0361 unsubscribe->exec(); 0362 0363 qDebug() << "Listing subscribed mailboxes with name TestFolder:"; 0364 listFolders(session, false, QStringLiteral("TestFolder")); 0365 0366 // cleanup 0367 auto deletejob = new DeleteJob(session); 0368 deletejob->setMailBox(QStringLiteral("INBOX/TestFolder")); 0369 deletejob->exec(); 0370 } 0371 0372 void testDelete(Session *session) 0373 { 0374 qDebug() << "TESTING: DELETE"; 0375 qDebug() << "Creating INBOX/TestFolder:"; 0376 auto create = new CreateJob(session); 0377 create->setMailBox(QStringLiteral("INBOX/TestFolder")); 0378 create->exec(); 0379 0380 qDebug() << "Listing with name TestFolder before DELETE:"; 0381 listFolders(session, true, QStringLiteral("TestFolder")); 0382 0383 qDebug() << "Deleting INBOX/TestFolder"; 0384 auto deletejob = new DeleteJob(session); 0385 deletejob->setMailBox(QStringLiteral("INBOX/TestFolder")); 0386 deletejob->exec(); 0387 0388 qDebug() << "Listing with name TestFolder after DELETE:"; 0389 listFolders(session, true, QStringLiteral("TestFolder")); 0390 } 0391 0392 int main(int argc, char **argv) 0393 { 0394 QCoreApplication::setApplicationName(QStringLiteral("TestImapServer")); 0395 0396 if (argc < 4) { 0397 qCritical() << "Not enough parameters, expecting: <server> <user> <password>"; 0398 } 0399 0400 QString server = QString::fromLocal8Bit(argv[1]); 0401 int port = 143; 0402 if (server.count(QLatin1Char(':')) == 1) { 0403 const QStringList lstSplit = server.split(QLatin1Char(':')); 0404 port = lstSplit.last().toInt(); 0405 server = lstSplit.first(); 0406 } 0407 QString user = QString::fromLocal8Bit(argv[2]); 0408 QString password = QString::fromLocal8Bit(argv[3]); 0409 0410 qDebug() << "Querying:" << server << port << user << password; 0411 qDebug(); 0412 0413 QCoreApplication app(argc, argv); 0414 Session session(server, port); 0415 UiProxy::Ptr proxy(new UiProxy()); 0416 session.setUiProxy(proxy); 0417 0418 qDebug() << "Logging in..."; 0419 auto login = new LoginJob(&session); 0420 // login->setEncryptionMode( LoginJob::TlsV1 ); 0421 // login->setAuthenticationMode( LoginJob::Plain ); 0422 login->setUserName(user); 0423 login->setPassword(password); 0424 login->exec(); 0425 qDebug(); 0426 0427 /*if (login->encryptionMode() == LoginJob::Unencrypted) 0428 { 0429 qDebug() << "Encrypted login not possible, try to log in without encryption"; 0430 login = new LoginJob( &session ); 0431 login->setUserName( user ); 0432 login->setPassword( password ); 0433 login->exec(); 0434 Q_ASSERT_X( login->error() == 0, "LoginJob", login->errorString().toLocal8Bit().constData() ); 0435 Q_ASSERT( session.state() == Session::Authenticated ); 0436 qDebug(); 0437 0438 }*/ 0439 0440 qDebug() << "Server greeting:" << session.serverGreeting(); 0441 0442 qDebug() << "Asking for capabilities:"; 0443 auto capabilities = new CapabilitiesJob(&session); 0444 capabilities->exec(); 0445 Q_ASSERT_X(capabilities->error() == 0, "CapabilitiesJob", capabilities->errorString().toLocal8Bit().constData()); 0446 Q_ASSERT(session.state() == Session::Authenticated); 0447 qDebug() << capabilities->capabilities(); 0448 qDebug(); 0449 0450 qDebug() << "Asking for namespaces:"; 0451 auto namespaces = new NamespaceJob(&session); 0452 namespaces->exec(); 0453 Q_ASSERT_X(namespaces->error() == 0, "CapabilitiesJob", namespaces->errorString().toLocal8Bit().constData()); 0454 Q_ASSERT(session.state() == Session::Authenticated); 0455 0456 qDebug() << "Contains empty namespace:" << namespaces->containsEmptyNamespace(); 0457 0458 qDebug() << "Personal:"; 0459 const auto personalNamespaces = namespaces->personalNamespaces(); 0460 for (MailBoxDescriptor ns : personalNamespaces) { 0461 qDebug() << ns.separator << ns.name; 0462 } 0463 0464 qDebug() << "User: "; 0465 const auto userNamespaces = namespaces->userNamespaces(); 0466 for (MailBoxDescriptor ns : userNamespaces) { 0467 qDebug() << ns.separator << ns.name; 0468 } 0469 0470 qDebug() << "Shared: "; 0471 const auto sharedNamespaces = namespaces->sharedNamespaces(); 0472 for (MailBoxDescriptor ns : sharedNamespaces) { 0473 qDebug() << ns.separator << ns.name; 0474 } 0475 qDebug(); 0476 0477 qDebug() << "Listing mailboxes:"; 0478 listFolders(&session); 0479 Q_ASSERT(session.state() == Session::Authenticated); 0480 0481 qDebug() << "Selecting INBOX:"; 0482 auto select = new SelectJob(&session); 0483 select->setMailBox(QStringLiteral("INBOX")); 0484 select->exec(); 0485 Q_ASSERT_X(select->error() == 0, "SelectJob", select->errorString().toLocal8Bit().constData()); 0486 Q_ASSERT(session.state() == Session::Selected); 0487 qDebug() << "Flags:" << select->flags(); 0488 qDebug() << "Permanent flags:" << select->permanentFlags(); 0489 qDebug() << "Total Number of Messages:" << select->messageCount(); 0490 qDebug() << "Number of recent Messages:" << select->recentCount(); 0491 qDebug() << "First Unseen Message Index:" << select->firstUnseenIndex(); 0492 qDebug() << "UID validity:" << select->uidValidity(); 0493 qDebug() << "Next UID:" << select->nextUid(); 0494 qDebug(); 0495 0496 qDebug() << "Fetching first 3 messages headers:"; 0497 auto fetch = new FetchJob(&session); 0498 FetchJob::FetchScope scope; 0499 fetch->setSequenceSet(ImapSet(1, 3)); 0500 scope.parts.clear(); 0501 scope.mode = FetchJob::FetchScope::Headers; 0502 fetch->setScope(scope); 0503 QMap<qint64, qint64> sizes; 0504 QMap<qint64, MessagePtr> messages; 0505 0506 QObject::connect(fetch, 0507 static_cast<HeadersReceivedSignal>(&FetchJob::headersReceived), 0508 fetch, 0509 [&](const QString &, 0510 const QMap<qint64, qint64> &, 0511 const QMap<qint64, qint64> &sizes_, 0512 const QMap<qint64, MessageFlags> &, 0513 const QMap<qint64, MessagePtr> &msgs_) { 0514 sizes = sizes_; 0515 messages = msgs_; 0516 }); 0517 fetch->exec(); 0518 Q_ASSERT_X(fetch->error() == 0, "FetchJob", fetch->errorString().toLocal8Bit().constData()); 0519 Q_ASSERT(session.state() == Session::Selected); 0520 const auto messagesKey = messages.keys(); 0521 for (qint64 id : messagesKey) { 0522 qDebug() << "* Message" << id << "(" << sizes[id] << "bytes )"; 0523 qDebug() << " From :" << messages[id]->from()->asUnicodeString(); 0524 qDebug() << " To :" << messages[id]->to()->asUnicodeString(); 0525 qDebug() << " Date :" << messages[id]->date()->asUnicodeString(); 0526 qDebug() << " Subject :" << messages[id]->subject()->asUnicodeString(); 0527 qDebug() << " Message-ID:" << messages[id]->messageID()->asUnicodeString(); 0528 } 0529 qDebug(); 0530 0531 qDebug() << "Fetching first 3 messages flags:"; 0532 fetch = new FetchJob(&session); 0533 fetch->setSequenceSet(ImapSet(1, 3)); 0534 scope.parts.clear(); 0535 scope.mode = FetchJob::FetchScope::Flags; 0536 fetch->setScope(scope); 0537 QMap<qint64, MessageFlags> flags; 0538 QObject::connect(fetch, 0539 static_cast<HeadersReceivedSignal>(&FetchJob::headersReceived), 0540 fetch, 0541 [&](const QString &, 0542 const QMap<qint64, qint64> &, 0543 const QMap<qint64, qint64> &, 0544 const QMap<qint64, MessageFlags> &flags_, 0545 const QMap<qint64, MessagePtr> &) { 0546 flags = flags_; 0547 }); 0548 fetch->exec(); 0549 Q_ASSERT_X(fetch->error() == 0, "FetchJob", fetch->errorString().toLocal8Bit().constData()); 0550 Q_ASSERT(session.state() == Session::Selected); 0551 const auto flagsKey = flags.keys(); 0552 for (qint64 id : flagsKey) { 0553 qDebug() << "* Message" << id << "flags:" << flags[id]; 0554 } 0555 qDebug(); 0556 0557 qDebug() << "Fetching first message structure:"; 0558 fetch = new FetchJob(&session); 0559 fetch->setSequenceSet(ImapSet(1)); 0560 scope.parts.clear(); 0561 scope.mode = FetchJob::FetchScope::Structure; 0562 fetch->setScope(scope); 0563 QObject::connect(fetch, 0564 static_cast<HeadersReceivedSignal>(&FetchJob::headersReceived), 0565 fetch, 0566 [&](const QString &, 0567 const QMap<qint64, qint64> &, 0568 const QMap<qint64, qint64> &, 0569 const QMap<qint64, MessageFlags> &, 0570 const QMap<qint64, MessagePtr> &msgs_) { 0571 messages = msgs_; 0572 }); 0573 fetch->exec(); 0574 Q_ASSERT_X(fetch->error() == 0, "FetchJob", fetch->errorString().toLocal8Bit().constData()); 0575 Q_ASSERT(session.state() == Session::Selected); 0576 MessagePtr message = messages[1]; 0577 dumpContentHelper(message.data()); 0578 qDebug(); 0579 0580 qDebug() << "Fetching first message second part headers:"; 0581 fetch = new FetchJob(&session); 0582 fetch->setSequenceSet(ImapSet(1)); 0583 scope.parts.clear(); 0584 scope.parts << "2"; 0585 scope.mode = FetchJob::FetchScope::Headers; 0586 fetch->setScope(scope); 0587 QMap<qint64, MessageParts> allParts; 0588 QObject::connect(fetch, 0589 static_cast<PartsReceivedSignal>(&FetchJob::partsReceived), 0590 fetch, 0591 [&](const QString &, const QMap<qint64, qint64> &, const QMap<qint64, MessageParts> &parts_) { 0592 allParts = parts_; 0593 }); 0594 fetch->exec(); 0595 Q_ASSERT_X(fetch->error() == 0, "FetchJob", fetch->errorString().toLocal8Bit().constData()); 0596 Q_ASSERT(session.state() == Session::Selected); 0597 const auto allkeys = allParts.keys(); 0598 for (qint64 id : allkeys) { 0599 qDebug() << "* Message" << id << "parts headers"; 0600 MessageParts parts = allParts[id]; 0601 const auto parsKeys = parts.keys(); 0602 for (const QByteArray &partId : parsKeys) { 0603 qDebug() << " ** Part" << partId; 0604 qDebug() << " Name :" << parts[partId]->contentType()->name(); 0605 qDebug() << " Mimetype :" << parts[partId]->contentType()->mimeType(); 0606 qDebug() << " Description:" << parts[partId]->contentDescription()->asUnicodeString().simplified(); 0607 } 0608 } 0609 qDebug(); 0610 0611 qDebug() << "Fetching first message second part content:"; 0612 fetch = new FetchJob(&session); 0613 fetch->setSequenceSet(ImapSet(1)); 0614 scope.parts.clear(); 0615 scope.parts << "2"; 0616 scope.mode = FetchJob::FetchScope::Content; 0617 fetch->setScope(scope); 0618 QObject::connect(fetch, 0619 static_cast<PartsReceivedSignal>(&FetchJob::partsReceived), 0620 fetch, 0621 [&](const QString &, const QMap<qint64, qint64> &, const QMap<qint64, MessageParts> &parts_) { 0622 allParts = parts_; 0623 }); 0624 fetch->exec(); 0625 Q_ASSERT_X(fetch->error() == 0, "FetchJob", fetch->errorString().toLocal8Bit().constData()); 0626 Q_ASSERT(session.state() == Session::Selected); 0627 const auto allpartskeys = allParts.keys(); 0628 for (int id : allpartskeys) { 0629 MessageParts parts = allParts[id]; 0630 const auto partsKeys = parts.keys(); 0631 for (const QByteArray &partId : partsKeys) { 0632 qDebug() << "* Message" << id << "part" << partId << "content:"; 0633 qDebug() << parts[partId]->body(); 0634 } 0635 } 0636 qDebug(); 0637 0638 testDelete(&session); 0639 0640 testSubscribe(&session); 0641 0642 testRename(&session); 0643 0644 testAppendAndStore(&session); 0645 0646 testAcl(&session, user); 0647 0648 testMetaData(&session); 0649 0650 qDebug() << "Expunge INBOX:"; 0651 auto expunge = new ExpungeJob(&session); 0652 expunge->exec(); 0653 0654 qDebug() << "Closing INBOX:"; 0655 auto close = new CloseJob(&session); 0656 close->exec(); 0657 Q_ASSERT(session.state() == Session::Authenticated); 0658 qDebug(); 0659 0660 qDebug() << "Logging out..."; 0661 auto logout = new LogoutJob(&session); 0662 logout->exec(); 0663 Q_ASSERT_X(logout->error() == 0, "LogoutJob", logout->errorString().toLocal8Bit().constData()); 0664 Q_ASSERT(session.state() == Session::Disconnected); 0665 0666 return 0; 0667 }