Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Issue #47: get and fetch messages.
Added a feature to get and fetch a list of messages at the same time,
to avoid a roundtrip to the server.
  • Loading branch information
vincent-richard committed Mar 10, 2014
1 parent 16bd0a6 commit 3fcea19
Show file tree
Hide file tree
Showing 7 changed files with 126 additions and 0 deletions.
13 changes: 13 additions & 0 deletions src/vmime/net/folder.hpp
Expand Up @@ -368,6 +368,19 @@ class VMIME_EXPORT folder : public object
*/
virtual void fetchMessage(shared_ptr <message> msg, const fetchAttributes& attribs) = 0;

/** Get new references to messages in this folder, given either their
* sequence numbers or UIDs, and fetch objects for them at the same time.
*
* @param msgs index set of messages to retrieve
* @param attribs set of attributes to fetch
* @return new objects referencing the specified messages
* @throw exceptions::net_exception if an error occurs
* @see folder::getMessages()
* @see folder::fetchMessages()
*/
virtual std::vector <shared_ptr <message> > getAndFetchMessages
(const messageSet& msgs, const fetchAttributes& attribs) = 0;

/** Return the list of fetchable objects supported by
* the underlying protocol (see folder::fetchAttributes).
*
Expand Down
84 changes: 84 additions & 0 deletions src/vmime/net/imap/IMAPFolder.cpp
Expand Up @@ -860,6 +860,90 @@ void IMAPFolder::fetchMessage(shared_ptr <message> msg, const fetchAttributes& o
}


std::vector <shared_ptr <message> > IMAPFolder::getAndFetchMessages
(const messageSet& msgs, const fetchAttributes& attribs)
{
shared_ptr <IMAPStore> store = m_store.lock();

if (!store)
throw exceptions::illegal_state("Store disconnected");
else if (!isOpen())
throw exceptions::illegal_state("Folder not open");

// Ensure we also get the UID for each message
fetchAttributes attribsWithUID(attribs);
attribsWithUID.add(fetchAttributes::UID);

// Send the request
const string command = IMAPUtils::buildFetchRequest
(m_connection, msgs, attribsWithUID);

m_connection->send(true, command, true);

// Get the response
std::auto_ptr <IMAPParser::response> resp(m_connection->readResponse());

if (resp->isBad() || resp->response_done()->response_tagged()->
resp_cond_state()->status() != IMAPParser::resp_cond_state::OK)
{
throw exceptions::command_error("FETCH",
resp->getErrorLog(), "bad response");
}

const std::vector <IMAPParser::continue_req_or_response_data*>& respDataList =
resp->continue_req_or_response_data();

std::vector <shared_ptr <message> > messages;

for (std::vector <IMAPParser::continue_req_or_response_data*>::const_iterator
it = respDataList.begin() ; it != respDataList.end() ; ++it)
{
if ((*it)->response_data() == NULL)
{
throw exceptions::command_error("FETCH",
resp->getErrorLog(), "invalid response");
}

const IMAPParser::message_data* messageData =
(*it)->response_data()->message_data();

// We are only interested in responses of type "FETCH"
if (messageData == NULL || messageData->type() != IMAPParser::message_data::FETCH)
continue;

// Get message number
const int msgNum = static_cast <int>(messageData->number());

// Get message UID
const std::vector <IMAPParser::msg_att_item*> atts = messageData->msg_att()->items();
message::uid msgUID;

for (std::vector <IMAPParser::msg_att_item*>::const_iterator
it = atts.begin() ; it != atts.end() ; ++it)
{
if ((*it)->type() == IMAPParser::msg_att_item::UID)
{
msgUID = (*it)->unique_id()->value();
break;
}
}

// Create a new message reference
shared_ptr <IMAPFolder> thisFolder = dynamicCast <IMAPFolder>(shared_from_this());
shared_ptr <IMAPMessage> msg = make_shared <IMAPMessage>(thisFolder, msgNum, msgUID);

messages.push_back(msg);

// Process fetch response for this message
msg->processFetchResponse(attribsWithUID, messageData);
}

processStatusUpdate(resp.get());

return messages;
}


int IMAPFolder::getFetchCapabilities() const
{
return fetchAttributes::ENVELOPE | fetchAttributes::CONTENT_INFO |
Expand Down
3 changes: 3 additions & 0 deletions src/vmime/net/imap/IMAPFolder.hpp
Expand Up @@ -134,6 +134,9 @@ class VMIME_EXPORT IMAPFolder : public folder
void fetchMessages(std::vector <shared_ptr <message> >& msg, const fetchAttributes& options, utility::progressListener* progress = NULL);
void fetchMessage(shared_ptr <message> msg, const fetchAttributes& options);

std::vector <shared_ptr <message> > getAndFetchMessages
(const messageSet& msgs, const fetchAttributes& attribs);

int getFetchCapabilities() const;

/** Returns the UID validity of the folder for the current session.
Expand Down
10 changes: 10 additions & 0 deletions src/vmime/net/maildir/maildirFolder.cpp
Expand Up @@ -1223,6 +1223,16 @@ void maildirFolder::fetchMessage(shared_ptr <message> msg, const fetchAttributes
}


std::vector <shared_ptr <message> > maildirFolder::getAndFetchMessages
(const messageSet& msgs, const fetchAttributes& attribs)
{
std::vector <shared_ptr <message> > messages = getMessages(msgs);
fetchMessages(messages, attribs);

return messages;
}


int maildirFolder::getFetchCapabilities() const
{
return fetchAttributes::ENVELOPE | fetchAttributes::STRUCTURE |
Expand Down
3 changes: 3 additions & 0 deletions src/vmime/net/maildir/maildirFolder.hpp
Expand Up @@ -119,6 +119,9 @@ class VMIME_EXPORT maildirFolder : public folder
void fetchMessages(std::vector <shared_ptr <message> >& msg, const fetchAttributes& options, utility::progressListener* progress = NULL);
void fetchMessage(shared_ptr <message> msg, const fetchAttributes& options);

std::vector <shared_ptr <message> > getAndFetchMessages
(const messageSet& msgs, const fetchAttributes& attribs);

int getFetchCapabilities() const;

std::vector <int> getMessageNumbersStartingOnUID(const message::uid& uid);
Expand Down
10 changes: 10 additions & 0 deletions src/vmime/net/pop3/POP3Folder.cpp
Expand Up @@ -484,6 +484,16 @@ void POP3Folder::fetchMessage(shared_ptr <message> msg, const fetchAttributes& o
}


std::vector <shared_ptr <message> > POP3Folder::getAndFetchMessages
(const messageSet& msgs, const fetchAttributes& attribs)
{
std::vector <shared_ptr <message> > messages = getMessages(msgs);
fetchMessages(messages, attribs);

return messages;
}


int POP3Folder::getFetchCapabilities() const
{
return fetchAttributes::ENVELOPE | fetchAttributes::CONTENT_INFO |
Expand Down
3 changes: 3 additions & 0 deletions src/vmime/net/pop3/POP3Folder.hpp
Expand Up @@ -116,6 +116,9 @@ class VMIME_EXPORT POP3Folder : public folder
void fetchMessages(std::vector <shared_ptr <message> >& msg, const fetchAttributes& options, utility::progressListener* progress = NULL);
void fetchMessage(shared_ptr <message> msg, const fetchAttributes& options);

std::vector <shared_ptr <message> > getAndFetchMessages
(const messageSet& msgs, const fetchAttributes& attribs);

int getFetchCapabilities() const;

std::vector <int> getMessageNumbersStartingOnUID(const message::uid& uid);
Expand Down

0 comments on commit 3fcea19

Please sign in to comment.