Adds two iCloud-specific, provider-scoped policies that build on the
existing shared throttling framework (#360's AccountThrottleGate, #356's
BackfillPacer) without refactoring either:
- IcloudConnectionLimiter: a per-account permit gate capping an iCloud
account at 5 simultaneous connections (Apple documents 5-8; pinned to
the conservative low end). Wired into MailBackfiller around both
connection-opening call sites (the header-page fetch and the
body/attachment prefetch loop - the "1 + K + attachments" per-page
connection count issue #363 describes). A no-op passthrough for every
other provider, so it composes cleanly with #360's reactive backoff
(already consulted first, per account) and #356's slice pacing
(BackfillWorker composes BackfillPacer.runPaced around
MailBackfiller.runBackfill, so the cap sits one layer beneath the
pacer's cooldown/cap in the same call graph).
- IcloudSendLimits: enforces Apple's ~20 MB outgoing message-size cap
before SmtpSender ever opens a connection, estimating the actual
encoded wire size (base64 inflates binary attachment bytes by ~4/3)
rather than comparing raw file bytes, mirroring GraphSender's existing
pre-send attachment-size guard. An over-cap send throws
MessageTooLargeException, caught by SendWorker's existing runCatching
and turned into a clean, PII-free outbox error - no crash, no raw
provider rejection.
Both are new, self-contained files kept intentionally separate from a
shared cross-provider table, per the parallel-safety note on this ticket
(sibling issues #361/#362/#364 add their own provider's limits the same
way).
Touches two shared files: MailBackfiller.kt (new constructor dependency
+ two call sites wrapped in icloudConnectionLimiter.withPermit) and
SendWorker.kt (one guard call before smtpSender.send). Both are
minimal, additive edits — flagged for conflict-awareness with the
sibling provider tickets.
Also excludes MailBackfillerTest.kt from detekt's LargeClass rule
(config/detekt/detekt.yml), mirroring the existing MailRepositoryImplTest
exclusion: one cohesive single-SUT suite tipped over the LLOC boundary
by the new connection-cap wiring tests.
Closes#363