如果您想坚持使用 MailSystem.NET,arnt 给出的答案是正确的。
但是,正如我在此处(以及为方便起见)指出的那样,MailSystem.NET 存在许多使其无法使用的架构设计问题。
如果您使用其他开源库,例如MailKit,您将更轻松地完成此搜索查询:
var query = SearchQuery.BodyContains ("icône");
var orderBy = new OrderBy[] { OrderBy.ReverseArrival };
var results = folder.Search (query, orderBy);
希望有帮助。
MailSystem.NET 中的架构问题包括:
MailSystem.NET 没有正确处理文字标记 - 发送它们(对于 APPEND 以外的任何内容)或接收它们(对于 FETCH 请求中的实际消息数据以外的任何内容)。作者似乎都没有注意到,服务器可能会选择对任何字符串响应使用文字。
这是什么意思?
这意味着服务器可以选择使用邮箱名称的文字来响应 LIST 命令。
这意味着 BODYSTRUCTURE 中的任何字段都可以是文字,而不必像他们都假设的那样必须是带引号的字符串。
(和更多...)
例如,MailSystem.NET 也没有正确编码或引用邮箱名称:
来自 MailSystem.NET 的示例:
public string RenameMailbox(string oldMailboxName, string newMailboxName)
{
string response = this.Command("rename \"" + oldMailboxName + "\" \"" + newMailboxName + "\"");
return response;
}
这值得让-卢克·皮卡德(Jean-Luc Picard)和威尔·赖克( Will Riker)掌声。这段代码只是盲目地在邮箱名称周围加上双引号。这是错误的,至少有两个原因:
- 如果邮箱名称有任何双引号或反斜杠怎么办?它需要用 \'s 来逃避它们。
- 如果mailboxName 包含非ASCII 字符或& 怎么办?它需要使用 UTF-7 字符编码的修改版本对名称进行编码。
我可以找到的大多数(全部?).NET IMAP 客户端将来自服务器的整个响应读取为 1 个大字符串,然后尝试使用正则表达式、IndexOf() 和 Substring() 的某种组合来解析响应。更糟糕的是,它们中的大多数也是由不知道 unicode 字符计数(即 string.Length)和八位字节(即字节计数)之间区别的开发人员编写的,因此当他们尝试解析对 FETCH 的响应时请求消息,他们在解析响应第一行中的“{}”值后执行此操作:
int startIndex = response.IndexOf ("}") + 3;
int endIndex = startIndex + octets;
string msg = response.Substring (startIndex, endIndex - startIndex);
MailSystem.NET 开发人员显然收到了关于这不适用于国际邮件的错误报告,因此他们的“修复”是这样做:
public string Body(int messageOrdinal)
{
this.ParentMailbox.SourceClient.SelectMailbox(this.ParentMailbox.Name);
string response = this.ParentMailbox.SourceClient.Command("fetch "+messageOrdinal.ToString()+" body", getFetchOptions());
return response.Substring(response.IndexOf("}")+3,response.LastIndexOf(" UID")-response.IndexOf("}")-7);
}
从本质上讲,他们假设UID 键/值对将出现在消息之后,并将其用作他们无能的黑客攻击。不幸的是,在现有的无能中增加更多的无能只会增加无能,它实际上并不能解决它。
IMAP 规范明确指出,结果的顺序可能会有所不同,并且它们甚至可能不在同一个未标记的响应中。
不仅如此,他们的 FETCH 请求甚至没有向服务器请求 UID 值,所以取决于服务器是否返回它!
TL;博士
如何评估 IMAP 客户端库
在评估 IMAP 客户端库实现时,您应该做的第一件事是查看它们如何解析响应。如果他们不使用实际的分词器,您可以立即判断该库是由不知道自己在做什么的人编写的。这是远离的最可靠的警告信号。
库是否在中心位置(例如它们的命令管道)处理未标记(“*”)的响应?还是它会做一些迟钝的事情,比如尝试在每个发送命令的方法中解析它(例如 ImapClient.SelectFolder()、ImapClient.FetchMessage() 等)?如果图书馆没有在可以正确处理这些未标记响应和更新状态(并通知您诸如 EXPUNGE 之类的重要事情)的中央位置处理它,请远离。
如果库将整个响应(甚至只是“消息”)读入 System.String,请远离。