IMAP commands.

This commit is contained in:
Vincent Richard 2014-03-15 23:33:20 +01:00
parent 86788ce022
commit 9d73fc5382
11 changed files with 1189 additions and 266 deletions

View File

@ -0,0 +1,410 @@
//
// VMime library (http://www.vmime.org)
// Copyright (C) 2002-2014 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 "vmime/config.hpp"
#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_IMAP
#include "vmime/net/imap/IMAPCommand.hpp"
#include "vmime/net/imap/IMAPConnection.hpp"
#include "vmime/net/imap/IMAPUtils.hpp"
#include <sstream>
namespace vmime {
namespace net {
namespace imap {
IMAPCommand::IMAPCommand(const string& text, const string& traceText)
: m_text(text), m_traceText(traceText)
{
}
// static
shared_ptr <IMAPCommand> IMAPCommand::LOGIN(const string& username, const string& password)
{
std::ostringstream cmd;
cmd.imbue(std::locale::classic());
cmd << "LOGIN " << IMAPUtils::quoteString(username)
<< " " << IMAPUtils::quoteString(password);
std::ostringstream trace;
trace.imbue(std::locale::classic());
trace << "LOGIN <username> <password>";
return createCommand(cmd.str(), trace.str());
}
// static
shared_ptr <IMAPCommand> IMAPCommand::AUTHENTICATE(const string& mechName)
{
std::ostringstream cmd;
cmd.imbue(std::locale::classic());
cmd << "AUTHENTICATE " << mechName;
return createCommand(cmd.str());
}
// static
shared_ptr <IMAPCommand> IMAPCommand::AUTHENTICATE(const string& mechName, const string& initialResponse)
{
std::ostringstream cmd;
cmd.imbue(std::locale::classic());
cmd << "AUTHENTICATE " << mechName << " " << initialResponse;
return createCommand(cmd.str());
}
// static
shared_ptr <IMAPCommand> IMAPCommand::LIST(const string& refName, const string& mailboxName)
{
std::ostringstream cmd;
cmd.imbue(std::locale::classic());
cmd << "LIST " << IMAPUtils::quoteString(refName)
<< " " << IMAPUtils::quoteString(mailboxName);
return createCommand(cmd.str());
}
// static
shared_ptr <IMAPCommand> IMAPCommand::SELECT
(const bool readOnly, const string& mailboxName, const std::vector <string>& params)
{
std::ostringstream cmd;
cmd.imbue(std::locale::classic());
if (readOnly)
cmd << "EXAMINE ";
else
cmd << "SELECT ";
cmd << IMAPUtils::quoteString(mailboxName);
if (!params.empty())
{
cmd << " (";
for (size_t i = 0, n = params.size() ; i < n ; ++i)
{
if (i != 0) cmd << " ";
cmd << params[i];
}
cmd << ")";
}
return createCommand(cmd.str());
}
// static
shared_ptr <IMAPCommand> IMAPCommand::STATUS
(const string& mailboxName, const std::vector <string>& attribs)
{
std::ostringstream cmd;
cmd.imbue(std::locale::classic());
cmd << "STATUS " << IMAPUtils::quoteString(mailboxName);
cmd << " (";
for (size_t i = 0, n = attribs.size() ; i < n ; ++i)
{
if (i != 0) cmd << " ";
cmd << attribs[i];
}
cmd << ")";
return createCommand(cmd.str());
}
// static
shared_ptr <IMAPCommand> IMAPCommand::CREATE
(const string& mailboxName, const std::vector <string>& params)
{
std::ostringstream cmd;
cmd.imbue(std::locale::classic());
cmd << "CREATE " << IMAPUtils::quoteString(mailboxName);
if (!params.empty())
{
cmd << " (";
for (size_t i = 0, n = params.size() ; i < n ; ++i)
{
if (i != 0) cmd << " ";
cmd << params[i];
}
cmd << ")";
}
return createCommand(cmd.str());
}
// static
shared_ptr <IMAPCommand> IMAPCommand::DELETE(const string& mailboxName)
{
std::ostringstream cmd;
cmd.imbue(std::locale::classic());
cmd << "DELETE " << IMAPUtils::quoteString(mailboxName);
return createCommand(cmd.str());
}
// static
shared_ptr <IMAPCommand> IMAPCommand::RENAME
(const string& mailboxName, const string& newMailboxName)
{
std::ostringstream cmd;
cmd.imbue(std::locale::classic());
cmd << "RENAME " << IMAPUtils::quoteString(mailboxName)
<< " " << IMAPUtils::quoteString(newMailboxName);
return createCommand(cmd.str());
}
// static
shared_ptr <IMAPCommand> IMAPCommand::FETCH
(const messageSet& msgs, const std::vector <string>& params)
{
std::ostringstream cmd;
cmd.imbue(std::locale::classic());
if (msgs.isUIDSet())
cmd << "UID FETCH " << IMAPUtils::messageSetToSequenceSet(msgs);
else
cmd << "FETCH " << IMAPUtils::messageSetToSequenceSet(msgs);
if (params.size() == 1)
{
cmd << " " << params[0];
}
else
{
cmd << " (";
for (size_t i = 0, n = params.size() ; i < n ; ++i)
{
if (i != 0) cmd << " ";
cmd << params[i];
}
cmd << ")";
}
return createCommand(cmd.str());
}
// static
shared_ptr <IMAPCommand> IMAPCommand::STORE
(const messageSet& msgs, const int mode, const std::vector <string>& flags)
{
std::ostringstream cmd;
cmd.imbue(std::locale::classic());
if (msgs.isUIDSet())
cmd << "UID STORE " << IMAPUtils::messageSetToSequenceSet(msgs);
else
cmd << "STORE " << IMAPUtils::messageSetToSequenceSet(msgs);
if (mode == message::FLAG_MODE_ADD)
cmd << " +FLAGS ";
else if (mode == message::FLAG_MODE_REMOVE)
cmd << " -FLAGS ";
else // if (mode == message::FLAG_MODE_SET)
cmd << " FLAGS ";
cmd << "(";
for (size_t i = 0, n = flags.size() ; i < n ; ++i)
{
if (i != 0) cmd << " ";
cmd << flags[i];
}
cmd << ")";
return createCommand(cmd.str());
}
// static
shared_ptr <IMAPCommand> IMAPCommand::APPEND
(const string& mailboxName, const std::vector <string>& flags,
vmime::datetime* date, const size_t size)
{
std::ostringstream cmd;
cmd.imbue(std::locale::classic());
cmd << "APPEND " << IMAPUtils::quoteString(mailboxName);
if (!flags.empty())
{
cmd << " (";
for (size_t i = 0, n = flags.size() ; i < n ; ++i)
{
if (i != 0) cmd << " ";
cmd << flags[i];
}
cmd << ")";
}
if (date != NULL)
cmd << " " << IMAPUtils::dateTime(*date);
cmd << " {" << size << "}";
return createCommand(cmd.str());
}
// static
shared_ptr <IMAPCommand> IMAPCommand::COPY
(const messageSet& msgs, const string& mailboxName)
{
std::ostringstream cmd;
cmd.imbue(std::locale::classic());
if (msgs.isUIDSet())
cmd << "UID COPY " << IMAPUtils::messageSetToSequenceSet(msgs);
else
cmd << "COPY " << IMAPUtils::messageSetToSequenceSet(msgs);
cmd << " " << IMAPUtils::quoteString(mailboxName);
return createCommand(cmd.str());
}
// static
shared_ptr <IMAPCommand> IMAPCommand::SEARCH
(const std::vector <string>& keys, const vmime::charset* charset)
{
std::ostringstream cmd;
cmd.imbue(std::locale::classic());
cmd << "SEARCH";
if (charset)
cmd << " CHARSET " << charset->getName();
for (size_t i = 0, n = keys.size() ; i < n ; ++i)
cmd << " " << keys[i];
return createCommand(cmd.str());
}
// static
shared_ptr <IMAPCommand> IMAPCommand::STARTTLS()
{
return createCommand("STARTTLS");
}
// static
shared_ptr <IMAPCommand> IMAPCommand::CAPABILITY()
{
return createCommand("CAPABILITY");
}
// static
shared_ptr <IMAPCommand> IMAPCommand::NOOP()
{
return createCommand("NOOP");
}
// static
shared_ptr <IMAPCommand> IMAPCommand::EXPUNGE()
{
return createCommand("EXPUNGE");
}
// static
shared_ptr <IMAPCommand> IMAPCommand::CLOSE()
{
return createCommand("CLOSE");
}
// static
shared_ptr <IMAPCommand> IMAPCommand::LOGOUT()
{
return createCommand("LOGOUT");
}
// static
shared_ptr <IMAPCommand> IMAPCommand::createCommand
(const string& text, const string& traceText)
{
if (traceText.empty())
return shared_ptr <IMAPCommand>(new IMAPCommand(text, text));
else
return shared_ptr <IMAPCommand>(new IMAPCommand(text, traceText));
}
const string IMAPCommand::getText() const
{
return m_text;
}
const string IMAPCommand::getTraceText() const
{
return m_traceText;
}
void IMAPCommand::send(shared_ptr <IMAPConnection> conn)
{
conn->sendCommand(dynamicCast <IMAPCommand>(shared_from_this()));
}
} // imap
} // net
} // vmime
#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_IMAP

View File

@ -0,0 +1,124 @@
//
// VMime library (http://www.vmime.org)
// Copyright (C) 2002-2014 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.
//
#ifndef VMIME_NET_IMAP_IMAPCOMMAND_HPP_INCLUDED
#define VMIME_NET_IMAP_IMAPCOMMAND_HPP_INCLUDED
#include "vmime/config.hpp"
#if VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_IMAP
#include "vmime/object.hpp"
#include "vmime/base.hpp"
#include "vmime/datetime.hpp"
#include "vmime/net/messageSet.hpp"
namespace vmime {
namespace net {
namespace imap {
class IMAPConnection;
/** An IMAP command that will be sent to the server.
*/
class VMIME_EXPORT IMAPCommand : public object
{
public:
static shared_ptr <IMAPCommand> LOGIN(const string& username, const string& password);
static shared_ptr <IMAPCommand> AUTHENTICATE(const string& mechName);
static shared_ptr <IMAPCommand> AUTHENTICATE(const string& mechName, const string& initialResponse);
static shared_ptr <IMAPCommand> LIST(const string& refName, const string& mailboxName);
static shared_ptr <IMAPCommand> SELECT(const bool readOnly, const string& mailboxName, const std::vector <string>& params);
static shared_ptr <IMAPCommand> STATUS(const string& mailboxName, const std::vector <string>& attribs);
static shared_ptr <IMAPCommand> CREATE(const string& mailboxName, const std::vector <string>& params);
static shared_ptr <IMAPCommand> DELETE(const string& mailboxName);
static shared_ptr <IMAPCommand> RENAME(const string& mailboxName, const string& newMailboxName);
static shared_ptr <IMAPCommand> FETCH(const messageSet& msgs, const std::vector <string>& params);
static shared_ptr <IMAPCommand> STORE(const messageSet& msgs, const int mode, const std::vector <string>& flags);
static shared_ptr <IMAPCommand> APPEND(const string& mailboxName, const std::vector <string>& flags, vmime::datetime* date, const size_t size);
static shared_ptr <IMAPCommand> COPY(const messageSet& msgs, const string& mailboxName);
static shared_ptr <IMAPCommand> SEARCH(const std::vector <string>& keys, const vmime::charset* charset);
static shared_ptr <IMAPCommand> STARTTLS();
static shared_ptr <IMAPCommand> CAPABILITY();
static shared_ptr <IMAPCommand> NOOP();
static shared_ptr <IMAPCommand> EXPUNGE();
static shared_ptr <IMAPCommand> CLOSE();
static shared_ptr <IMAPCommand> LOGOUT();
/** Creates a new IMAP command with the specified text.
*
* @param text command text
* @param traceText trace text (if empty, command text is used)
* @return a new IMAPCommand object
*/
static shared_ptr <IMAPCommand> createCommand(const string& text, const string& traceText = "");
/** Sends this command over the specified connection.
*
* @param conn connection onto which the command will be sent
*/
virtual void send(shared_ptr <IMAPConnection> conn);
/** Returns the full text of the command, including command name
* and parameters (if any). This is the text that will be sent
* to the server.
*
* @return command text (eg. "LOGIN myusername mypassword")
*/
virtual const string getText() const;
/** Returns the full text of the command, suitable for outputing
* to the tracer.
*
* @return trace text (eg. "LOGIN myusername ***")
*/
virtual const string getTraceText() const;
protected:
IMAPCommand(const string& text, const string& traceText);
IMAPCommand(const IMAPCommand&);
private:
string m_text;
string m_traceText;
};
} // imap
} // net
} // vmime
#endif // VMIME_HAVE_MESSAGING_FEATURES && VMIME_HAVE_MESSAGING_PROTO_IMAP
#endif // VMIME_NET_IMAP_IMAPCOMMAND_HPP_INCLUDED

View File

@ -31,6 +31,7 @@
#include "vmime/net/imap/IMAPConnection.hpp"
#include "vmime/net/imap/IMAPUtils.hpp"
#include "vmime/net/imap/IMAPStore.hpp"
#include "vmime/net/imap/IMAPCommand.hpp"
#include "vmime/exception.hpp"
#include "vmime/platform.hpp"
@ -70,6 +71,7 @@ IMAPConnection::IMAPConnection(shared_ptr <IMAPStore> store, shared_ptr <securit
m_hierarchySeparator('\0'), m_state(STATE_NONE), m_timeoutHandler(null),
m_secured(false), m_firstTag(true), m_capabilitiesFetched(false), m_noModSeq(false)
{
m_tag = make_shared <IMAPTag>();
}
@ -133,7 +135,6 @@ void IMAPConnection::connect()
m_socket->connect(address, port);
m_tag = make_shared <IMAPTag>();
m_parser = make_shared <IMAPParser>(m_tag, m_socket, m_timeoutHandler);
@ -259,8 +260,8 @@ void IMAPConnection::authenticate()
const string username = getAuthenticator()->getUsername();
const string password = getAuthenticator()->getPassword();
send(true, "LOGIN " + IMAPUtils::quoteString(username)
+ " " + IMAPUtils::quoteString(password), true);
shared_ptr <IMAPConnection> conn = dynamicCast <IMAPConnection>(shared_from_this());
IMAPCommand::LOGIN(username, password)->send(conn);
std::auto_ptr <IMAPParser::response> resp(m_parser->readResponse());
@ -355,8 +356,7 @@ void IMAPConnection::authenticateSASL()
saslSession->init();
std::ostringstream cmd;
cmd << "AUTHENTICATE " << mech->getName();
shared_ptr <IMAPCommand> authCmd;
if (saslSession->getMechanism()->hasInitialResponse())
{
@ -369,12 +369,16 @@ void IMAPConnection::authenticateSASL()
delete [] initialResp;
if (encodedInitialResp.empty())
cmd << " =";
authCmd = IMAPCommand::AUTHENTICATE(mech->getName(), "=");
else
cmd << " " << encodedInitialResp;
authCmd = IMAPCommand::AUTHENTICATE(mech->getName(), encodedInitialResp);
}
else
{
authCmd = IMAPCommand::AUTHENTICATE(mech->getName());
}
send(true, cmd.str(), true);
authCmd->send(dynamicCast <IMAPConnection>(shared_from_this()));
for (bool cont = true ; cont ; )
{
@ -428,7 +432,8 @@ void IMAPConnection::authenticateSASL()
(challenge, challengeLen, &resp, &respLen);
// Send response
send(false, saslContext->encodeB64(resp, respLen), true);
const string respB64 = saslContext->encodeB64(resp, respLen) + "\r\n";
sendRaw(utility::stringUtils::bytesFromString(respB64), respB64.length());
// Server capabilities may change when logged in
invalidateCapabilities();
@ -448,7 +453,7 @@ void IMAPConnection::authenticateSASL()
}
// Cancel SASL exchange
send(false, "*", true);
sendRaw(utility::stringUtils::bytesFromString("*\r\n"), 3);
}
catch (...)
{
@ -483,7 +488,7 @@ void IMAPConnection::startTLS()
{
try
{
send(true, "STARTTLS", true);
IMAPCommand::STARTTLS()->send(dynamicCast <IMAPConnection>(shared_from_this()));
std::auto_ptr <IMAPParser::response> resp(m_parser->readResponse());
@ -582,7 +587,7 @@ void IMAPConnection::invalidateCapabilities()
void IMAPConnection::fetchCapabilities()
{
send(true, "CAPABILITY", true);
IMAPCommand::CAPABILITY()->send(dynamicCast <IMAPConnection>(shared_from_this()));
std::auto_ptr <IMAPParser::response> resp(m_parser->readResponse());
@ -675,7 +680,7 @@ void IMAPConnection::internalDisconnect()
{
if (isConnected())
{
send(true, "LOGOUT", true);
IMAPCommand::LOGOUT()->send(dynamicCast <IMAPConnection>(shared_from_this()));
m_socket->disconnect();
m_socket = null;
@ -692,7 +697,7 @@ void IMAPConnection::internalDisconnect()
void IMAPConnection::initHierarchySeparator()
{
send(true, "LIST \"\" \"\"", true);
IMAPCommand::LIST("", "")->send(dynamicCast <IMAPConnection>(shared_from_this()));
std::auto_ptr <IMAPParser::response> resp(m_parser->readResponse());
@ -732,42 +737,16 @@ void IMAPConnection::initHierarchySeparator()
}
void IMAPConnection::send(bool tag, const string& what, bool end)
void IMAPConnection::sendCommand(shared_ptr <IMAPCommand> cmd)
{
if (tag && !m_firstTag)
if (!m_firstTag)
++(*m_tag);
#if VMIME_DEBUG
std::ostringstream oss;
if (tag)
{
oss << string(*m_tag);
oss << " ";
}
oss << what;
if (end)
oss << "\r\n";
m_socket->send(oss.str());
#else
if (tag)
{
m_socket->send(*m_tag);
m_socket->send(" ");
}
m_socket->send(what);
if (end)
{
m_socket->send(cmd->getText());
m_socket->send("\r\n");
}
#endif
if (tag)
m_firstTag = false;
}
@ -826,6 +805,18 @@ shared_ptr <const socket> IMAPConnection::getSocket() const
}
void IMAPConnection::setSocket(shared_ptr <socket> sok)
{
m_socket = sok;
}
shared_ptr <IMAPTag> IMAPConnection::getTag()
{
return m_tag;
}
bool IMAPConnection::isMODSEQDisabled() const
{
return m_noModSeq;

View File

@ -48,6 +48,7 @@ namespace imap {
class IMAPTag;
class IMAPStore;
class IMAPCommand;
class VMIME_EXPORT IMAPConnection : public object
@ -79,7 +80,7 @@ public:
char hierarchySeparator() const;
void send(bool tag, const string& what, bool end);
void sendCommand(shared_ptr <IMAPCommand> cmd);
void sendRaw(const byte_t* buffer, const size_t count);
IMAPParser::response* readResponse(IMAPParser::literalHandler* lh = NULL);
@ -102,6 +103,9 @@ public:
shared_ptr <connectionInfos> getConnectionInfos() const;
shared_ptr <const socket> getSocket() const;
void setSocket(shared_ptr <socket> sok);
shared_ptr <IMAPTag> getTag();
bool isMODSEQDisabled() const;
void disableMODSEQ();

View File

@ -35,6 +35,7 @@
#include "vmime/net/imap/IMAPUtils.hpp"
#include "vmime/net/imap/IMAPConnection.hpp"
#include "vmime/net/imap/IMAPFolderStatus.hpp"
#include "vmime/net/imap/IMAPCommand.hpp"
#include "vmime/message.hpp"
@ -157,20 +158,16 @@ void IMAPFolder::open(const int mode, bool failIfModeIsNotAvailable)
// S: * OK [PERMANENTFLAGS (\Deleted \Seen \*)] Limited
// S: A142 OK [READ-WRITE] SELECT completed
std::ostringstream oss;
if (mode == MODE_READ_ONLY)
oss << "EXAMINE ";
else
oss << "SELECT ";
oss << IMAPUtils::quoteString(IMAPUtils::pathToString
(connection->hierarchySeparator(), getFullPath()));
std::vector <string> selectParams;
if (m_connection->hasCapability("CONDSTORE"))
oss << " (CONDSTORE)";
selectParams.push_back("CONDSTORE");
connection->send(true, oss.str(), true);
IMAPCommand::SELECT(
mode == MODE_READ_ONLY,
IMAPUtils::pathToString(connection->hierarchySeparator(), getFullPath()),
selectParams
)->send(connection);
// Read the response
std::auto_ptr <IMAPParser::response> resp(connection->readResponse());
@ -289,7 +286,7 @@ void IMAPFolder::close(const bool expunge)
if (m_mode == MODE_READ_ONLY)
throw exceptions::operation_not_supported();
oldConnection->send(true, "CLOSE", true);
IMAPCommand::CLOSE()->send(oldConnection);
}
// Close this folder connection
@ -345,8 +342,7 @@ void IMAPFolder::create(const folderAttributes& attribs)
if (attribs.getType() & folderAttributes::TYPE_CONTAINS_FOLDERS)
mailbox += m_connection->hierarchySeparator();
std::ostringstream oss;
oss << "CREATE " << IMAPUtils::quoteString(mailbox);
std::vector <string> createParams;
if (attribs.getSpecialUse() != folderAttributes::SPECIALUSE_NONE)
{
@ -354,7 +350,8 @@ void IMAPFolder::create(const folderAttributes& attribs)
throw exceptions::operation_not_supported();
// C: t2 CREATE MySpecial (USE (\Drafts \Sent))
oss << "(USE (";
std::ostringstream oss;
oss << "USE (";
switch (attribs.getSpecialUse())
{
@ -369,10 +366,12 @@ void IMAPFolder::create(const folderAttributes& attribs)
case folderAttributes::SPECIALUSE_IMPORTANT: oss << "\\Important"; break;
}
oss << "))";
oss << ")";
createParams.push_back(oss.str());
}
m_connection->send(true, oss.str(), true);
IMAPCommand::CREATE(mailbox, createParams)->send(m_connection);
std::auto_ptr <IMAPParser::response> resp(m_connection->readResponse());
@ -407,10 +406,7 @@ void IMAPFolder::destroy()
const string mailbox = IMAPUtils::pathToString
(m_connection->hierarchySeparator(), getFullPath());
std::ostringstream oss;
oss << "DELETE " << IMAPUtils::quoteString(mailbox);
m_connection->send(true, oss.str(), true);
IMAPCommand::DELETE(mailbox)->send(m_connection);
std::auto_ptr <IMAPParser::response> resp(m_connection->readResponse());
@ -464,12 +460,8 @@ int IMAPFolder::testExistAndGetType()
//
// ==> NO, does not exist
std::ostringstream oss;
oss << "LIST \"\" ";
oss << IMAPUtils::quoteString(IMAPUtils::pathToString
(m_connection->hierarchySeparator(), getFullPath()));
m_connection->send(true, oss.str(), true);
IMAPCommand::LIST("", IMAPUtils::pathToString
(m_connection->hierarchySeparator(), getFullPath()))->send(m_connection);
std::auto_ptr <IMAPParser::response> resp(m_connection->readResponse());
@ -560,14 +552,10 @@ std::vector <shared_ptr <message> > IMAPFolder::getMessages(const messageSet& ms
// S: * nnnn3 FETCH (UID uuuu3)
// S: . OK UID FETCH completed
// Prepare command and arguments
std::ostringstream cmd;
cmd.imbue(std::locale::classic());
std::vector <string> params;
params.push_back("UID");
cmd << "UID FETCH " << IMAPUtils::messageSetToSequenceSet(msgs) << " UID";
// Send the request
m_connection->send(true, cmd.str(), true);
IMAPCommand::FETCH(msgs, params)->send(m_connection);
// Get the response
std::auto_ptr <IMAPParser::response> resp(m_connection->readResponse());
@ -679,28 +667,22 @@ std::vector <shared_ptr <folder> > IMAPFolder::getFolders(const bool recursive)
// S: * LIST (\NoInferiors) "/" foo/bar/zap
// S: a005 OK LIST completed
std::ostringstream oss;
oss << "LIST ";
shared_ptr <IMAPCommand> cmd;
const string pathString = IMAPUtils::pathToString
(m_connection->hierarchySeparator(), getFullPath());
if (recursive)
{
oss << IMAPUtils::quoteString(pathString);
oss << " *";
cmd = IMAPCommand::LIST(pathString, "*");
}
else
{
if (pathString.empty()) // don't add sep for root folder
oss << "\"\"";
else
oss << IMAPUtils::quoteString(pathString + m_connection->hierarchySeparator());
oss << " %";
cmd = IMAPCommand::LIST
(pathString.empty() ? "" : (pathString + m_connection->hierarchySeparator()), "%");
}
m_connection->send(true, oss.str(), true);
cmd->send(m_connection);
std::auto_ptr <IMAPParser::response> resp(m_connection->readResponse());
@ -783,10 +765,8 @@ void IMAPFolder::fetchMessages(std::vector <shared_ptr <message> >& msg, const f
}
// Send the request
const string command = IMAPUtils::buildFetchRequest
(m_connection, messageSet::byNumber(list), options);
m_connection->send(true, command, true);
IMAPUtils::buildFetchCommand
(m_connection, messageSet::byNumber(list), options)->send(m_connection);
// Get the response
std::auto_ptr <IMAPParser::response> resp(m_connection->readResponse());
@ -881,10 +861,8 @@ std::vector <shared_ptr <message> > IMAPFolder::getAndFetchMessages
attribsWithUID.add(fetchAttributes::UID);
// Send the request
const string command = IMAPUtils::buildFetchRequest
(m_connection, msgs, attribsWithUID);
m_connection->send(true, command, true);
IMAPUtils::buildFetchCommand
(m_connection, msgs, attribsWithUID)->send(m_connection);
// Get the response
std::auto_ptr <IMAPParser::response> resp(m_connection->readResponse());
@ -1016,19 +994,11 @@ void IMAPFolder::deleteMessages(const messageSet& msgs)
else if (m_mode == MODE_READ_ONLY)
throw exceptions::illegal_state("Folder is read-only");
// Build the request text
std::ostringstream command;
command.imbue(std::locale::classic());
if (msgs.isUIDSet())
command << "UID STORE " << IMAPUtils::messageSetToSequenceSet(msgs);
else
command << "STORE " << IMAPUtils::messageSetToSequenceSet(msgs);
command << " +FLAGS (\\Deleted)";
// Send the request
m_connection->send(true, command.str(), true);
IMAPCommand::STORE(
msgs, message::FLAG_MODE_ADD,
IMAPUtils::messageFlagList(message::FLAG_DELETED)
)->send(m_connection);
// Get the response
std::auto_ptr <IMAPParser::response> resp(m_connection->readResponse());
@ -1046,31 +1016,12 @@ void IMAPFolder::deleteMessages(const messageSet& msgs)
void IMAPFolder::setMessageFlags(const messageSet& msgs, const int flags, const int mode)
{
// Build the request text
std::ostringstream command;
command.imbue(std::locale::classic());
if (msgs.isUIDSet())
command << "UID STORE " << IMAPUtils::messageSetToSequenceSet(msgs);
else
command << "STORE " << IMAPUtils::messageSetToSequenceSet(msgs);
switch (mode)
{
case message::FLAG_MODE_ADD: command << " +FLAGS "; break;
case message::FLAG_MODE_REMOVE: command << " -FLAGS "; break;
default:
case message::FLAG_MODE_SET: command << " FLAGS "; break;
}
const string flagList = IMAPUtils::messageFlagList(flags);
const std::vector <string> flagList = IMAPUtils::messageFlagList(flags);
if (!flagList.empty())
{
command << flagList;
// Send the request
m_connection->send(true, command.str(), true);
IMAPCommand::STORE(msgs, mode, flagList)->send(m_connection);
// Get the response
std::auto_ptr <IMAPParser::response> resp(m_connection->readResponse());
@ -1116,31 +1067,11 @@ messageSet IMAPFolder::addMessage
else if (m_mode == MODE_READ_ONLY)
throw exceptions::illegal_state("Folder is read-only");
// Build the request text
std::ostringstream command;
command.imbue(std::locale::classic());
command << "APPEND " << IMAPUtils::quoteString(IMAPUtils::pathToString
(m_connection->hierarchySeparator(), getFullPath())) << ' ';
const string flagList = IMAPUtils::messageFlagList(flags);
if (flags != -1 && !flagList.empty())
{
command << flagList;
command << ' ';
}
if (date != NULL)
{
command << IMAPUtils::dateTime(*date);
command << ' ';
}
command << '{' << size << '}';
// Send the request
m_connection->send(true, command.str(), true);
IMAPCommand::APPEND(
IMAPUtils::pathToString(m_connection->hierarchySeparator(), getFullPath()),
IMAPUtils::messageFlagList(flags), date, size
)->send(m_connection);
// Get the response
std::auto_ptr <IMAPParser::response> resp(m_connection->readResponse());
@ -1191,7 +1122,7 @@ messageSet IMAPFolder::addMessage
progress->progress(current, total);
}
m_connection->send(false, "", true);
m_connection->sendRaw(utility::stringUtils::bytesFromString("\r\n"), 2);
if (progress)
progress->stop(total);
@ -1230,7 +1161,7 @@ void IMAPFolder::expunge()
throw exceptions::illegal_state("Folder is read-only");
// Send the request
m_connection->send(true, "EXPUNGE", true);
IMAPCommand::EXPUNGE()->send(m_connection);
// Get the response
std::auto_ptr <IMAPParser::response> resp(m_connection->readResponse());
@ -1259,18 +1190,11 @@ void IMAPFolder::rename(const folder::path& newPath)
else if (!store->isValidFolderName(newPath.getLastComponent()))
throw exceptions::invalid_folder_name();
// Build the request text
std::ostringstream command;
command.imbue(std::locale::classic());
command << "RENAME ";
command << IMAPUtils::quoteString(IMAPUtils::pathToString
(m_connection->hierarchySeparator(), getFullPath())) << " ";
command << IMAPUtils::quoteString(IMAPUtils::pathToString
(m_connection->hierarchySeparator(), newPath));
// Send the request
m_connection->send(true, command.str(), true);
IMAPCommand::RENAME(
IMAPUtils::pathToString(m_connection->hierarchySeparator(), getFullPath()),
IMAPUtils::pathToString(m_connection->hierarchySeparator(), newPath)
)->send(m_connection);
// Get the response
std::auto_ptr <IMAPParser::response> resp(m_connection->readResponse());
@ -1327,16 +1251,11 @@ messageSet IMAPFolder::copyMessages(const folder::path& dest, const messageSet&
else if (!isOpen())
throw exceptions::illegal_state("Folder not open");
// Build the request text
std::ostringstream command;
command.imbue(std::locale::classic());
command << "COPY " << IMAPUtils::messageSetToSequenceSet(set) << " ";
command << IMAPUtils::quoteString(IMAPUtils::pathToString
(m_connection->hierarchySeparator(), dest));
// Send the request
m_connection->send(true, command.str(), true);
IMAPCommand::COPY(
set,
IMAPUtils::pathToString(m_connection->hierarchySeparator(), dest)
)->send(m_connection);
// Get the response
std::auto_ptr <IMAPParser::response> resp(m_connection->readResponse());
@ -1379,24 +1298,22 @@ shared_ptr <folderStatus> IMAPFolder::getStatus()
if (!store)
throw exceptions::illegal_state("Store disconnected");
// Build the request text
std::ostringstream command;
command.imbue(std::locale::classic());
// Build the attributes list
std::vector <string> attribs;
command << "STATUS ";
command << IMAPUtils::quoteString(IMAPUtils::pathToString
(m_connection->hierarchySeparator(), getFullPath()));
command << " (";
command << "MESSAGES" << ' ' << "UNSEEN" << ' ' << "UIDNEXT" << ' ' << "UIDVALIDITY";
attribs.push_back("MESSAGES");
attribs.push_back("UNSEEN");
attribs.push_back("UIDNEXT");
attribs.push_back("UIDVALIDITY");
if (m_connection->hasCapability("CONDSTORE"))
command << ' ' << "HIGHESTMODSEQ";
command << ")";
attribs.push_back("HIGHESTMODSEQ");
// Send the request
m_connection->send(true, command.str(), true);
IMAPCommand::STATUS(
IMAPUtils::pathToString(m_connection->hierarchySeparator(), getFullPath()),
attribs
)->send(m_connection);
// Get the response
std::auto_ptr <IMAPParser::response> resp(m_connection->readResponse());
@ -1443,7 +1360,7 @@ void IMAPFolder::noop()
if (!store)
throw exceptions::illegal_state("Store disconnected");
m_connection->send(true, "NOOP", true);
IMAPCommand::NOOP()->send(m_connection);
std::auto_ptr <IMAPParser::response> resp(m_connection->readResponse());
@ -1459,15 +1376,15 @@ void IMAPFolder::noop()
std::vector <int> IMAPFolder::getMessageNumbersStartingOnUID(const message::uid& uid)
{
std::vector<int> v;
std::ostringstream command;
command.imbue(std::locale::classic());
command << "SEARCH UID " << uid << ":*";
// Send the request
m_connection->send(true, command.str(), true);
std::ostringstream uidSearchKey;
uidSearchKey.imbue(std::locale::classic());
uidSearchKey << "UID " << uid << ":*";
std::vector <string> searchKeys;
searchKeys.push_back(uidSearchKey.str());
IMAPCommand::SEARCH(searchKeys, /* charset */ NULL)->send(m_connection);
// Get the response
std::auto_ptr <IMAPParser::response> resp(m_connection->readResponse());
@ -1480,6 +1397,7 @@ std::vector <int> IMAPFolder::getMessageNumbersStartingOnUID(const message::uid&
}
const std::vector <IMAPParser::continue_req_or_response_data*>& respDataList = resp->continue_req_or_response_data();
std::vector <int> seqNumbers;
for (std::vector <IMAPParser::continue_req_or_response_data*>::const_iterator
it = respDataList.begin() ; it != respDataList.end() ; ++it)
@ -1505,13 +1423,13 @@ std::vector <int> IMAPFolder::getMessageNumbersStartingOnUID(const message::uid&
it != mailboxData->search_nz_number_list().end();
++it)
{
v.push_back((*it)->value());
seqNumbers.push_back((*it)->value());
}
}
processStatusUpdate(resp.get());
return v;
return seqNumbers;
}

View File

@ -299,15 +299,7 @@ void IMAPMessage::extractImpl
}
}
// Build the request text
std::ostringstream command;
command.imbue(std::locale::classic());
if (m_uid.empty())
command << "FETCH " << m_num << " BODY";
else
command << "UID FETCH " << m_uid << " BODY";
// Build the body descriptor for FETCH
/*
BODY[] header + body
BODY.PEEK[] header + body (peek)
@ -316,43 +308,53 @@ void IMAPMessage::extractImpl
BODY[TEXT] body
BODY.PEEK[TEXT] body (peek)
*/
std::ostringstream bodyDesc;
bodyDesc.imbue(std::locale::classic());
bodyDesc << "BODY";
if (extractFlags & EXTRACT_PEEK)
command << ".PEEK";
bodyDesc << ".PEEK";
command << "[";
bodyDesc << "[";
if (section.str().empty())
{
// header + body
if ((extractFlags & EXTRACT_HEADER) && (extractFlags & EXTRACT_BODY))
command << "";
bodyDesc << "";
// body only
else if (extractFlags & EXTRACT_BODY)
command << "TEXT";
bodyDesc << "TEXT";
// header only
else if (extractFlags & EXTRACT_HEADER)
command << "HEADER";
bodyDesc << "HEADER";
}
else
{
command << section.str();
bodyDesc << section.str();
// header + body
if ((extractFlags & EXTRACT_HEADER) && (extractFlags & EXTRACT_BODY))
throw exceptions::operation_not_supported();
// header only
else if (extractFlags & EXTRACT_HEADER)
command << ".MIME"; // "MIME" not "HEADER" for parts
bodyDesc << ".MIME"; // "MIME" not "HEADER" for parts
}
command << "]";
bodyDesc << "]";
if (start != 0 || length != static_cast <size_t>(-1))
command << "<" << start << "." << length << ">";
bodyDesc << "<" << start << "." << length << ">";
std::vector <std::string> fetchParams;
fetchParams.push_back(bodyDesc.str());
// Send the request
constCast <IMAPFolder>(folder)->m_connection->send(true, command.str(), true);
IMAPCommand::FETCH(
m_uid.empty() ? messageSet::byNumber(m_num) : messageSet::byUID(m_uid),
fetchParams
)->send(constCast <IMAPFolder>(folder)->m_connection);
// Get the response
std::auto_ptr <IMAPParser::response> resp

View File

@ -31,6 +31,7 @@
#include "vmime/net/imap/IMAPFolder.hpp"
#include "vmime/net/imap/IMAPConnection.hpp"
#include "vmime/net/imap/IMAPFolderStatus.hpp"
#include "vmime/net/imap/IMAPCommand.hpp"
#include "vmime/exception.hpp"
#include "vmime/platform.hpp"
@ -192,7 +193,7 @@ void IMAPStore::noop()
if (!isConnected())
throw exceptions::not_connected();
m_connection->send(true, "NOOP", true);
IMAPCommand::NOOP()->send(m_connection);
std::auto_ptr <IMAPParser::response> resp(m_connection->readResponse());

View File

@ -488,35 +488,21 @@ int IMAPUtils::messageFlagsFromFlags(const IMAPParser::flag_list* list)
}
const string IMAPUtils::messageFlagList(const int flags)
// static
const std::vector <string> IMAPUtils::messageFlagList(const int flags)
{
std::vector <string> flagList;
if (flags == -1)
return flagList; // default flags
if (flags & message::FLAG_REPLIED) flagList.push_back("\\Answered");
if (flags & message::FLAG_MARKED) flagList.push_back("\\Flagged");
if (flags & message::FLAG_DELETED) flagList.push_back("\\Deleted");
if (flags & message::FLAG_SEEN) flagList.push_back("\\Seen");
if (flags & message::FLAG_DRAFT) flagList.push_back("\\Draft");
if (!flagList.empty())
{
std::ostringstream res;
res.imbue(std::locale::classic());
res << "(";
if (flagList.size() >= 2)
{
std::copy(flagList.begin(), flagList.end() - 1,
std::ostream_iterator <string>(res, " "));
}
res << *(flagList.end() - 1) << ")";
return (res.str());
}
return "";
return flagList;
}
@ -590,7 +576,7 @@ const string IMAPUtils::dateTime(const vmime::datetime& date)
// static
const string IMAPUtils::buildFetchRequest
shared_ptr <IMAPCommand> IMAPUtils::buildFetchCommand
(shared_ptr <IMAPConnection> cnt, const messageSet& msgs, const fetchAttributes& options)
{
// Example:
@ -659,25 +645,7 @@ const string IMAPUtils::buildFetchRequest
}
}
// Build the request text
std::ostringstream command;
command.imbue(std::locale::classic());
if (msgs.isUIDSet())
command << "UID FETCH " << messageSetToSequenceSet(msgs) << " (";
else
command << "FETCH " << messageSetToSequenceSet(msgs) << " (";
for (std::vector <string>::const_iterator it = items.begin() ;
it != items.end() ; ++it)
{
if (it != items.begin()) command << " ";
command << *it;
}
command << ")";
return command.str();
return IMAPCommand::FETCH(msgs, items);
}

View File

@ -38,6 +38,7 @@
#include "vmime/net/message.hpp"
#include "vmime/net/imap/IMAPParser.hpp"
#include "vmime/net/imap/IMAPConnection.hpp"
#include "vmime/net/imap/IMAPCommand.hpp"
#include "vmime/mailboxList.hpp"
@ -79,7 +80,7 @@ public:
static int messageFlagsFromFlags(const IMAPParser::flag_list* list);
static const string messageFlagList(const int flags);
static const std::vector <string> messageFlagList(const int flags);
/** Format a date/time to IMAP date/time format.
*
@ -96,7 +97,7 @@ public:
* @param options fetch options
* @return fetch request
*/
static const string buildFetchRequest
static shared_ptr <IMAPCommand> buildFetchCommand
(shared_ptr <IMAPConnection> cnt, const messageSet& msgs, const fetchAttributes& options);
/** Convert a parser-style address list to a mailbox list.

View File

@ -53,6 +53,26 @@ public:
return string(reinterpret_cast <const char*>(data), count);
}
/** Casts a string to bytes.
*
* @param str string
* @return pointer to the first byte of the string
*/
static const byte_t* bytesFromString(const string& str)
{
return reinterpret_cast <const byte_t*>(str.data());
}
/** Casts a NULL-terminated string to bytes.
*
* @param str string
* @return pointer to the first byte of the string
*/
static const byte_t* bytesFromString(const char* str)
{
return reinterpret_cast <const byte_t*>(str);
}
/** Appends bytes to a string.
*
* @param str string to which append data

View File

@ -0,0 +1,484 @@
//
// VMime library (http://www.vmime.org)
// Copyright (C) 2002-2014 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::make_shared <vmime::net::session>();
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