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.
This commit is contained in:
Vincent Richard 2014-03-10 19:10:08 +01:00
parent 16bd0a6ec2
commit 3fcea19d75
7 changed files with 126 additions and 0 deletions

View File

@ -368,6 +368,19 @@ public:
*/
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).
*

View File

@ -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 |

View File

@ -134,6 +134,9 @@ public:
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.

View File

@ -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 |

View File

@ -119,6 +119,9 @@ public:
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);

View File

@ -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 |

View File

@ -116,6 +116,9 @@ public:
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);