#include "__IMAP_APPEND.h" #include "IMAPArgs.h" #include "IMAPServer.h" #include "MailFolder.h" #include #include namespace mail { int __IMAP_APPEND::processCommand(coreutils::ZString &request, IMAPSession &session, IMAPServer &server) { if (session.state == IMAPSession::NOT_AUTHENTICATED) { session.out << session.tag << " NO Not authenticated" << CRLF; return 1; } coreutils::ZString mailboxArg = IMAPArgs::nextArgument(request); std::string folderName = IMAPArgs::normalizeFolderName(IMAPArgs::unwrap(mailboxArg)); coreutils::ZString userNameZ(session.userName); if (!IMAPArgs::isValidFolderName(folderName)) { session.out << session.tag << " BAD Invalid mailbox name" << CRLF; return 1; } if (!server.mailFileSystem.ifFolderExists(userNameZ, folderName)) { session.out << session.tag << " NO [TRYCREATE] Mailbox does not exist" << CRLF; return 1; } std::vector flags; time_t internalDate = 0; coreutils::ZString nextArg = IMAPArgs::nextArgument(request); std::string nextText = nextArg.str(); if (!nextText.empty() && nextText[0] == '(') { std::string flagText = IMAPArgs::unwrap(nextArg); std::istringstream flagStream(flagText); std::string flag; while (flagStream >> flag) flags.push_back(flag); nextArg = IMAPArgs::nextArgument(request); nextText = nextArg.str(); } if (!nextText.empty() && nextText[0] == '"') { internalDate = IMAPArgs::parseDate(nextArg); if (internalDate == (time_t)-1) internalDate = 0; nextArg = IMAPArgs::nextArgument(request); nextText = nextArg.str(); } if (nextText.empty() || nextText[0] != '{') { session.out << session.tag << " BAD APPEND requires a message literal" << CRLF; return 1; } long literalSize = std::strtol(IMAPArgs::unwrap(nextArg).c_str(), nullptr, 10); if (literalSize < 0) { session.out << session.tag << " BAD Invalid literal size" << CRLF; return 1; } std::string folderPath = server.mailFileSystem.getFolderPath(userNameZ, folderName).str(); std::string tag = session.tag; bool wasSelectedFolder = (session.state == IMAPSession::SELECTED && session.selectedFolderName == folderName); session.pendingBlockHandler = [&session, folderPath, flags, internalDate, tag, wasSelectedFolder](coreutils::ZString &block) { session.setBlockSize(0); MailFolder folder; folder.load(folderPath); uint32_t uid = folder.append(block.str(), flags, internalDate); // A client that APPENDs into the mailbox it currently has // SELECTed needs its own view refreshed, or a subsequent FETCH/ // STORE against the sequence numbers it already knows would be // working off a stale EXISTS count. if (wasSelectedFolder) session.mailbox = folder; session.out << tag << " OK [APPENDUID " << (int)folder.uidValidity() << " " << (int)uid << "] APPEND completed" << CRLF; session.send(); }; session.out << "+ OK" << CRLF; session.send(); session.setBlockSize((int)literalSize); return 1; } }