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();
}