使用.NET MVC获取Gmail电子邮件

时间:2016-03-10 16:08:12

标签: asp.net-mvc email gmail imap

我正在尝试创建一个小型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封电子邮件的电子邮件,并且需要永久地获取所有电子邮件....

1 个答案:

答案 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