我正在尝试创建一个小型Web应用程序,作为Gmail的Web邮件客户端...
我使用以下代码从我的收件箱中提取电子邮件:
public ActionResult Index()
{
using (var client = new ImapClient())
{
using (var cancel = new CancellationTokenSource())
{
ServicePointManager.ServerCertificateValidationCallback += (o, c, ch, er) => true;
client.Connect("imap.gmail.com", 993, true, cancel.Token);
// If you want to disable an authentication mechanism,
// you can do so by removing the mechanism like this:
client.AuthenticationMechanisms.Remove("XOAUTH");
client.Authenticate("********@gmail.com", "****", cancel.Token);
// The Inbox folder is always available...
var inbox = client.Inbox;
inbox.Open(FolderAccess.ReadOnly, cancel.Token);
m = new List<string>();
// download each message based on the message index
for (int i = 0; i < inbox.length; i++)
{
var message = inbox.GetMessage(i, cancel.Token);
m.Insert(i, message.TextBody);
}
client.Disconnect(true, cancel.Token);
}
}
return View(m.ToList());
}
我不喜欢这样做的原因是代码的这一部分:
for (int i = 0; i < inbox.length; i++)
{
var message = inbox.GetMessage(i, cancel.Token);
m.Insert(i, message.TextBody);
}
获取所有电子邮件需要很长时间,每5秒钟提取大约40封电子邮件...因此,如果有人有2000封电子邮件,则需要20分钟才能加载所有电子邮件...
有没有更快的方法将所有电子邮件加载到我的MVC应用程序中? :/
P.S。我已经尝试过使用包含10000封电子邮件的电子邮件,并且需要永久地获取所有电子邮件....
答案 0 :(得分:0)
如果您想要的只是邮件的文本正文,则可以使用以下方法减少IMAP流量:
var messages = inbox.Fetch (0, -1, MessageSummaryItems.UniqueId | MessageSummaryItems.BodyStructure);
int i = 0;
foreach (var message in messages) {
var part = message.TextBody;
if (part != null) {
var body = (TextPart) inbox.GetBodyPart (message.UniqueId, part);
m.Insert (i, body.Text);
} else {
m.Insert (i, null);
}
i++;
}
这样做是将批量的FETCH请求发送到IMAP服务器,请求&#34;大纲&#34; (又名身体结构)消息及其唯一标识符。
然后,它后面的循环查看消息的结构,找到哪个MIME部分包含消息的文本正文,然后只获取消息的特定子部分。
通常,您不会通过IMAP下载每条消息。 IMAP的目的是将所有消息保留在IMAP服务器上,只需获取所需的最少量数据,以便显示您想要显示给用户的任何内容。
还应该注意的是,除非您实际上计划取消操作,否则您实际上并不需要使用CancellationTokenSource
。
例如,您的代码段可以替换为:
public ActionResult Index()
{
using (var client = new ImapClient())
{
ServicePointManager.ServerCertificateValidationCallback += (o, c, ch, er) => true;
client.Connect("imap.gmail.com", 993, true);
// If you want to disable an authentication mechanism,
// you can do so by removing the mechanism like this:
client.AuthenticationMechanisms.Remove("XOAUTH");
client.Authenticate("********@gmail.com", "****");
// The Inbox folder is always available...
var inbox = client.Inbox;
inbox.Open(FolderAccess.ReadOnly);
m = new List<string>();
var messages = inbox.Fetch (0, -1, MessageSummaryItems.UniqueId | MessageSummaryItems.BodyStructure);
int i = 0;
foreach (var message in messages) {
var part = message.TextBody;
if (part != null) {
var body = (TextPart) inbox.GetBodyPart (message.UniqueId, part);
m.Insert (i, body.Text);
} else {
m.Insert (i, null);
}
i++;
}
client.Disconnect(true);
}
return View(m.ToList());
}
由于您正在为GMail编写自己的Webmail前端,因此您可能会发现以下建议有用:
当您查看GMail webmail用户界面或Yahoo Mail!的用户界面时,您可能已经注意到他们只向您显示最近50条左右的消息,您必须专门点击链接显示下一组50条消息,依此类推,对吧?
原因是查询完整的消息列表并将其全部下载(甚至只是所有消息的文本正文)效率低下。
他们所做的只是一次只要求50封邮件。事实上,他们根本不会要求提供这些信息,他们要求提供如下摘要信息:
var all = inbox.Search (SearchQuery.All);
var uids = new UniqueIdSet ();
// grab the last 50 unique identifiers
int min = Math.Max (all.Count - 50, 0);
for (int i = all.Count - 1; i >= min; i--)
uids.Add (all[i]);
// get the summary info needed to display a message-list UI
var messages = inbox.Fetch (uids, MessageSummaryItems.UniqueId |
MessageSummaryItems.All | MessageSummaryItems.BodyStructure);
foreach (var message in messages) {
// the 'message' will contain a whole bunch of useful info
// to use for displaying a message list such as subject, date,
// the flags (read/unread/etc), the unique id, and the
// body structure that you can use to minimize your query when
// the user actually clicks on a message and wants to read it.
}
用户点击邮件进行阅读后,您可以使用message.Body
找出实际需要下载哪些正文部分,以便将其显示给用户(即避免下载附件等。)
有关如何执行此操作的示例,请查看MailKit GitHub存储库中包含的ImapClientDemo示例:https://github.com/jstedfast/MailKit