Improve IMAP reconnection and error handling in polling
Refactored PollInboxAsync to better handle IMAP connection drops and protocol errors by reconnecting and resuming processing as needed. Switched from using a using statement to explicit disposal in a finally block. Now logs and recovers from transient IMAP issues, and ensures proper cancellation handling by rethrowing OperationCanceledException. This increases service robustness and reliability.
This commit is contained in:
@@ -90,7 +90,9 @@ public sealed partial class InboxMonitorService : BackgroundService
|
||||
|
||||
private async Task PollInboxAsync(CancellationToken ct)
|
||||
{
|
||||
using var client = await _imapFactory.CreateConnectedClientAsync(_imap, ct);
|
||||
var client = await _imapFactory.CreateConnectedClientAsync(_imap, ct);
|
||||
try
|
||||
{
|
||||
var inbox = client.Inbox;
|
||||
await inbox.OpenAsync(FolderAccess.ReadWrite, ct);
|
||||
|
||||
@@ -130,6 +132,10 @@ public sealed partial class InboxMonitorService : BackgroundService
|
||||
{
|
||||
await ProcessMessageAsync(inbox, uid, spamFolder, ct);
|
||||
}
|
||||
catch (OperationCanceledException) when (ct.IsCancellationRequested)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "Error processing UID={Uid}", uid.Id);
|
||||
@@ -140,6 +146,17 @@ public sealed partial class InboxMonitorService : BackgroundService
|
||||
Uid = uid.Id, AccountName = AccountName
|
||||
});
|
||||
_processedUids.Add(uid.Id);
|
||||
|
||||
// Reconnect if the server dropped the connection (e.g. unexpected response after MoveToAsync)
|
||||
if (!client.IsConnected || ex is MailKit.Net.Imap.ImapProtocolException)
|
||||
{
|
||||
_logger.LogWarning("IMAP connection lost for {Account}, reconnecting", AccountName);
|
||||
try { client.Dispose(); } catch { }
|
||||
client = await _imapFactory.CreateConnectedClientAsync(_imap, ct);
|
||||
inbox = client.Inbox;
|
||||
await inbox.OpenAsync(FolderAccess.ReadWrite, ct);
|
||||
spamFolder = await FindSpamFolderAsync(client, ct);
|
||||
}
|
||||
}
|
||||
|
||||
if (uid.Id > _lastSeenUid) _lastSeenUid = uid.Id;
|
||||
@@ -147,6 +164,11 @@ public sealed partial class InboxMonitorService : BackgroundService
|
||||
|
||||
await client.DisconnectAsync(true, ct);
|
||||
}
|
||||
finally
|
||||
{
|
||||
client.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
private async Task ProcessMessageAsync(
|
||||
IMailFolder inbox, UniqueId uid, IMailFolder? spamFolder, CancellationToken ct)
|
||||
|
||||
Reference in New Issue
Block a user