如何在MailKit中创建/获取含多级子文件夹的目录(带路径分隔符)
使用MailKit创建多级IMAP文件夹的问题
我用MailKit创建文件夹时,一级文件夹的创建很简单——在父文件夹上调用CreateFolderAsync(异步方式)即可,示例代码如下:
public async Task<IMailFolder> GetOrCreateFolder(string folderName) { var rootFolder = await authenticatedClient.GetFolderAsync(imapClient.PersonalNamespaces[0].Path); var existingFolders = await rootFolder.GetSubfoldersAsync(); var matchingFolder = existingFolders.FirstOrDefault(folder => folder.FullName == folderName); if (matchingFolder == null) { matchingFolder = await rootFolder.CreateAsync(folderName, true); } return matchingFolder; }
但如果传入带层级的路径,比如GetOrCreateFolder("folder/subfolder")或GetOrCreateFolder("folder.subfolder")(后续发现很多IMAP服务器用.作为目录分隔符,可通过IMailFolder.DirectorySeparator获取),就会抛出异常:The name is not a legal folder name,具体异常信息如下:
System.ArgumentException HResult=0x80070057 Nachricht = The name is not a legal folder name. Arg_ParamName_Name Quelle = MailKit Stapelüberwachung: bei MailKit.Net.Imap.ImapFolder.QueueCreateCommand(String name, Boolean isMessageFolder, CancellationToken cancellationToken, String& encodedName) bei MailKit.Net.Imap.ImapFolder.CreateAsync(String name, Boolean isMessageFolder, CancellationToken cancellationToken) // ... Diese Ausnahme wurde ursprünglich von dieser Aufrufliste ausgelöst: MailKit.Net.Imap.ImapFolder.QueueCreateCommand(string, bool, System.Threading.CancellationToken, out string) MailKit.Net.Imap.ImapFolder.CreateAsync(string, bool, System.Threading.CancellationToken)
硬编码先创建一级再创建二级的方式太不灵活,Linux的mkdir都支持一次性创建多级文件夹,请问怎么灵活解决这个问题?
解决方案:递归创建多级文件夹
要实现类似mkdir -p的效果,需要拆分路径为层级目录,从根目录开始逐级检查并创建不存在的文件夹,具体实现如下:
public async Task<IMailFolder> GetOrCreateNestedFolder(string folderPath) { var rootFolder = await authenticatedClient.GetFolderAsync(imapClient.PersonalNamespaces[0].Path); char separator = rootFolder.DirectorySeparator; // 拆分路径,过滤空字符串(避免路径开头/结尾的分隔符导致无效项) var folderNames = folderPath.Split(new[] { separator, '/' }, StringSplitOptions.RemoveEmptyEntries); var currentFolder = rootFolder; foreach (var folderName in folderNames) { var subfolders = await currentFolder.GetSubfoldersAsync(); var existingFolder = subfolders.FirstOrDefault(f => f.Name.Equals(folderName, StringComparison.OrdinalIgnoreCase)); if (existingFolder == null) { existingFolder = await currentFolder.CreateAsync(folderName, true); } currentFolder = existingFolder; } return currentFolder; }
代码说明:
- 兼容两种分隔符:同时处理服务器原生分隔符(如
.)和通用的/,适配不同格式的路径输入 - 大小写不敏感匹配:用
StringComparison.OrdinalIgnoreCase判断文件夹是否存在,兼容部分IMAP服务器的大小写特性 - 逐级创建:从根目录开始遍历每一层,确保所有父文件夹都存在,最终返回目标的多级文件夹
内容的提问来源于stack exchange,提问作者rklec
相关产品推荐
相关产品推荐

