MailKit: попытка внедрить IMAP-клиент в ASP.NET Core для получения нового почтового события

Я пытаюсь внедрить IMAP-клиент в моем веб-проекте ASP.NET Core, чтобы он мог работать в своем собственном потоке всякий раз, когда приходит новое электронное письмо. MailRecieved событие будет запущено, и я получу парсинг тела письма и сохраню в БД.

Но проблема в том, что я должен сделать MailClient Keep-Alive, так что я могу продолжать слушать новые электронные письма, что не работает в моем случае. Я читал пример кода в документации MailKit, где они используют System.Timer, к сожалению, ASP.NET нет таймера.

Вот код, который я использую:-

 public static async Task MailSubscribe(IMAPConnection connection)
    {
        try
        {
            using (var client = new ImapClient())
            {
                client.ServerCertificateValidationCallback = (s, c, h, e) => true;
                await client.ConnectAsync(connection.Host, connection.Port, connection.EnableSSL);
                client.AuthenticationMechanisms.Remove("XOAUTH2");
                if (client.IsConnected)
                    client.Authenticate(connection.UserName, connection.Password);
                if (client.IsAuthenticated)
                {
                    var inbox = client.Inbox;
                    inbox.Open(FolderAccess.ReadOnly);
                    inbox.MessagesArrived += async (s, e) =>
                    {
                        using (var mailFetch = new ImapClient())
                        {
                            mailFetch.ServerCertificateValidationCallback = (g, c, h, k) => true;
                            await mailFetch.ConnectAsync(connection.Host, connection.Port, connection.EnableSSL);
                            mailFetch.AuthenticationMechanisms.Remove("XOAUTH2");
                            if (mailFetch.IsConnected)
                                mailFetch.Authenticate(connection.UserName, connection.Password);
                            if (mailFetch.IsAuthenticated)
                            {
                                mailFetch.Inbox.Open(FolderAccess.ReadOnly);
                                var mailIds = mailFetch.Inbox.Search(SearchQuery.NotSeen);
                                foreach (var id in mailIds)
                                {
                                    var mail = mailFetch.Inbox.GetMessage(id);
                                    var htmlDoc = new HtmlDocument();
                                    htmlDoc.LoadHtml(mail.HtmlBody);
                                    var context = htmlDoc.GetElementbyId("context")?.InnerText;
                                    if (context != null)
                                    {
                                        var entity = context;
                                    }
                                }
                            }
                        };
                    };
                }
                using (var done = new CancellationTokenSource())
                {
                    var task = client.IdleAsync(done.Token);
                    int timeout = client.Timeout;
                    while (true)
                    {
                        Thread.Sleep(10000);
                        if (client.IsIdle)
                        {
                            if (!client.Inbox.IsOpen)
                                client.Inbox.Open(FolderAccess.ReadOnly);
                           client.Idle(done.Token);
                        }
                    }
                    // done.Cancel();
                    // task.Wait();
                }
                //client.Disconnect(true);
            };
        }
        catch (Exception ex)
        {
            string exception = ex.Message;
            string innerexception = ex.InnerException.ToString();
        }
    }

1 ответ

Решение

Есть конструктор CancellationTokenSource, который принимает значение тайм-аута int, которое вы можете использовать. Я думаю, что это доступно для ASP.NET Core.

Если нет, попробуйте что-то более похожее на это:

while (true) {
    if (!client.Inbox.IsOpen)
        client.Inbox.Open(FolderAccess.ReadOnly);
    var task = client.IdleAsync (done.Token);
    Thread.Sleep(10000);
    done.Cancel();
    task.Wait();
}
Другие вопросы по тегам