Skip to content

Fix IMAP connection exhaustion under burst of searches#69

Merged
rockfordlhotka merged 2 commits into
mainfrom
fix/imap-connection-reuse
Jun 9, 2026
Merged

Fix IMAP connection exhaustion under burst of searches#69
rockfordlhotka merged 2 commits into
mainfrom
fix/imap-connection-reuse

Conversation

@rockfordlhotka

Copy link
Copy Markdown
Member

Problem

A burst of repeated search_emails calls (e.g. 5 searches in ~90s) hangs for the full request timeout against Gmail. Each IMAP read/mutation operation opened a brand-new connection, ran a fresh AUTHENTICATE, then closed it via Dispose() without a graceful LOGOUT. Abruptly-dropped connections linger server-side against Gmail's per-account simultaneous-connection limit, and Gmail throttles repeated AUTHENTICATE. The burst exhausts the limit/trips the throttle and stalls the next AUTHENTICATE, so subsequent calls hang. send_email was unaffected because its SMTP path (and IMAP append) already disconnected gracefully.

Fix

ImapProviderService now keeps and reuses a single authenticated IMAP connection per account:

  • Per-account SemaphoreSlim gate serializes access (an ImapClient runs one command at a time).
  • NOOP health-check before reuse; transparent reconnect if dead, plus a single reconnect-and-retry if a reused connection breaks mid-operation.
  • Graceful DisconnectAsync(true) (LOGOUT) on eviction and on shutdown via new IAsyncDisposable/IDisposable.
  • All read/mutation ops + the APPEND-to-Sent step of send_email route through the pool.

This removes the throttled repeated AUTHENTICATE round-trips and prevents connection-slot exhaustion.

Notes

  • Pooling serializes IMAP calls per account — desirable here to stay within Gmail's connection limits; concurrent same-account requests queue rather than open parallel connections.
  • Version bumped 1.4.0 → 1.4.1 (patch, bug fix). Changelog added.

Testing

  • dotnet build clean (only pre-existing warnings).
  • All 275 tests pass.

rockfordlhotka and others added 2 commits June 9, 2026 11:31
IMAP read/mutation operations opened a fresh connection per call and closed
it via Dispose() without a graceful LOGOUT. Lingering connections plus repeated
AUTHENTICATE attempts hit Gmail's per-account connection limit/throttle, stalling
subsequent AUTHENTICATE calls so rapid searches hung for the full timeout.

Reuse a single authenticated IMAP connection per account behind a per-account
gate, with NOOP health-check, reconnect-and-retry on a broken reused connection,
and graceful DisconnectAsync(true) on eviction/shutdown via IAsyncDisposable.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@rockfordlhotka rockfordlhotka merged commit fe76057 into main Jun 9, 2026
1 check passed
@rockfordlhotka rockfordlhotka deleted the fix/imap-connection-reuse branch June 9, 2026 16:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant