Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 1c00512661 |
@@ -90,62 +90,84 @@ public sealed partial class InboxMonitorService : BackgroundService
|
|||||||
|
|
||||||
private async Task PollInboxAsync(CancellationToken ct)
|
private async Task PollInboxAsync(CancellationToken ct)
|
||||||
{
|
{
|
||||||
using var client = await _imapFactory.CreateConnectedClientAsync(_imap, ct);
|
var client = await _imapFactory.CreateConnectedClientAsync(_imap, ct);
|
||||||
var inbox = client.Inbox;
|
try
|
||||||
await inbox.OpenAsync(FolderAccess.ReadWrite, ct);
|
{
|
||||||
|
var inbox = client.Inbox;
|
||||||
|
await inbox.OpenAsync(FolderAccess.ReadWrite, ct);
|
||||||
|
|
||||||
// Build search query: only fetch new messages
|
// Build search query: only fetch new messages
|
||||||
IList<UniqueId> uids;
|
IList<UniqueId> uids;
|
||||||
if (_lastSeenUid > 0)
|
if (_lastSeenUid > 0)
|
||||||
{
|
|
||||||
var range = new UniqueIdRange(new UniqueId(_lastSeenUid + 1), UniqueId.MaxValue);
|
|
||||||
uids = await inbox.SearchAsync(range, SearchQuery.All, ct);
|
|
||||||
}
|
|
||||||
else if (_processedUids.Count > 0)
|
|
||||||
{
|
|
||||||
// Resuming from persisted state -- scan recent messages only
|
|
||||||
uids = await inbox.SearchAsync(
|
|
||||||
SearchQuery.DeliveredAfter(DateTime.UtcNow.AddDays(-1)), ct);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// First ever run -- initial scan window
|
|
||||||
uids = await inbox.SearchAsync(
|
|
||||||
SearchQuery.DeliveredAfter(DateTime.UtcNow.AddDays(-_monitoring.InitialScanDays)), ct);
|
|
||||||
}
|
|
||||||
_logger.LogDebug("Found {Count} messages in inbox", uids.Count);
|
|
||||||
|
|
||||||
// Find the spam/junk folder
|
|
||||||
var spamFolder = await FindSpamFolderAsync(client, ct);
|
|
||||||
|
|
||||||
foreach (var uid in uids)
|
|
||||||
{
|
|
||||||
if (_processedUids.Contains(uid.Id))
|
|
||||||
{
|
{
|
||||||
if (uid.Id > _lastSeenUid) _lastSeenUid = uid.Id;
|
var range = new UniqueIdRange(new UniqueId(_lastSeenUid + 1), UniqueId.MaxValue);
|
||||||
continue;
|
uids = await inbox.SearchAsync(range, SearchQuery.All, ct);
|
||||||
}
|
}
|
||||||
|
else if (_processedUids.Count > 0)
|
||||||
try
|
|
||||||
{
|
{
|
||||||
await ProcessMessageAsync(inbox, uid, spamFolder, ct);
|
// Resuming from persisted state -- scan recent messages only
|
||||||
|
uids = await inbox.SearchAsync(
|
||||||
|
SearchQuery.DeliveredAfter(DateTime.UtcNow.AddDays(-1)), ct);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
else
|
||||||
{
|
{
|
||||||
_logger.LogError(ex, "Error processing UID={Uid}", uid.Id);
|
// First ever run -- initial scan window
|
||||||
_activityLog.Add(new ActivityEntry
|
uids = await inbox.SearchAsync(
|
||||||
|
SearchQuery.DeliveredAfter(DateTime.UtcNow.AddDays(-_monitoring.InitialScanDays)), ct);
|
||||||
|
}
|
||||||
|
_logger.LogDebug("Found {Count} messages in inbox", uids.Count);
|
||||||
|
|
||||||
|
// Find the spam/junk folder
|
||||||
|
var spamFolder = await FindSpamFolderAsync(client, ct);
|
||||||
|
|
||||||
|
foreach (var uid in uids)
|
||||||
|
{
|
||||||
|
if (_processedUids.Contains(uid.Id))
|
||||||
{
|
{
|
||||||
Timestamp = DateTime.UtcNow, Sender = "", Subject = $"UID {uid.Id}",
|
if (uid.Id > _lastSeenUid) _lastSeenUid = uid.Id;
|
||||||
Verdict = Verdict.Error, Reason = ex.Message,
|
continue;
|
||||||
Uid = uid.Id, AccountName = AccountName
|
}
|
||||||
});
|
|
||||||
_processedUids.Add(uid.Id);
|
try
|
||||||
|
{
|
||||||
|
await ProcessMessageAsync(inbox, uid, spamFolder, ct);
|
||||||
|
}
|
||||||
|
catch (OperationCanceledException) when (ct.IsCancellationRequested)
|
||||||
|
{
|
||||||
|
throw;
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogError(ex, "Error processing UID={Uid}", uid.Id);
|
||||||
|
_activityLog.Add(new ActivityEntry
|
||||||
|
{
|
||||||
|
Timestamp = DateTime.UtcNow, Sender = "", Subject = $"UID {uid.Id}",
|
||||||
|
Verdict = Verdict.Error, Reason = ex.Message,
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (uid.Id > _lastSeenUid) _lastSeenUid = uid.Id;
|
await client.DisconnectAsync(true, ct);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
client.Dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
await client.DisconnectAsync(true, ct);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task ProcessMessageAsync(
|
private async Task ProcessMessageAsync(
|
||||||
|
|||||||
Reference in New Issue
Block a user