Imap flow.

This commit is contained in:
Burak Kaan Köse
2026-04-19 20:13:09 +02:00
parent 496c7735f7
commit 3bd0b69429
16 changed files with 277 additions and 24 deletions
+8 -3
View File
@@ -58,6 +58,7 @@ public class ImapClientPool : IDisposable
private readonly int _targetMinimumConnections;
private DateTime _lastKeepAliveSentUtc = DateTime.MinValue;
private Exception _lastConnectionException;
private WinoImapClient _dedicatedIdleClient;
private bool _disposedValue;
private bool _initialized;
@@ -114,7 +115,7 @@ public class ImapClientPool : IDisposable
var initialClient = await CreateAndConnectClientAsync(cancellationToken).ConfigureAwait(false);
if (initialClient == null)
{
throw CreatePoolException("Failed to create initial IMAP connection for the pool.");
throw CreatePoolException("Failed to create initial IMAP connection for the pool.", _lastConnectionException);
}
_clientStates[initialClient] = ImapClientState.Available;
@@ -192,6 +193,7 @@ public class ImapClientPool : IDisposable
}
catch (Exception ex)
{
_lastConnectionException = ex;
_logger.Warning(ex, "Pooled IMAP client was not ready. Marking as failed.");
MarkClientAsFailed(pooledClient);
}
@@ -215,12 +217,12 @@ public class ImapClientPool : IDisposable
}
catch (OperationCanceledException) when (!cancellationToken.IsCancellationRequested)
{
throw CreatePoolException($"Timed out while acquiring an IMAP client after {timeout.TotalSeconds:F1} seconds. Failures: {createFailures}.");
throw CreatePoolException($"Timed out while acquiring an IMAP client after {timeout.TotalSeconds:F1} seconds. Failures: {createFailures}.", _lastConnectionException);
}
throw cancellationToken.IsCancellationRequested
? new OperationCanceledException(cancellationToken)
: CreatePoolException($"Failed to acquire IMAP client within {timeout.TotalSeconds:F1} seconds. Failures: {createFailures}.");
: CreatePoolException($"Failed to acquire IMAP client within {timeout.TotalSeconds:F1} seconds. Failures: {createFailures}.", _lastConnectionException);
}
/// <summary>
@@ -516,14 +518,17 @@ public class ImapClientPool : IDisposable
private async Task<WinoImapClient> CreateAndConnectClientAsync(CancellationToken cancellationToken)
{
var client = CreateNewClient();
_lastConnectionException = null;
try
{
await EnsureClientReadyAsync(client, cancellationToken).ConfigureAwait(false);
_lastConnectionException = null;
return client;
}
catch (Exception ex)
{
_lastConnectionException = ex;
_logger.Warning(ex, "Failed to create and connect IMAP client.");
DisposeClient(client);
return null;
@@ -11,6 +11,7 @@ using Serilog;
using Wino.Core.Domain.Interfaces;
using Wino.Core.Domain.Models;
using Wino.Core.Domain.Models.AutoDiscovery;
using Wino.Core.Domain.Validation;
namespace Wino.Core.Services;
@@ -450,6 +451,9 @@ public class AutoDiscoveryService : IAutoDiscoveryService
private async Task<bool> HasAnyDnsAddressRecordAsync(string host, CancellationToken cancellationToken)
{
if (MailAccountAddressValidator.IsImplicitlyResolvableHost(host))
return true;
var aRecords = await QueryDnsAsync(host, "A", cancellationToken).ConfigureAwait(false);
if (aRecords.Count > 0)
return true;
+1 -1
View File
@@ -123,7 +123,7 @@ public class SynchronizationManager : ISynchronizationManager, IRecipient<Accoun
catch (ImapClientPoolException clientPoolException)
{
_logger.Error(clientPoolException, "IMAP connectivity test failed");
return ImapConnectivityTestResults.Failure(clientPoolException);
return ImapConnectivityTestResults.Failure(clientPoolException.InnerException ?? clientPoolException);
}
catch (Exception exception)
{