···11# Changelog
2233# 2026-04-21
44+- **Fix: potential memory leak in background sync** — fixed infinite loop that occurred when IMAP errors (e.g., after suspend/resume) triggered immediate retry instead of waiting for next scheduled interval; `bgFetchInboxCmd()` now returns nil on error instead of `bgSyncTickMsg{}`, preventing tight loop that consumes large amounts of RAM; added `bgSyncInProgress` flag to prevent concurrent background syncs from piling up during slow network conditions
45- **Fix: reply-all excludes all own addresses** — `ctrl+r` reply-all now excludes all configured email addresses (accounts + sender aliases) from the CC field; previously only excluded the active account's address, causing your own email to appear in CC when the original email was sent to one of your other addresses
5667# 2026-04-18
+16-1
internal/ui/model.go
···490490 pendingReply bool
491491 pendingReplyAll bool
492492493493+ // bgSyncInProgress prevents concurrent background syncs from piling up
494494+ bgSyncInProgress bool
495495+493496 // Chord prefix: "g" or "M" while waiting for second key
494497 pendingKey string
495498···14341437 m.imapCli().ResetMailboxSelection() // force fresh SELECT to see new messages
14351438 emails, err := m.imapCli().FetchHeaders(nil, m.cfg.Folders.Inbox, m.cfg.UI.InboxCount)
14361439 if err != nil {
14371437- return bgSyncTickMsg{} // reschedule retry on next tick instead of errMsg
14401440+ // Return nil to let the next scheduled tick retry naturally.
14411441+ // Returning bgSyncTickMsg{} here creates an infinite loop on persistent errors!
14421442+ return bgInboxFetchedMsg{emails: nil} // signal completion even on error
14381443 }
14391444 return bgInboxFetchedMsg{emails: emails}
14401445 }
···19491954 return m, tea.Batch(m.spinner.Tick, m.fetchFolderCmd(m.activeFolder()))
1950195519511956 case bgSyncTickMsg:
19571957+ // Skip if a background sync is already in progress to prevent pileup.
19581958+ if m.bgSyncInProgress {
19591959+ return m, m.scheduleBgSync() // just reschedule the next tick
19601960+ }
19521961 // Fire background inbox fetch; reschedule next tick in parallel.
19621962+ m.bgSyncInProgress = true
19531963 return m, tea.Batch(m.bgFetchInboxCmd(), m.scheduleBgSync())
1954196419551965 case bgInboxFetchedMsg:
19661966+ m.bgSyncInProgress = false // clear flag regardless of success/failure
19671967+ if msg.emails == nil {
19681968+ // Error case (network down, etc.) - silently skip until next tick
19691969+ return m, nil
19701970+ }
19561971 if err := m.validateScreenerSafety(); err != nil {
19571972 m.status = err.Error()
19581973 m.isError = true