Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support imap and maildir recent, fix maildir for dovecot server #188

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion src/vmime/net/imap/IMAPParser.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1783,6 +1783,8 @@ class VMIME_EXPORT IMAPParser : public object
m_type = SEEN;
else if (name == "draft")
m_type = DRAFT;
else if (name == "recent")
m_type = RECENT;
else
{
m_type = UNKNOWN;
Expand Down Expand Up @@ -1811,7 +1813,8 @@ class VMIME_EXPORT IMAPParser : public object
SEEN,
DRAFT,
KEYWORD_OR_EXTENSION,
STAR // * = custom flags allowed
STAR, // * = custom flags allowed
RECENT
};

private:
Expand Down
3 changes: 3 additions & 0 deletions src/vmime/net/imap/IMAPUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -491,6 +491,9 @@ int IMAPUtils::messageFlagsFromFlags(const IMAPParser::flag_list* list)
case IMAPParser::flag::SEEN:
flags |= message::FLAG_SEEN;
break;
case IMAPParser::flag::RECENT:
flags |= message::FLAG_RECENT;
break;
case IMAPParser::flag::DRAFT:
flags |= message::FLAG_DRAFT;
break;
Expand Down
85 changes: 58 additions & 27 deletions src/vmime/net/maildir/maildirFolder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -102,10 +102,8 @@ const folderAttributes maildirFolder::getAttributes()
{
folderAttributes attribs;

if (m_path.isEmpty())
attribs.setType(folderAttributes::TYPE_CONTAINS_FOLDERS);
else
attribs.setType(folderAttributes::TYPE_CONTAINS_FOLDERS | folderAttributes::TYPE_CONTAINS_MESSAGES);
// For dovecot server (use courier implementation) the root directory can contain messages
attribs.setType(folderAttributes::TYPE_CONTAINS_FOLDERS | folderAttributes::TYPE_CONTAINS_MESSAGES);

if (m_store.lock()->getFormat()->folderHasSubfolders(m_path))
attribs.setFlags(folderAttributes::FLAG_HAS_CHILDREN); // contains at least one sub-folder
Expand Down Expand Up @@ -137,10 +135,11 @@ void maildirFolder::open(const int mode, bool /* failIfModeIsNotAvailable */)
else if (!exists())
throw exceptions::illegal_state("Folder does not exist");

m_mode = mode; // Should be know by scanFolder modifications

scanFolder();

m_open = true;
m_mode = mode;
}


Expand Down Expand Up @@ -321,17 +320,33 @@ void maildirFolder::scanFolder()
// "maildirUtils::messageIdComparator" to compare only the 'unique'
// portion of the filename...

if (msgInfos.type == messageInfos::TYPE_CUR)
if (msgInfos.type != messageInfos::TYPE_DELETED)
{
const std::vector <utility::file::path::component>::iterator pos =
std::find_if(curMessageFilenames.begin(), curMessageFilenames.end(),
maildirUtils::messageIdComparator(msgInfos.path));

// If we cannot find this message in the 'cur' directory,
// it means it has been deleted (and expunged).
// search in the 'new' directory.
// Don't move from new to cur directory when open folder directory
if (pos == curMessageFilenames.end())
{
msgInfos.type = messageInfos::TYPE_DELETED;
const std::vector <utility::file::path::component>::iterator pos =
std::find_if(newMessageFilenames.begin(), newMessageFilenames.end(),
maildirUtils::messageIdComparator(msgInfos.path));

// If we cannot find this message also in the 'new' directory,
// it means it has been deleted (and expunged).
if (pos == newMessageFilenames.end())
{
msgInfos.type = messageInfos::TYPE_DELETED;
}
// Otherwise, update its information.
else
{
msgInfos.path = *pos;
newMessageFilenames.erase(pos);
}
}
// Otherwise, update its information.
else
Expand All @@ -345,33 +360,24 @@ void maildirFolder::scanFolder()
m_messageInfos.reserve(m_messageInfos.size()
+ newMessageFilenames.size() + curMessageFilenames.size());

// Add new messages from 'new': we are responsible to move the files
// from the 'new' directory to the 'cur' directory, and append them
// to our message list.
// Add new messages from 'new' directory
// Don't move to 'cur' directory
for (std::vector <utility::file::path::component>::const_iterator
it = newMessageFilenames.begin() ; it != newMessageFilenames.end() ; ++it)
{
const utility::file::path::component newFilename =
maildirUtils::buildFilename(maildirUtils::extractId(*it), 0);

// Move messages from 'new' to 'cur'
shared_ptr <utility::file> file = fsf->create(newDirPath / *it);
file->rename(curDirPath / newFilename);

// Append to message list
messageInfos msgInfos;
msgInfos.path = newFilename;
msgInfos.path = *it;

if (maildirUtils::extractFlags(msgInfos.path) & message::FLAG_DELETED)
msgInfos.type = messageInfos::TYPE_DELETED;
else
msgInfos.type = messageInfos::TYPE_CUR;
msgInfos.type = messageInfos::TYPE_NEW;

m_messageInfos.push_back(msgInfos);
}

// Add new messages from 'cur': the files have already been moved
// from 'new' to 'cur'. Just append them to our message list.
// Add new messages from 'cur'
for (std::vector <utility::file::path::component>::const_iterator
it = curMessageFilenames.begin() ; it != curMessageFilenames.end() ; ++it)
{
Expand Down Expand Up @@ -630,6 +636,8 @@ void maildirFolder::setMessageFlags

if (flags & message::FLAG_DELETED)
m_messageInfos[num].type = messageInfos::TYPE_DELETED;
else if (flags & message::FLAG_RECENT)
m_messageInfos[num].type = messageInfos::TYPE_NEW;
else
m_messageInfos[num].type = messageInfos::TYPE_CUR;

Expand Down Expand Up @@ -1205,12 +1213,11 @@ void maildirFolder::fetchMessages(std::vector <shared_ptr <message> >& msg,
if (progress)
progress->start(total);

shared_ptr <maildirFolder> thisFolder = dynamicCast <maildirFolder>(shared_from_this());

for (std::vector <shared_ptr <message> >::iterator it = msg.begin() ;
it != msg.end() ; ++it)
{
dynamicCast <maildirMessage>(*it)->fetch(thisFolder, options);
// For each recent message the fetchMessage function should be move from 'new' to 'cur' directory
fetchMessage ((*it), options);

if (progress)
progress->progress(++current, total);
Expand All @@ -1232,6 +1239,29 @@ void maildirFolder::fetchMessage(shared_ptr <message> msg, const fetchAttributes

dynamicCast <maildirMessage>(msg)->fetch
(dynamicCast <maildirFolder>(shared_from_this()), options);

// For recent message move from 'new' to 'cur' directory
size_t msgNum = msg->getNumber ();
messageInfos& msgInfos = m_messageInfos [msgNum - 1];
if (msgInfos.type == messageInfos::TYPE_NEW)
{
if (options.has(fetchAttributes::FLAGS))
dynamicCast <maildirMessage> (msg)->m_flags |= message::FLAG_RECENT;
// Don't move if read only access
if (m_mode != MODE_READ_ONLY)
{
// Move messages from 'new' to 'cur'
const utility::file::path::component curFilename =
maildirUtils::buildFilename (maildirUtils::extractId (msgInfos.path), 0);

shared_ptr <utility::fileSystemFactory> fsf = platform::getHandler()->getFileSystemFactory();
shared_ptr <utility::file> file = fsf->create(store->getFormat ()->folderPathToFileSystemPath
(m_path, maildirFormat::NEW_DIRECTORY) / msgInfos.path);
file->rename (store->getFormat ()->folderPathToFileSystemPath
(m_path, maildirFormat::CUR_DIRECTORY) / curFilename);
msgInfos.path = curFilename;
}
}
}


Expand Down Expand Up @@ -1259,10 +1289,11 @@ int maildirFolder::getFetchCapabilities() const

const utility::file::path maildirFolder::getMessageFSPath(const size_t number) const
{
const messageInfos& msgInfos = m_messageInfos [number - 1];
utility::file::path curDirPath = m_store.lock()->getFormat()->
folderPathToFileSystemPath(m_path, maildirFormat::CUR_DIRECTORY);
folderPathToFileSystemPath(m_path, messageInfos::TYPE_NEW ? maildirFormat::NEW_DIRECTORY : maildirFormat::CUR_DIRECTORY);

return (curDirPath / m_messageInfos[number - 1].path);
return (curDirPath / msgInfos.path);
}


Expand Down
3 changes: 2 additions & 1 deletion src/vmime/net/maildir/maildirFolder.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,8 @@ class VMIME_EXPORT maildirFolder : public folder
enum Type
{
TYPE_CUR,
TYPE_DELETED
TYPE_DELETED,
TYPE_NEW
};

utility::file::path::component path; // filename
Expand Down