Reputation: 433
I have an email provider that uses SMTP and IMAP from Mailkit. The main function I am using at the moment is to read messages from the inbox, and depending on the contents of the email they will go into a 'Processed' or an 'Ignored' folder. In existing systems we used with Exchange, these folders exist as subfolders to the Inbox. If the folders don't exist, they are created. A sample code snippet is below:
var _inboxFolder = _provider.GetInboxFolder();
var folder = _inboxFolder.GetChildFolder(folderName);
if (folder == null)
{
// If Gmail, Inbox does not allow children. Check for folder in root.
folder = _provider.GetFolder(folderName);
}
if (folder == null)
{
// Create new folder under Inbox
folder = _inboxFolder.CreateChildFolder(folderName);
if (folder == null)
{
// Cannot create under Inbox, create on root
folder = _provider.CreateFolderOnRoot(folderName);
}
}
These all use my own provider which is based on an interface we use for other providers, so there is some 'strange' logic there that makes sense for the other providers. GetInboxFolder and GetFolder returns a folder, but returns null if one can't be found. This works fine in all providers - if the folders don't exist, they can be created.
The issue arrives when creating the folders. If the folders cannot be found, they should be created under the Inbox folder. If this can't happen (like in Gmail), it should create them on the root folder. However, attempting to create a folder under the Inbox folder doesn't fail, it simply creates a label called "INBOX/FolderName". Ideally I would like to have any attempt to create this folder fail so it can simply be created on the root. I imagine this is an issue in the conversion from IMAP to the GMail label system.
Is there any way of preventing the "INBOX/FolderName" label, or identifying this issue before creating it? Or is there a way of identifying that this is a gmail server and implementing a special clause for it?
For a little extra info, the CreateChildFolder and CreateFolderOnRoot code is below.
public IEmailFolder CreateChildFolder(string displayName)
{
if (_imapClient == null || !_imapClient.IsConnected)
{
throw new NotLoggedInException();
}
return new ImapFolder(_folder.Create(displayName, true), _imapClient);
}
public IEmailFolder CreateFolderOnRoot(string displayName)
{
if (_client == null)
{
throw new NotLoggedInException();
}
try
{
var toplevel = _client.GetFolder(_client.PersonalNamespaces[0]);
var mailkit = toplevel.Create(displayName, true);
return new ImapFolder(mailkit, _client);
}
catch (Exception exception)
{
throw new LoadFolderFailedException(exception);
}
}
Upvotes: 0
Views: 2114
Reputation: 38643
The GMail "Label System" is how GMail implements folders. They do not implement physical folders, what they do is have "virtual" folders that are just whatever labels the user has defined and the folder is just a query of all mail that has that label applied.
That said, the GMail root namespace is string.Empty
. Some IMAP servers have a root namespace of "INBOX"
(such as Courier IMAP, I think).
Your CreateFolderOnRoot
method should create a folder at the root for GMail, it won't create it under INBOX, so your question is very confusing.
If you want to add the folder under the INBOX, just use client.Inbox.Create (displayName, true);
The issue arrives when creating the folders. If the folders cannot be found, they should be created under the Inbox folder.
This makes me think that what you actually want to do is this:
try {
var toplevel = _client.GetFolder(_client.PersonalNamespaces[0]);
var mailkit = folder.GetSubfolder(displayName);
return new ImapFolder(mailkit, _client);
} catch (Exception ex) {
throw new LoadFolderFailedException(ex);
}
Notice the use of GetSubfolder
as opposed to Create
. Create
will always create the folder. GetSubfolder
will only get it if it exists.
Upvotes: 1