Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 34 additions & 6 deletions fetcher/fetcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -1919,11 +1919,18 @@ func FetchFolders(account *config.Account) ([]Folder, error) {
}
defer c.Close() //nolint:errcheck

listCmd := c.List("", "*", &imap.ListOptions{
ReturnStatus: &imap.StatusOptions{
NumUnseen: true,
},
})
// Only request the unseen count inline via LIST ... RETURN (STATUS (UNSEEN))
// when the server advertises LIST-STATUS (RFC 5819). Servers without it
// (e.g. Proton Mail Bridge, Exchange Online) either reject the RETURN
// argument outright or send a reply go-imap can't parse (#1408). For those
// we fall back to a per-mailbox STATUS below.
hasListStatus := c.Caps().Has(imap.CapListStatus)
listOpts := &imap.ListOptions{}
if hasListStatus {
listOpts.ReturnStatus = &imap.StatusOptions{NumUnseen: true}
}

listCmd := c.List("", "*", listOpts)
defer listCmd.Close() //nolint:errcheck

var folders []Folder
Expand All @@ -1938,7 +1945,7 @@ func FetchFolders(account *config.Account) ([]Folder, error) {
}

var unread uint32
if data.Status != nil {
if data.Status != nil && data.Status.NumUnseen != nil {
unread = *data.Status.NumUnseen
}

Expand All @@ -1958,6 +1965,27 @@ func FetchFolders(account *config.Account) ([]Folder, error) {
return nil, err
}

// Without LIST-STATUS the LIST reply carries no unseen counts, so issue a
// STATUS per mailbox to populate them. Skip \Noselect folders, which can't
// be queried with STATUS.
if !hasListStatus {
for i := range folders {
if slices.Contains(folders[i].Attributes, string(imap.MailboxAttrNoSelect)) {
continue
}
status, err := c.Status(folders[i].Name, &imap.StatusOptions{NumUnseen: true}).Wait()
if err != nil {
// A single failing mailbox shouldn't abort the whole listing;
// leave its unread count at zero.
loglevel.Debugf("STATUS UNSEEN failed for %q: %v", folders[i].Name, err)
continue
}
if status.NumUnseen != nil {
folders[i].Unread = *status.NumUnseen
}
}
}

return folders, nil
}

Expand Down
Loading