From d4420cff7dc29bb33f9c802145af178c95b1b8d5 Mon Sep 17 00:00:00 2001 From: Abhinav Raut Date: Mon, 1 Dec 2025 01:33:50 +0530 Subject: [PATCH] feat(imap): add fallback for servers without ESEARCH support Check ESEARCH capability before using extended search options. For servers that don't support ESEARCH, fall back to using sequence numbers from AllSeqNums() instead of Min/Max range. Ref #181 --- internal/inbox/channel/email/imap.go | 29 +++++++++++++++++++++------- 1 file changed, 22 insertions(+), 7 deletions(-) diff --git a/internal/inbox/channel/email/imap.go b/internal/inbox/channel/email/imap.go index 1920326b..525e6d6f 100644 --- a/internal/inbox/channel/email/imap.go +++ b/internal/inbox/channel/email/imap.go @@ -112,23 +112,38 @@ func (e *Email) processMailbox(ctx context.Context, scanInboxSince time.Duration // searchMessages searches for messages in the specified time range. func (e *Email) searchMessages(client *imapclient.Client, since time.Time) (*imap.SearchData, error) { - searchCMD := client.Search(&imap.SearchCriteria{ + criteria := &imap.SearchCriteria{ Since: since, - }, - &imap.SearchOptions{ + } + + // Only use ESEARCH options if server supports it + var opts *imap.SearchOptions + if client.Caps().Has(imap.CapESearch) { + opts = &imap.SearchOptions{ ReturnMin: true, ReturnMax: true, ReturnAll: true, ReturnCount: true, - }, - ) - return searchCMD.Wait() + } + } + + return client.Search(criteria, opts).Wait() } // fetchAndProcessMessages fetches and processes messages based on the search results. func (e *Email) fetchAndProcessMessages(ctx context.Context, client *imapclient.Client, searchResults *imap.SearchData, inboxID int) error { seqSet := imap.SeqSet{} - seqSet.AddRange(searchResults.Min, searchResults.Max) + if searchResults.Min > 0 && searchResults.Max > 0 { + e.lo.Debug("using ESEARCH range", "min", searchResults.Min, "max", searchResults.Max, "inbox_id", inboxID) + seqSet.AddRange(searchResults.Min, searchResults.Max) + } else if seqNums := searchResults.AllSeqNums(); len(seqNums) > 0 { + e.lo.Debug("using SEARCH fallback (no ESEARCH support)", "count", len(seqNums), "inbox_id", inboxID) + seqSet.AddNum(seqNums...) + } else { + // No results found + e.lo.Debug("no messages found in search results", "inbox_id", inboxID) + return nil + } // Fetch envelope and headers needed for auto-reply detection. fetchOptions := &imap.FetchOptions{