Skip to content

fix(parse): report a tagged NO/BAD instead of an empty result - #146

Open
giacomomasseron wants to merge 1 commit into
chatmail:mainfrom
giacomomasseron:fix/report-tagged-no-instead-of-empty-result
Open

giacomomasseron wants to merge 1 commit into
chatmail:mainfrom
giacomomasseron:fix/report-tagged-no-instead-of-empty-result

Conversation

@giacomomasseron

Copy link
Copy Markdown

The problem

parse_ids, parse_capabilities, parse_noop and parse_metadata end the
response stream at the command's tag without reading the completion status:

// parse.rs, filter_sync
Response::Done { tag, .. } => tag != command_tag,

So a command the server refused returns success with nothing in it. A
SEARCH answered NO reaches the caller as Ok({}).

For a client that is not a difference it can defend against: an empty set is
also the normal answer to "nothing matched", so both outcomes arrive as the
same value. Concretely, a refused UID SEARCH X-GM-LABELS "SomeLabel" reads as
"no message carries that label", and a client that syncs labels then writes
that conclusion back - dropping labels the user set in the Gmail web UI. The
same shape affects CAPABILITY, NOOP and GETMETADATA.

parse_status and parse_mailbox already return Error::No / Error::Bad
here. This brings the other parsers in line with them.

The change

One helper, command_completion, returning Ok(()) for OK and
Error::No / Error::Bad for a refusal - the same arms parse_status
already has - consulted by the four collect-style parsers.

Deliberately unchanged:

  • A stream that ends without a tagged completion still succeeds. Several
    existing tests (parse_ids_test, parse_ids_search, parse_capability_test)
    feed exactly that shape and expect Ok.
  • Another command's completion is still ignored rather than failing ours -
    the case fixed in 8cdd3dc for LOGIN. Covered by a test here.

Tests

  • a tagged NO on SEARCH is an error, not an empty result
  • a tagged BAD on CAPABILITY is an error
  • another command's NO in the same stream does not fail ours

Not included

parse_names, parse_fetches and parse_expunge return streams rather than
collecting, so surfacing a refusal there means yielding a final Err item
instead of ending the stream early. That is a larger change to the pipeline and
I left it out to keep this reviewable. Happy to follow up in the same shape if
you would like it.

parse_ids, parse_capabilities, parse_noop and parse_metadata ended the
response stream at the command tag without reading its completion status,
so a command the server refused returned success with no data. A SEARCH
answered NO reached the caller as Ok({}) - the very value the server
sends when nothing matched, leaving callers no way to tell the two
apart.

Add command_completion, mirroring the status arms parse_status and
parse_mailbox already have, and consult it in those four parsers.

Unchanged on purpose: a stream that ends without a tagged completion
still succeeds (several existing tests feed exactly that shape), and
another command's completion is still ignored rather than failing ours
(8cdd3dc).

Tests: a tagged NO on SEARCH is an error; a tagged BAD on CAPABILITY is
an error; another command's NO in the same stream does not fail ours.
@hpk42

hpk42 commented Oct 1, 2026 •

Copy link
Copy Markdown
Contributor

sorry for talking a bit to get back. it generally looks ok on first read, could you rebase?

sidenote: please make sure to always write all commit messages and PR descriptions by hand, see also https://delta.chat/en/community-standards#collective-maintenance-standards . thanks.

@giacomomasseron

Copy link
Copy Markdown
Author

@hpk42 I can rebase, but honestly I can not go deep explaining the change, because my rust knowledge is limited.
I used Claude for this PR.

I understand your point, I think it's better for me to close this PR and open an issue about the problem.

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.

2 participants