diff options
author | Wojtek Kosior <wk@koszkonutek-tmp.pl.eu.org> | 2021-04-30 00:33:56 +0200 |
---|---|---|
committer | Wojtek Kosior <wk@koszkonutek-tmp.pl.eu.org> | 2021-04-30 00:33:56 +0200 |
commit | aa4d426b4d3527d7e166df1a05058c9a4a0f6683 (patch) | |
tree | 4ff17ce8b89a2321b9d0ed4bcfc37c447bcb6820 /vmime-master/tests/net/imap | |
download | smtps-and-pop3s-console-program-master.tar.gz smtps-and-pop3s-console-program-master.zip |
Diffstat (limited to 'vmime-master/tests/net/imap')
-rw-r--r-- | vmime-master/tests/net/imap/IMAPCommandTest.cpp | 495 | ||||
-rw-r--r-- | vmime-master/tests/net/imap/IMAPParserTest.cpp | 374 | ||||
-rw-r--r-- | vmime-master/tests/net/imap/IMAPTagTest.cpp | 90 | ||||
-rw-r--r-- | vmime-master/tests/net/imap/IMAPUtilsTest.cpp | 283 |
4 files changed, 1242 insertions, 0 deletions
diff --git a/vmime-master/tests/net/imap/IMAPCommandTest.cpp b/vmime-master/tests/net/imap/IMAPCommandTest.cpp new file mode 100644 index 0000000..cf3446d --- /dev/null +++ b/vmime-master/tests/net/imap/IMAPCommandTest.cpp @@ -0,0 +1,495 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002 Vincent Richard <vincent@vmime.org> +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules is making +// a combined work based on this library. Thus, the terms and conditions of +// the GNU General Public License cover the whole combination. +// + +#include "tests/testUtils.hpp" + +#include "vmime/net/imap/IMAPCommand.hpp" +#include "vmime/net/imap/IMAPStore.hpp" +#include "vmime/net/imap/IMAPConnection.hpp" + + +using namespace vmime::net::imap; + + +VMIME_TEST_SUITE_BEGIN(IMAPCommandTest) + + VMIME_TEST_LIST_BEGIN + VMIME_TEST(testCreateCommand) + VMIME_TEST(testCreateCommandParams) + VMIME_TEST(testLOGIN) + VMIME_TEST(testAUTHENTICATE) + VMIME_TEST(testAUTHENTICATE_InitialResponse) + VMIME_TEST(testLIST) + VMIME_TEST(testSELECT) + VMIME_TEST(testSTATUS) + VMIME_TEST(testCREATE) + VMIME_TEST(testDELETE) + VMIME_TEST(testRENAME) + VMIME_TEST(testFETCH) + VMIME_TEST(testSTORE) + VMIME_TEST(testAPPEND) + VMIME_TEST(testCOPY) + VMIME_TEST(testSEARCH) + VMIME_TEST(testSTARTTLS) + VMIME_TEST(testCAPABILITY) + VMIME_TEST(testNOOP) + VMIME_TEST(testEXPUNGE) + VMIME_TEST(testCLOSE) + VMIME_TEST(testLOGOUT) + VMIME_TEST(testSend) + VMIME_TEST_LIST_END + + + void testCreateCommand() { + + vmime::shared_ptr <IMAPCommand> cmd = IMAPCommand::createCommand("MY_COMMAND"); + + VASSERT_NOT_NULL("Not null", cmd); + VASSERT_EQ("Text", "MY_COMMAND", cmd->getText()); + } + + void testCreateCommandParams() { + + vmime::shared_ptr <IMAPCommand> cmd = IMAPCommand::createCommand("MY_COMMAND param1 param2"); + + VASSERT_NOT_NULL("Not null", cmd); + VASSERT_EQ("Text", "MY_COMMAND param1 param2", cmd->getText()); + } + + void testLOGIN() { + + vmime::shared_ptr <IMAPCommand> cmd = IMAPCommand::LOGIN("username", "password"); + + VASSERT_NOT_NULL("Not null", cmd); + VASSERT_EQ("Text", "LOGIN username password", cmd->getText()); + VASSERT_EQ("Trace Text", "LOGIN {username} {password}", cmd->getTraceText()); + } + + void testAUTHENTICATE() { + + vmime::shared_ptr <IMAPCommand> cmd = IMAPCommand::AUTHENTICATE("saslmechanism"); + + VASSERT_NOT_NULL("Not null", cmd); + VASSERT_EQ("Text", "AUTHENTICATE saslmechanism", cmd->getText()); + } + + void testAUTHENTICATE_InitialResponse() { + + vmime::shared_ptr <IMAPCommand> cmd = IMAPCommand::AUTHENTICATE("saslmechanism", "initial-response"); + + VASSERT_NOT_NULL("Not null", cmd); + VASSERT_EQ("Text", "AUTHENTICATE saslmechanism initial-response", cmd->getText()); + } + + void testLIST() { + + vmime::shared_ptr <IMAPCommand> cmd = IMAPCommand::LIST("ref-name", "mailbox-name"); + + VASSERT_NOT_NULL("Not null", cmd); + VASSERT_EQ("Text", "LIST ref-name mailbox-name", cmd->getText()); + + vmime::shared_ptr <IMAPCommand> cmdQuote = IMAPCommand::LIST("ref name", "mailbox-name"); + + VASSERT_NOT_NULL("Not null", cmdQuote); + VASSERT_EQ("Text", "LIST \"ref name\" mailbox-name", cmdQuote->getText()); + } + + void testSELECT() { + + std::vector <vmime::string> params; + params.push_back("param-1"); + params.push_back("param-2"); + + + vmime::shared_ptr <IMAPCommand> cmdRO = IMAPCommand::SELECT( + /* readOnly */ true, "mailbox-name", std::vector <vmime::string>() + ); + + VASSERT_NOT_NULL("Not null", cmdRO); + VASSERT_EQ("Text", "EXAMINE mailbox-name", cmdRO->getText()); + + vmime::shared_ptr <IMAPCommand> cmdROQuote = IMAPCommand::SELECT( + /* readOnly */ true, "mailbox name", std::vector <vmime::string>() + ); + + VASSERT_NOT_NULL("Not null", cmdROQuote); + VASSERT_EQ("Text", "EXAMINE \"mailbox name\"", cmdROQuote->getText()); + + + vmime::shared_ptr <IMAPCommand> cmdRW = IMAPCommand::SELECT( + /* readOnly */ false, "mailbox-name", std::vector <vmime::string>() + ); + + VASSERT_NOT_NULL("Not null", cmdRW); + VASSERT_EQ("Text", "SELECT mailbox-name", cmdRW->getText()); + + vmime::shared_ptr <IMAPCommand> cmdRWParams = IMAPCommand::SELECT( + /* readOnly */ false, "mailbox-name", params + ); + + VASSERT_NOT_NULL("Not null", cmdRWParams); + VASSERT_EQ("Text", "SELECT mailbox-name (param-1 param-2)", cmdRWParams->getText()); + + vmime::shared_ptr <IMAPCommand> cmdRWQuote = IMAPCommand::SELECT( + /* readOnly */ false, "mailbox name", std::vector <vmime::string>() + ); + + VASSERT_NOT_NULL("Not null", cmdRWQuote); + VASSERT_EQ("Text", "SELECT \"mailbox name\"", cmdRWQuote->getText()); + } + + void testSTATUS() { + + std::vector <vmime::string> attribs; + attribs.push_back("attrib-1"); + attribs.push_back("attrib-2"); + + + vmime::shared_ptr <IMAPCommand> cmd = + IMAPCommand::STATUS("mailbox-name", attribs); + + VASSERT_NOT_NULL("Not null", cmd); + VASSERT_EQ("Text", "STATUS mailbox-name (attrib-1 attrib-2)", cmd->getText()); + + + vmime::shared_ptr <IMAPCommand> cmdQuote = + IMAPCommand::STATUS("mailbox name", attribs); + + VASSERT_NOT_NULL("Not null", cmdQuote); + VASSERT_EQ("Text", "STATUS \"mailbox name\" (attrib-1 attrib-2)", cmdQuote->getText()); + } + + void testCREATE() { + + std::vector <vmime::string> params; + params.push_back("param-1"); + params.push_back("param-2"); + + + vmime::shared_ptr <IMAPCommand> cmd = + IMAPCommand::CREATE("mailbox-name", params); + + VASSERT_NOT_NULL("Not null", cmd); + VASSERT_EQ("Text", "CREATE mailbox-name (param-1 param-2)", cmd->getText()); + + + vmime::shared_ptr <IMAPCommand> cmdQuote = + IMAPCommand::CREATE("mailbox name", params); + + VASSERT_NOT_NULL("Not null", cmdQuote); + VASSERT_EQ("Text", "CREATE \"mailbox name\" (param-1 param-2)", cmdQuote->getText()); + + + vmime::shared_ptr <IMAPCommand> cmdNoParam = + IMAPCommand::CREATE("mailbox-name", std::vector <vmime::string>()); + + VASSERT_NOT_NULL("Not null", cmdNoParam); + VASSERT_EQ("Text", "CREATE mailbox-name", cmdNoParam->getText()); + } + + void testDELETE() { + + vmime::shared_ptr <IMAPCommand> cmd = + IMAPCommand::DELETE("mailbox-name"); + + VASSERT_NOT_NULL("Not null", cmd); + VASSERT_EQ("Text", "DELETE mailbox-name", cmd->getText()); + + + vmime::shared_ptr <IMAPCommand> cmdQuote = + IMAPCommand::DELETE("mailbox name"); + + VASSERT_NOT_NULL("Not null", cmdQuote); + VASSERT_EQ("Text", "DELETE \"mailbox name\"", cmdQuote->getText()); + } + + void testRENAME() { + + vmime::shared_ptr <IMAPCommand> cmd = + IMAPCommand::RENAME("mailbox-name", "new-mailbox-name"); + + VASSERT_NOT_NULL("Not null", cmd); + VASSERT_EQ("Text", "RENAME mailbox-name new-mailbox-name", cmd->getText()); + + + vmime::shared_ptr <IMAPCommand> cmdQuote = + IMAPCommand::RENAME("mailbox name", "new mailbox name"); + + VASSERT_NOT_NULL("Not null", cmdQuote); + VASSERT_EQ("Text", "RENAME \"mailbox name\" \"new mailbox name\"", cmdQuote->getText()); + } + + void testFETCH() { + + std::vector <vmime::string> params; + params.push_back("param-1"); + params.push_back("param-2"); + + + vmime::shared_ptr <IMAPCommand> cmdNum = + IMAPCommand::FETCH(vmime::net::messageSet::byNumber(42), params); + + VASSERT_NOT_NULL("Not null", cmdNum); + VASSERT_EQ("Text", "FETCH 42 (param-1 param-2)", cmdNum->getText()); + + + vmime::shared_ptr <IMAPCommand> cmdNums = + IMAPCommand::FETCH(vmime::net::messageSet::byNumber(42, 47), params); + + VASSERT_NOT_NULL("Not null", cmdNums); + VASSERT_EQ("Text", "FETCH 42:47 (param-1 param-2)", cmdNums->getText()); + + + vmime::shared_ptr <IMAPCommand> cmdUID = + IMAPCommand::FETCH(vmime::net::messageSet::byUID(42), params); + + VASSERT_NOT_NULL("Not null", cmdUID); + VASSERT_EQ("Text", "UID FETCH 42 (param-1 param-2)", cmdUID->getText()); + + + vmime::shared_ptr <IMAPCommand> cmdUIDs = + IMAPCommand::FETCH(vmime::net::messageSet::byUID(42, 47), params); + + VASSERT_NOT_NULL("Not null", cmdUIDs); + VASSERT_EQ("Text", "UID FETCH 42:47 (param-1 param-2)", cmdUIDs->getText()); + } + + void testSTORE() { + + std::vector <vmime::string> flags; + flags.push_back("flag-1"); + flags.push_back("flag-2"); + + + vmime::shared_ptr <IMAPCommand> cmdNum = IMAPCommand::STORE( + vmime::net::messageSet::byNumber(42), vmime::net::message::FLAG_MODE_SET, flags + ); + + VASSERT_NOT_NULL("Not null", cmdNum); + VASSERT_EQ("Text", "STORE 42 FLAGS (flag-1 flag-2)", cmdNum->getText()); + + + vmime::shared_ptr <IMAPCommand> cmdNums = IMAPCommand::STORE( + vmime::net::messageSet::byNumber(42, 47), vmime::net::message::FLAG_MODE_SET, flags + ); + + VASSERT_NOT_NULL("Not null", cmdNums); + VASSERT_EQ("Text", "STORE 42:47 FLAGS (flag-1 flag-2)", cmdNums->getText()); + + + vmime::shared_ptr <IMAPCommand> cmdUID = IMAPCommand::STORE( + vmime::net::messageSet::byUID(42), vmime::net::message::FLAG_MODE_SET, flags + ); + + VASSERT_NOT_NULL("Not null", cmdUID); + VASSERT_EQ("Text", "UID STORE 42 FLAGS (flag-1 flag-2)", cmdUID->getText()); + + + vmime::shared_ptr <IMAPCommand> cmdUIDs = IMAPCommand::STORE( + vmime::net::messageSet::byUID(42, 47), vmime::net::message::FLAG_MODE_SET, flags + ); + + VASSERT_NOT_NULL("Not null", cmdUIDs); + VASSERT_EQ("Text", "UID STORE 42:47 FLAGS (flag-1 flag-2)", cmdUIDs->getText()); + + + vmime::shared_ptr <IMAPCommand> cmdAdd = IMAPCommand::STORE( + vmime::net::messageSet::byUID(42, 47), vmime::net::message::FLAG_MODE_ADD, flags + ); + + VASSERT_NOT_NULL("Not null", cmdAdd); + VASSERT_EQ("Text", "UID STORE 42:47 +FLAGS (flag-1 flag-2)", cmdAdd->getText()); + + + vmime::shared_ptr <IMAPCommand> cmdRem = IMAPCommand::STORE( + vmime::net::messageSet::byUID(42, 47), vmime::net::message::FLAG_MODE_REMOVE, flags + ); + + VASSERT_NOT_NULL("Not null", cmdRem); + VASSERT_EQ("Text", "UID STORE 42:47 -FLAGS (flag-1 flag-2)", cmdRem->getText()); + } + + void testAPPEND() { + + std::vector <vmime::string> flags; + flags.push_back("flag-1"); + flags.push_back("flag-2"); + + + vmime::shared_ptr <IMAPCommand> cmd = + IMAPCommand::APPEND("mailbox-name", flags, /* date */ NULL, 1234); + + VASSERT_NOT_NULL("Not null", cmd); + VASSERT_EQ("Text", "APPEND mailbox-name (flag-1 flag-2) {1234}", cmd->getText()); + + + vmime::shared_ptr <IMAPCommand> cmdQuote = + IMAPCommand::APPEND("mailbox name", flags, /* date */ NULL, 1234); + + VASSERT_NOT_NULL("Not null", cmdQuote); + VASSERT_EQ("Text", "APPEND \"mailbox name\" (flag-1 flag-2) {1234}", cmdQuote->getText()); + + + vmime::datetime date(2014, 3, 15, 23, 11, 47, vmime::datetime::GMT2); + vmime::shared_ptr <IMAPCommand> cmdDate = + IMAPCommand::APPEND("mailbox name", flags, &date, 1234); + + VASSERT_NOT_NULL("Not null", cmdDate); + VASSERT_EQ("Text", "APPEND \"mailbox name\" (flag-1 flag-2) \"15-Mar-2014 23:11:47 +0200\" {1234}", cmdDate->getText()); + } + + void testCOPY() { + + vmime::shared_ptr <IMAPCommand> cmdNum = + IMAPCommand::COPY(vmime::net::messageSet::byNumber(42), "mailbox-name"); + + VASSERT_NOT_NULL("Not null", cmdNum); + VASSERT_EQ("Text", "COPY 42 mailbox-name", cmdNum->getText()); + + + vmime::shared_ptr <IMAPCommand> cmdNums = + IMAPCommand::COPY(vmime::net::messageSet::byNumber(42, 47), "mailbox-name"); + + VASSERT_NOT_NULL("Not null", cmdNums); + VASSERT_EQ("Text", "COPY 42:47 mailbox-name", cmdNums->getText()); + + + vmime::shared_ptr <IMAPCommand> cmdUID = + IMAPCommand::COPY(vmime::net::messageSet::byUID(42), "mailbox-name"); + + VASSERT_NOT_NULL("Not null", cmdUID); + VASSERT_EQ("Text", "UID COPY 42 mailbox-name", cmdUID->getText()); + + + vmime::shared_ptr <IMAPCommand> cmdUIDs = + IMAPCommand::COPY(vmime::net::messageSet::byUID(42, 47), "mailbox-name"); + + VASSERT_NOT_NULL("Not null", cmdUIDs); + VASSERT_EQ("Text", "UID COPY 42:47 mailbox-name", cmdUIDs->getText()); + + + vmime::shared_ptr <IMAPCommand> cmdQuote = + IMAPCommand::COPY(vmime::net::messageSet::byNumber(42, 47), "mailbox name"); + + VASSERT_NOT_NULL("Not null", cmdQuote); + VASSERT_EQ("Text", "COPY 42:47 \"mailbox name\"", cmdQuote->getText()); + } + + void testSEARCH() { + + std::vector <vmime::string> searchKeys; + searchKeys.push_back("search-key-1"); + searchKeys.push_back("search-key-2"); + + vmime::shared_ptr <IMAPCommand> cmd = + IMAPCommand::SEARCH(searchKeys, /* charset */ NULL); + + VASSERT_NOT_NULL("Not null", cmd); + VASSERT_EQ("Text", "SEARCH search-key-1 search-key-2", cmd->getText()); + + + vmime::charset cset("test-charset"); + + vmime::shared_ptr <IMAPCommand> cmdCset = + IMAPCommand::SEARCH(searchKeys, &cset); + + VASSERT_NOT_NULL("Not null", cmdCset); + VASSERT_EQ("Text", "SEARCH CHARSET test-charset search-key-1 search-key-2", cmdCset->getText()); + } + + void testSTARTTLS() { + + vmime::shared_ptr <IMAPCommand> cmd = IMAPCommand::STARTTLS(); + + VASSERT_NOT_NULL("Not null", cmd); + VASSERT_EQ("Text", "STARTTLS", cmd->getText()); + } + + void testCAPABILITY() { + + vmime::shared_ptr <IMAPCommand> cmd = IMAPCommand::CAPABILITY(); + + VASSERT_NOT_NULL("Not null", cmd); + VASSERT_EQ("Text", "CAPABILITY", cmd->getText()); + } + + void testNOOP() { + + vmime::shared_ptr <IMAPCommand> cmd = IMAPCommand::NOOP(); + + VASSERT_NOT_NULL("Not null", cmd); + VASSERT_EQ("Text", "NOOP", cmd->getText()); + } + + void testEXPUNGE() { + + vmime::shared_ptr <IMAPCommand> cmd = IMAPCommand::EXPUNGE(); + + VASSERT_NOT_NULL("Not null", cmd); + VASSERT_EQ("Text", "EXPUNGE", cmd->getText()); + } + + void testCLOSE() { + + vmime::shared_ptr <IMAPCommand> cmd = IMAPCommand::CLOSE(); + + VASSERT_NOT_NULL("Not null", cmd); + VASSERT_EQ("Text", "CLOSE", cmd->getText()); + } + + void testLOGOUT() { + + vmime::shared_ptr <IMAPCommand> cmd = IMAPCommand::LOGOUT(); + + VASSERT_NOT_NULL("Not null", cmd); + VASSERT_EQ("Text", "LOGOUT", cmd->getText()); + } + + void testSend() { + + vmime::shared_ptr <IMAPCommand> cmd = + IMAPCommand::createCommand("MY_COMMAND param1 param2"); + + vmime::shared_ptr <vmime::net::session> sess = vmime::net::session::create(); + + vmime::shared_ptr <vmime::security::authenticator> auth = + vmime::make_shared <vmime::security::defaultAuthenticator>(); + + vmime::shared_ptr <IMAPStore> store = + vmime::make_shared <IMAPStore>(sess, auth, /* secured */ false); + + vmime::shared_ptr <IMAPConnection> conn = + vmime::make_shared <IMAPConnection>(store, auth); + + vmime::shared_ptr <testSocket> sok = vmime::make_shared <testSocket>(); + conn->setSocket(sok); + + cmd->send(conn); + + vmime::string response; + sok->localReceive(response); + + VASSERT_EQ("Sent buffer", vmime::string(*conn->getTag()) + " MY_COMMAND param1 param2\r\n", response); + } + +VMIME_TEST_SUITE_END diff --git a/vmime-master/tests/net/imap/IMAPParserTest.cpp b/vmime-master/tests/net/imap/IMAPParserTest.cpp new file mode 100644 index 0000000..60ce16d --- /dev/null +++ b/vmime-master/tests/net/imap/IMAPParserTest.cpp @@ -0,0 +1,374 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002 Vincent Richard <vincent@vmime.org> +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules is making +// a combined work based on this library. Thus, the terms and conditions of +// the GNU General Public License cover the whole combination. +// + +#include "tests/testUtils.hpp" + +#include "vmime/net/imap/IMAPTag.hpp" +#include "vmime/net/imap/IMAPParser.hpp" + + +VMIME_TEST_SUITE_BEGIN(IMAPParserTest) + + VMIME_TEST_LIST_BEGIN + VMIME_TEST(testExtraSpaceInCapaResponse) + VMIME_TEST(testContinueReqWithoutSpace) + VMIME_TEST(testNILValueInBodyFldEnc) + VMIME_TEST(testFETCHResponse_optional_body_fld_lang) + VMIME_TEST(testFETCHBodyStructure_NIL_body_fld_param_value) + VMIME_TEST(testFETCHBodyStructure_empty_body_fld_param_instead_of_NIL) + VMIME_TEST(testPipelining) + VMIME_TEST(testStarFlagWithoutBackslash) + VMIME_TEST_LIST_END + + + // For Apple iCloud IMAP server + void testExtraSpaceInCapaResponse() { + + const char* resp = + "* CAPABILITY IMAP4rev1 AUTH=ATOKEN AUTH=PLAIN \r\n" // extra space at end + "a001 OK Capability completed.\r\n"; + + // Strict mode + { + auto socket = vmime::make_shared <testSocket>(); + socket->localSend(resp); + + auto parser = vmime::make_shared <vmime::net::imap::IMAPParser>(); + auto tag = vmime::make_shared <vmime::net::imap::IMAPTag>(); + + parser->setSocket(socket); + parser->setTimeoutHandler(vmime::make_shared <testTimeoutHandler>()); + parser->setStrict(true); + + VASSERT_THROW("strict mode", parser->readResponse(*tag), vmime::exceptions::invalid_response); + } + + // Non-strict mode + { + auto socket = vmime::make_shared <testSocket>(); + socket->localSend(resp); + + auto parser = vmime::make_shared <vmime::net::imap::IMAPParser>(); + auto tag = vmime::make_shared <vmime::net::imap::IMAPTag>(); + + parser->setSocket(socket); + parser->setTimeoutHandler(vmime::make_shared <testTimeoutHandler>()); + parser->setStrict(false); + + VASSERT_NO_THROW("non-strict mode", parser->readResponse(*tag)); + } + } + + // For Apple iCloud/Exchange IMAP server + void testContinueReqWithoutSpace() { + + // continue_req ::= "+" SPACE (resp_text / base64) + // + // Some servers do not send SPACE when response text is empty. + // IMAP parser should allow this in non-strict mode. + // + // Eg: + // + // C: a002 AUTHENTICATE xxx[CR][LF] + // S: +[CR][LF] + + vmime::shared_ptr <testSocket> socket = vmime::make_shared <testSocket>(); + vmime::shared_ptr <vmime::net::timeoutHandler> toh = vmime::make_shared <testTimeoutHandler>(); + + vmime::shared_ptr <vmime::net::imap::IMAPTag> tag = + vmime::make_shared <vmime::net::imap::IMAPTag>(); + + socket->localSend("+\r\n"); + + vmime::shared_ptr <vmime::net::imap::IMAPParser> parser = + vmime::make_shared <vmime::net::imap::IMAPParser>(); + + parser->setSocket(socket); + parser->setTimeoutHandler(toh); + + parser->setStrict(false); + VASSERT_NO_THROW("non-strict mode", parser->readResponse(*tag)); + + ++(*tag); + + socket->localSend("+\r\n"); + + parser->setStrict(true); + VASSERT_THROW("strict mode", parser->readResponse(*tag), vmime::exceptions::invalid_response); + } + + // When an IMAP4 client sends a FETCH (bodystructure) request to a server + // that is running the Exchange Server 2007 IMAP4 service, a corrupted + // response is sent as a reply + // --> http://support.microsoft.com/kb/975918/en-us + void testNILValueInBodyFldEnc() { + + const char* resp = "* 7970 FETCH (UID 8036 FLAGS () BODYSTRUCTURE (\"text\" \"html\" (\"charset\" \"utf-8\") NIL NIL NIL 175501 1651 NIL NIL NIL NIL) RFC822.HEADER {3}\r\nx\r\n)\r\na001 OK FETCH complete\r\n"; + + // Strict mode + { + auto socket = vmime::make_shared <testSocket>(); + socket->localSend(resp); + + auto parser = vmime::make_shared <vmime::net::imap::IMAPParser>(); + auto tag = vmime::make_shared <vmime::net::imap::IMAPTag>(); + + parser->setSocket(socket); + parser->setTimeoutHandler(vmime::make_shared <testTimeoutHandler>()); + parser->setStrict(true); + + VASSERT_THROW("strict mode", parser->readResponse(*tag), vmime::exceptions::invalid_response); + } + + // Non-strict mode + { + auto socket = vmime::make_shared <testSocket>(); + socket->localSend(resp); + + auto parser = vmime::make_shared <vmime::net::imap::IMAPParser>(); + auto tag = vmime::make_shared <vmime::net::imap::IMAPTag>(); + + parser->setSocket(socket); + parser->setTimeoutHandler(vmime::make_shared <testTimeoutHandler>()); + parser->setStrict(false); + + VASSERT_NO_THROW("non-strict mode", parser->readResponse(*tag)); + } + } + + // "body_fld_lang" is optional after "body_fld_dsp" in "body_ext_mpart" (Yahoo) + void testFETCHResponse_optional_body_fld_lang() { + + vmime::shared_ptr <testSocket> socket = vmime::make_shared <testSocket>(); + vmime::shared_ptr <vmime::net::timeoutHandler> toh = vmime::make_shared <testTimeoutHandler>(); + + vmime::shared_ptr <vmime::net::imap::IMAPTag> tag = + vmime::make_shared <vmime::net::imap::IMAPTag>(); + + const char* resp = "* 1 FETCH (UID 7 RFC822.SIZE 694142 BODYSTRUCTURE (((\"text\" \"plain\" (\"charset\" \"utf-8\") NIL NIL \"7bit\" 0 0 NIL NIL NIL NIL)(\"text\" \"html\" (\"charset\" \"utf-8\") NIL NIL \"7bit\" 193 0 NIL NIL NIL NIL) \"alternative\" (\"boundary\" \"----=_Part_536_109505883.1410847112666\") NIL)(\"image\" \"jpeg\" NIL \"<4db20d0e-e9f8-729b-aaf7-688b5956d0bc@yahoo.com>\" NIL \"base64\" 351784 NIL (\"attachment\" (\"name\" \"att2\" \"filename\" \"9.jpg\")) NIL NIL)(\"image\" \"jpeg\" NIL \"<542417d7-c0ed-db72-f9fc-d9ab2c7e0a6f@yahoo.com>\" NIL \"base64\" 337676 NIL (\"attachment\" (\"name\" \"att3\" \"filename\" \"10.jpg\")) NIL NIL) \"mixed\" (\"boundary\" \"----=_Part_537_1371134700.1410847112668\") NIL) RFC822.HEADER {3}\r\nx\r\n)\r\na001 OK FETCH complete\r\n"; + + socket->localSend(resp); + + vmime::shared_ptr <vmime::net::imap::IMAPParser> parser = + vmime::make_shared <vmime::net::imap::IMAPParser>(); + + parser->setSocket(socket); + parser->setTimeoutHandler(toh); + + VASSERT_NO_THROW("parse", parser->readResponse(*tag)); + } + + // Support for NIL boundary, for mail.ru IMAP server: + // https://www.ietf.org/mail-archive/web/imapext/current/msg05442.html + void testFETCHBodyStructure_NIL_body_fld_param_value() { + + // ...("boundary" NIL)))... is an invalid syntax for a "body_fld_param_item" + const char* resp = "* 1 FETCH (BODYSTRUCTURE ((\"text\" \"plain\" (\"charset\" \"utf-8\") NIL NIL \"8bit\" 536 0 NIL NIL NIL NIL)(\"text\" \"html\" (\"charset\" \"utf-8\") NIL NIL \"8bit\" 7130 0 NIL NIL NIL NIL) \"alternative\" (\"boundary\" NIL)))\r\na001 OK FETCH complete\r\n"; + + // Strict mode + { + auto socket = vmime::make_shared <testSocket>(); + socket->localSend(resp); + + auto parser = vmime::make_shared <vmime::net::imap::IMAPParser>(); + auto tag = vmime::make_shared <vmime::net::imap::IMAPTag>(); + + parser->setSocket(socket); + parser->setTimeoutHandler(vmime::make_shared <testTimeoutHandler>()); + parser->setStrict(true); + + VASSERT_THROW("strict mode", parser->readResponse(*tag), vmime::exceptions::invalid_response); + } + + // Non-strict mode + { + auto socket = vmime::make_shared <testSocket>(); + socket->localSend(resp); + + auto parser = vmime::make_shared <vmime::net::imap::IMAPParser>(); + auto tag = vmime::make_shared <vmime::net::imap::IMAPTag>(); + + parser->setSocket(socket); + parser->setTimeoutHandler(vmime::make_shared <testTimeoutHandler>()); + parser->setStrict(false); + + VASSERT_NO_THROW("non-strict mode", parser->readResponse(*tag)); + } + } + + void testFETCHBodyStructure_empty_body_fld_param_instead_of_NIL() { + + const char* resp = "* 1 FETCH (BODYSTRUCTURE ((\"text\" \"html\" (\"charset\" \"cp1251\") NIL NIL \"base64\" 84056 0 NIL (\"inline\" NIL) NIL NIL)(\"image\" \"gif\" () \"25b2b55b5d97f04e9ea939fe32a46a65.gif\" NIL \"base64\" 20776 NIL (\"inline\" NIL) NIL NIL) \"related\" (\"boundary\" NIL)))\r\na001 OK FETCH complete\r\n"; + + // Strict mode + { + auto socket = vmime::make_shared <testSocket>(); + socket->localSend(resp); + + auto parser = vmime::make_shared <vmime::net::imap::IMAPParser>(); + auto tag = vmime::make_shared <vmime::net::imap::IMAPTag>(); + + parser->setSocket(socket); + parser->setTimeoutHandler(vmime::make_shared <testTimeoutHandler>()); + parser->setStrict(true); + + VASSERT_THROW("strict mode", parser->readResponse(*tag), vmime::exceptions::invalid_response); + } + + // Non-strict mode + { + auto socket = vmime::make_shared <testSocket>(); + socket->localSend(resp); + + auto parser = vmime::make_shared <vmime::net::imap::IMAPParser>(); + auto tag = vmime::make_shared <vmime::net::imap::IMAPTag>(); + + parser->setSocket(socket); + parser->setTimeoutHandler(vmime::make_shared <testTimeoutHandler>()); + parser->setStrict(false); + + VASSERT_NO_THROW("non-strict mode", parser->readResponse(*tag)); + } + } + + // Test pipelined and out-of-order replies + void testPipelining() { + + /* + [C] a001 SELECT "INBOX" + [C] a002 UID FETCH 42 (INTERNALDATE) + [C] a003 UID FETCH 43 (INTERNALDATE) + [S] * NO Error for a001 + [S] a001 NO Access denied + [S] * NO Error for a003 + [S] a003 BAD No mailbox selected + [S] * NO Error for a002 + [S] a002 BAD No mailbox selected + */ + + vmime::shared_ptr <testSocket> socket = vmime::make_shared <testSocket>(); + vmime::shared_ptr <vmime::net::timeoutHandler> toh = vmime::make_shared <testTimeoutHandler>(); + + vmime::net::imap::IMAPTag tag1; // a001 + vmime::net::imap::IMAPTag tag2(tag1); // a002 + ++tag2; + vmime::net::imap::IMAPTag tag3(tag2); // a003 + ++tag3; + + socket->localSend( + "* NO Error for a001\r\n" + "a001 NO Access denied\r\n" + "* NO Error for a003\r\n" + "a003 BAD No mailbox selected a003\r\n" + "* NO Error for a002\r\n" + "a002 BAD No mailbox selected a002\r\n" + ); + + vmime::shared_ptr <vmime::net::imap::IMAPParser> parser = + vmime::make_shared <vmime::net::imap::IMAPParser>(); + + parser->setSocket(socket); + parser->setTimeoutHandler(toh); + + // Test response a001 + vmime::scoped_ptr <vmime::net::imap::IMAPParser::response> resp1(parser->readResponse(tag1, /* literalHandler */ NULL)); + VASSERT("a001 response", resp1); + VASSERT("a001 response_done", resp1->response_done); + VASSERT_EQ("a001 response tag", "a001", resp1->response_done->response_tagged->tag->tagString); + VASSERT_EQ("a001 response text", "Access denied", resp1->response_done->response_tagged->resp_cond_state->resp_text->text); + VASSERT_EQ("a001 resp_data.size()", 1, resp1->continue_req_or_response_data.size()); + VASSERT("a001 resp_data[0]", resp1->continue_req_or_response_data[0]->response_data); + VASSERT("a001 resp_cond_state", resp1->continue_req_or_response_data[0]->response_data->resp_cond_state); + VASSERT_EQ("a001 resp_cond_state.text", "Error for a001", resp1->continue_req_or_response_data[0]->response_data->resp_cond_state->resp_text->text); + VASSERT_EQ("a001 resp_cond_state.status", vmime::net::imap::IMAPParser::resp_cond_state::NO, resp1->continue_req_or_response_data[0]->response_data->resp_cond_state->status); + + // Test response a002 + vmime::scoped_ptr <vmime::net::imap::IMAPParser::response> resp2(parser->readResponse(tag2, /* literalHandler */ NULL)); + VASSERT("a002 response", resp2); + VASSERT("a002 response_done", resp2->response_done); + VASSERT_EQ("a002 response tag", "a002", resp2->response_done->response_tagged->tag->tagString); + VASSERT_EQ("a002 response text", "No mailbox selected a002", resp2->response_done->response_tagged->resp_cond_state->resp_text->text); + VASSERT_EQ("a002 resp_data.size()", 1, resp2->continue_req_or_response_data.size()); + VASSERT("a002 resp_data[0]", resp2->continue_req_or_response_data[0]->response_data); + VASSERT("a002 resp_cond_state", resp2->continue_req_or_response_data[0]->response_data->resp_cond_state); + VASSERT_EQ("a002 resp_cond_state.text", "Error for a002", resp2->continue_req_or_response_data[0]->response_data->resp_cond_state->resp_text->text); + VASSERT_EQ("a002 resp_cond_state.status", vmime::net::imap::IMAPParser::resp_cond_state::NO, resp2->continue_req_or_response_data[0]->response_data->resp_cond_state->status); + + // Test response a003 + vmime::scoped_ptr <vmime::net::imap::IMAPParser::response> resp3(parser->readResponse(tag3, /* literalHandler */ NULL)); + VASSERT("a003 response", resp3); + VASSERT("a003 response_done", resp3->response_done); + VASSERT_EQ("a003 response tag", "a003", resp3->response_done->response_tagged->tag->tagString); + VASSERT_EQ("a003 response text", "No mailbox selected a003", resp3->response_done->response_tagged->resp_cond_state->resp_text->text); + VASSERT_EQ("a003 resp_data.size()", 1, resp3->continue_req_or_response_data.size()); + VASSERT("a003 resp_data[0]", resp3->continue_req_or_response_data[0]->response_data); + VASSERT("a003 resp_cond_state", resp3->continue_req_or_response_data[0]->response_data->resp_cond_state); + VASSERT_EQ("a003 resp_cond_state.text", "Error for a003", resp3->continue_req_or_response_data[0]->response_data->resp_cond_state->resp_text->text); + VASSERT_EQ("a003 resp_cond_state.status", vmime::net::imap::IMAPParser::resp_cond_state::NO, resp3->continue_req_or_response_data[0]->response_data->resp_cond_state->status); + } + + // Some IMAP servers return "*" instead of "\*" in PERMANENTFLAGS + void testStarFlagWithoutBackslash() { + + const char* resp = + "* OK [PERMANENTFLAGS (Answered Flagged Deleted Seen Draft *)] Flags permitted.\r\n" + "a001 OK Completed.\r\n"; + + // Strict mode + { + auto socket = vmime::make_shared <testSocket>(); + auto toh = vmime::make_shared <testTimeoutHandler>(); + + auto tag = vmime::make_shared <vmime::net::imap::IMAPTag>(); + + socket->localSend(resp); + + auto parser = vmime::make_shared <vmime::net::imap::IMAPParser>(); + + parser->setSocket(socket); + parser->setTimeoutHandler(toh); + parser->setStrict(true); + + VASSERT_THROW("strict mode", parser->readResponse(*tag), vmime::exceptions::invalid_response); + } + + // Non-strict mode + { + auto socket = vmime::make_shared <testSocket>(); + auto toh = vmime::make_shared <testTimeoutHandler>(); + + auto tag = vmime::make_shared <vmime::net::imap::IMAPTag>(); + + socket->localSend(resp); + + auto parser = vmime::make_shared <vmime::net::imap::IMAPParser>(); + + parser->setSocket(socket); + parser->setTimeoutHandler(toh); + parser->setStrict(false); + + VASSERT_NO_THROW("non-strict mode", parser->readResponse(*tag)); + } + } + +VMIME_TEST_SUITE_END diff --git a/vmime-master/tests/net/imap/IMAPTagTest.cpp b/vmime-master/tests/net/imap/IMAPTagTest.cpp new file mode 100644 index 0000000..c8e09b6 --- /dev/null +++ b/vmime-master/tests/net/imap/IMAPTagTest.cpp @@ -0,0 +1,90 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002 Vincent Richard <vincent@vmime.org> +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules is making +// a combined work based on this library. Thus, the terms and conditions of +// the GNU General Public License cover the whole combination. +// + +#include "tests/testUtils.hpp" + +#include "vmime/net/imap/IMAPTag.hpp" + + +VMIME_TEST_SUITE_BEGIN(imapTagTest) + + VMIME_TEST_LIST_BEGIN + VMIME_TEST(testConstruct) + VMIME_TEST(testIncrement) + VMIME_TEST(testReset) + VMIME_TEST(testNumber) + VMIME_TEST_LIST_END + + + void testConstruct() { + + vmime::shared_ptr <vmime::net::imap::IMAPTag> tag = + vmime::make_shared <vmime::net::imap::IMAPTag>(); + + VASSERT_EQ("init", "a001", static_cast <vmime::string>(*tag)); + } + + void testIncrement() { + + vmime::shared_ptr <vmime::net::imap::IMAPTag> tag = + vmime::make_shared <vmime::net::imap::IMAPTag>(); + + (*tag)++; + VASSERT_EQ("init", "a002", static_cast <vmime::string>(*tag)); + + (*tag)++; + VASSERT_EQ("init", "a003", static_cast <vmime::string>(*tag)); + + (*tag)++; + VASSERT_EQ("init", "a004", static_cast <vmime::string>(*tag)); + } + + void testReset() { + + vmime::shared_ptr <vmime::net::imap::IMAPTag> tag = + vmime::make_shared <vmime::net::imap::IMAPTag>(); + + for (int i = tag->number() ; i < tag->maximumNumber() ; ++i) { + (*tag)++; + } + + VASSERT_EQ("last", "Z999", static_cast <vmime::string>(*tag)); + + (*tag)++; + + VASSERT_EQ("reset", "a001", static_cast <vmime::string>(*tag)); + } + + void testNumber() { + + vmime::shared_ptr <vmime::net::imap::IMAPTag> tag = + vmime::make_shared <vmime::net::imap::IMAPTag>(); + + for (int i = 0 ; i < 41 ; ++i) { + (*tag)++; + } + + VASSERT_EQ("number", 42, tag->number()); + } + +VMIME_TEST_SUITE_END diff --git a/vmime-master/tests/net/imap/IMAPUtilsTest.cpp b/vmime-master/tests/net/imap/IMAPUtilsTest.cpp new file mode 100644 index 0000000..b707fd0 --- /dev/null +++ b/vmime-master/tests/net/imap/IMAPUtilsTest.cpp @@ -0,0 +1,283 @@ +// +// VMime library (http://www.vmime.org) +// Copyright (C) 2002 Vincent Richard <vincent@vmime.org> +// +// This program is free software; you can redistribute it and/or +// modify it under the terms of the GNU General Public License as +// published by the Free Software Foundation; either version 3 of +// the License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. +// +// You should have received a copy of the GNU General Public License along +// with this program; if not, write to the Free Software Foundation, Inc., +// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +// +// Linking this library statically or dynamically with other modules is making +// a combined work based on this library. Thus, the terms and conditions of +// the GNU General Public License cover the whole combination. +// + +#include "tests/testUtils.hpp" + +#include "vmime/net/imap/IMAPUtils.hpp" +#include "vmime/net/imap/IMAPParser.hpp" + + +using namespace vmime::net::imap; + + + +VMIME_TEST_SUITE_BEGIN(IMAPUtilsTest) + + VMIME_TEST_LIST_BEGIN + VMIME_TEST(testQuoteString) + VMIME_TEST(testToModifiedUTF7) + VMIME_TEST(testFromModifiedUTF7) + VMIME_TEST(testConvertAddressList) + VMIME_TEST(testMessageFlagList) + VMIME_TEST(testDateTime) + VMIME_TEST(testPathToString) + VMIME_TEST(testStringToPath) + VMIME_TEST(testBuildFetchCommand) + VMIME_TEST_LIST_END + + + void testQuoteString() { + + VASSERT_EQ("unquoted", "ascii", IMAPUtils::quoteString("ascii")); + VASSERT_EQ("space", "\"ascii with space\"", IMAPUtils::quoteString("ascii with space")); + + VASSERT_EQ("special1", "\"(\"", IMAPUtils::quoteString("(")); + VASSERT_EQ("special2", "\")\"", IMAPUtils::quoteString(")")); + VASSERT_EQ("special3", "\"{\"", IMAPUtils::quoteString("{")); + VASSERT_EQ("special4", "\" \"", IMAPUtils::quoteString(" ")); + VASSERT_EQ("special5", "\"%\"", IMAPUtils::quoteString("%")); + VASSERT_EQ("special6", "\"*\"", IMAPUtils::quoteString("*")); + VASSERT_EQ("special7", "\"\\\"\"", IMAPUtils::quoteString("\"")); + VASSERT_EQ("special8", "\"\\\\\"", IMAPUtils::quoteString("\\")); + VASSERT_EQ("special9", "\"\x7f\"", IMAPUtils::quoteString("\x7f")); + + } + + void testToModifiedUTF7() { + + #define FC(x) vmime::net::folder::path::component(x, vmime::charsets::UTF_8) + + // Example strings from RFC-1642 (modified for IMAP UTF-7) + VASSERT_EQ("1", "A&ImIDkQ-.", IMAPUtils::toModifiedUTF7('/', FC("A\xe2\x89\xa2\xce\x91."))); + VASSERT_EQ("2", "Hi Mum &Jjo-!", IMAPUtils::toModifiedUTF7('/', FC("Hi Mum \xe2\x98\xba!"))); + VASSERT_EQ("3", "&ZeVnLIqe-", IMAPUtils::toModifiedUTF7('/', FC("\xe6\x97\xa5\xe6\x9c\xac\xe8\xaa\x9e"))); + VASSERT_EQ("4", "Item 3 is &AKM- 1.", IMAPUtils::toModifiedUTF7('/', FC("Item 3 is \xc2\xa3 1."))); + + VASSERT_EQ("escape char", "&-", IMAPUtils::toModifiedUTF7('/', FC("&"))); + VASSERT_EQ("ascii", "plain ascii text", IMAPUtils::toModifiedUTF7('/', FC("plain ascii text"))); + VASSERT_EQ("special", "!\"#$%*+-;<=>@[]^_`{|}", IMAPUtils::toModifiedUTF7('/', FC("!\"#$%*+-;<=>@[]^_`{|}"))); + + #undef FC + } + + void testFromModifiedUTF7() { + + #define FC(x) vmime::net::folder::path::component(x, vmime::charsets::UTF_8) + + // Example strings from RFC-1642 (modified for IMAP UTF-7) + VASSERT_EQ("1", FC("A\xe2\x89\xa2\xce\x91."), IMAPUtils::fromModifiedUTF7("A&ImIDkQ-.")); + VASSERT_EQ("2", FC("Hi Mum \xe2\x98\xba!"), IMAPUtils::fromModifiedUTF7("Hi Mum &Jjo-!")); + VASSERT_EQ("3", FC("\xe6\x97\xa5\xe6\x9c\xac\xe8\xaa\x9e"), IMAPUtils::fromModifiedUTF7("&ZeVnLIqe-")); + VASSERT_EQ("4", FC("Item 3 is \xc2\xa3 1."), IMAPUtils::fromModifiedUTF7("Item 3 is &AKM- 1.")); + + VASSERT_EQ("escape char", FC("&"), IMAPUtils::fromModifiedUTF7("&-")); + VASSERT_EQ("ascii", FC("plain ascii text"), IMAPUtils::fromModifiedUTF7("plain ascii text")); + VASSERT_EQ("special", FC("!\"#$%*+;<=>@[]^_`{|}"), IMAPUtils::fromModifiedUTF7("!\"#$%*+-;<=>@[]^_`{|}")); + + #undef FC + } + + void testConvertAddressList() { + + IMAPParser parser; + IMAPParser::address_list addrList; + + vmime::string line("((\"name\" NIL \"mailbox\" \"host\")(\"name2\" NIL \"mailbox2\" \"host2\"))"); + vmime::size_t pos = 0; + + VASSERT("parse", addrList.parseImpl(parser, line, &pos)); + + vmime::mailboxList mboxList; + IMAPUtils::convertAddressList(addrList, mboxList); + + VASSERT_EQ("mbox-count", 2, mboxList.getMailboxCount()); + VASSERT_EQ("mbox-1", "mailbox@host", mboxList.getMailboxAt(0)->getEmail().toString()); + VASSERT_EQ("mbox-1", "name", mboxList.getMailboxAt(0)->getName().getWholeBuffer()); + VASSERT_EQ("mbox-2", "mailbox2@host2", mboxList.getMailboxAt(1)->getEmail().toString()); + VASSERT_EQ("mbox-2", "name2", mboxList.getMailboxAt(1)->getName().getWholeBuffer()); + } + + void testMessageFlagList() { + + int flags = 0; + std::vector <vmime::string> flagList; + + // Test each flag + flags = vmime::net::message::FLAG_REPLIED; + flagList = IMAPUtils::messageFlagList(flags); + VASSERT("replied", std::find(flagList.begin(), flagList.end(), "\\Answered") != flagList.end()); + + flags = vmime::net::message::FLAG_MARKED; + flagList = IMAPUtils::messageFlagList(flags); + VASSERT("marked", std::find(flagList.begin(), flagList.end(), "\\Flagged") != flagList.end()); + + flags = vmime::net::message::FLAG_DELETED; + flagList = IMAPUtils::messageFlagList(flags); + VASSERT("deleted", std::find(flagList.begin(), flagList.end(), "\\Deleted") != flagList.end()); + + flags = vmime::net::message::FLAG_SEEN; + flagList = IMAPUtils::messageFlagList(flags); + VASSERT("seen", std::find(flagList.begin(), flagList.end(), "\\Seen") != flagList.end()); + + flags = vmime::net::message::FLAG_DRAFT; + flagList = IMAPUtils::messageFlagList(flags); + VASSERT("draft", std::find(flagList.begin(), flagList.end(), "\\Draft") != flagList.end()); + + // Multiple flags + flags = vmime::net::message::FLAG_REPLIED; + flagList = IMAPUtils::messageFlagList(flags); + + VASSERT_EQ("1.size", 1, flagList.size()); + VASSERT("1.found", std::find(flagList.begin(), flagList.end(), "\\Answered") != flagList.end()); + + flags |= vmime::net::message::FLAG_SEEN; + flagList = IMAPUtils::messageFlagList(flags); + + VASSERT_EQ("2.size", 2, flagList.size()); + VASSERT("2.found1", std::find(flagList.begin(), flagList.end(), "\\Answered") != flagList.end()); + VASSERT("2.found2", std::find(flagList.begin(), flagList.end(), "\\Seen") != flagList.end()); + } + + void testDateTime() { + + vmime::datetime dt(2014, 3, 17, 23, 26, 22, vmime::datetime::GMT2); + VASSERT_EQ("datetime", "\"17-Mar-2014 23:26:22 +0200\"", IMAPUtils::dateTime(dt)); + } + + void testPathToString() { + + #define FC(x) vmime::net::folder::path::component(x, vmime::charsets::UTF_8) + + vmime::net::folder::path path; + path /= FC("Hi Mum \xe2\x98\xba!"); + path /= FC("\xe6\x97\xa5\xe6\x9c\xac\xe8\xaa\x9e"); + + VASSERT_EQ("string", "Hi Mum &Jjo-!/&ZeVnLIqe-", IMAPUtils::pathToString('/', path)); + + #undef FC + } + + void testStringToPath() { + + #define FC(x) vmime::net::folder::path::component(x, vmime::charsets::UTF_8) + + vmime::net::folder::path path = IMAPUtils::stringToPath('/', "Hi Mum &Jjo-!/&ZeVnLIqe-"); + + VASSERT_EQ("count", 2, path.getSize()); + VASSERT_EQ("component1", FC("Hi Mum \xe2\x98\xba!"), path[0]); + VASSERT_EQ("component2", FC("\xe6\x97\xa5\xe6\x9c\xac\xe8\xaa\x9e"), path[1]); + + #undef FC + } + + void testBuildFetchCommand() { + + vmime::shared_ptr <IMAPConnection> cnt; + vmime::net::messageSet msgs = vmime::net::messageSet::byNumber(42); + + // SIZE + { + vmime::net::fetchAttributes attribs = vmime::net::fetchAttributes::SIZE; + + vmime::shared_ptr <IMAPCommand> cmd = IMAPUtils::buildFetchCommand(cnt, msgs, attribs); + VASSERT_EQ("size", "FETCH 42 RFC822.SIZE", cmd->getText()); + } + + // FLAGS + { + vmime::net::fetchAttributes attribs = vmime::net::fetchAttributes::FLAGS; + + vmime::shared_ptr <IMAPCommand> cmd = IMAPUtils::buildFetchCommand(cnt, msgs, attribs); + VASSERT_EQ("flags", "FETCH 42 FLAGS", cmd->getText()); + } + + // STRUCTURE + { + vmime::net::fetchAttributes attribs = vmime::net::fetchAttributes::STRUCTURE; + + vmime::shared_ptr <IMAPCommand> cmd = IMAPUtils::buildFetchCommand(cnt, msgs, attribs); + VASSERT_EQ("structure", "FETCH 42 BODYSTRUCTURE", cmd->getText()); + } + + // UID + { + vmime::net::fetchAttributes attribs = vmime::net::fetchAttributes::UID; + + vmime::shared_ptr <IMAPCommand> cmd = IMAPUtils::buildFetchCommand(cnt, msgs, attribs); + VASSERT_EQ("uid", "FETCH 42 UID", cmd->getText()); + } + + // ENVELOPE + { + vmime::net::fetchAttributes attribs = vmime::net::fetchAttributes::ENVELOPE; + + vmime::shared_ptr <IMAPCommand> cmd = IMAPUtils::buildFetchCommand(cnt, msgs, attribs); + VASSERT_EQ("envelope", "FETCH 42 ENVELOPE", cmd->getText()); + } + + // CONTENT_INFO + { + vmime::net::fetchAttributes attribs = vmime::net::fetchAttributes::CONTENT_INFO; + + vmime::shared_ptr <IMAPCommand> cmd = IMAPUtils::buildFetchCommand(cnt, msgs, attribs); + VASSERT_EQ("content", "FETCH 42 BODY[HEADER.FIELDS (CONTENT_TYPE)]", cmd->getText()); + } + + // IMPORTANCE + { + vmime::net::fetchAttributes attribs = vmime::net::fetchAttributes::IMPORTANCE; + + vmime::shared_ptr <IMAPCommand> cmd = IMAPUtils::buildFetchCommand(cnt, msgs, attribs); + VASSERT_EQ("importance", "FETCH 42 BODY[HEADER.FIELDS (IMPORTANCE X-PRIORITY)]", cmd->getText()); + } + + // Any header attribute + full header should give RFC822.HEADER + { + vmime::net::fetchAttributes attribs; + attribs.add(vmime::net::fetchAttributes::ENVELOPE); + attribs.add(vmime::net::fetchAttributes::FULL_HEADER); + + vmime::shared_ptr <IMAPCommand> cmd = IMAPUtils::buildFetchCommand(cnt, msgs, attribs); + VASSERT_EQ("full-header", "FETCH 42 RFC822.HEADER", cmd->getText()); + } + + // Test custom header + { + vmime::net::fetchAttributes attribs; + attribs.add("X-MyHeader"); + + vmime::shared_ptr <IMAPCommand> cmd = IMAPUtils::buildFetchCommand(cnt, msgs, attribs); + VASSERT_EQ("custom-header", "FETCH 42 BODY[HEADER.FIELDS (x-myheader)]", cmd->getText()); + } + + // Test multiple flags + { + vmime::net::fetchAttributes attribs = + vmime::net::fetchAttributes::UID | vmime::net::fetchAttributes::FLAGS; + + vmime::shared_ptr <IMAPCommand> cmd = IMAPUtils::buildFetchCommand(cnt, msgs, attribs); + VASSERT_EQ("multiple", "FETCH 42 (FLAGS UID)", cmd->getText()); + } + } + +VMIME_TEST_SUITE_END |