Skip to content

imap: read_thread rejects a bare Message-ID the contract says it accepts #1924

Open

Description

@sharpca

What's broken

imap_source.read_thread rejects a bare Message-ID ([email protected]),
although the mail-source contract says that form is accepted on input.

Which layer

tools/mail-source/imap/ — the read_thread operation of
contract:mail-source.

How to reproduce

$ imap-source-read [email protected]
reading thread [email protected] in INBOX on imap.example.org
thread [email protected] not found in INBOX

The same id with its brackets resolves:

$ imap-source-read '<[email protected]>'

maildir's read_thread accepts both spellings — _thread_key brackets a bare
id before the lookup — so the two backends disagree on their own input.

Expected vs actual

Expected. tools/mail-source/contract.md § Thread identity (added in
#1811):

An id typed without brackets is accepted on input and normalised to the
bracketed form; it is never emitted.

Actual. read_thread compares the argument verbatim against
position.message_id, which is always bracketed
(imap_source.threads.normalise_message_id), so a bare id matches nothing.

Impact. Automated callers are unaffected: list_recent_threads only emits
the bracketed form, so a tracker field written from it round-trips. This bites a
human typing the id, and a tracker field edited by hand.

Surface area (optional)

imap_source.read_thread. imap_source.thread_url takes the same argument and
should be checked in the same pass.

Suggested fix: normalise at the entry point with
imap_source.threads.normalise_message_id, and add a test next to
test_read_thread_declares_missing_root.

Found while implementing #1919 (PR #1922); left out of that PR to keep it to the
issue's scope.

Activity

  1. xiaobai0529 commented on Nov 1, 2026

    @xiaobai0529
    Contributor

    AI-generated comment on behalf of @xiaobai0529:

    I would like to work on this issue. The mismatch is reproducible from the current code: read_thread compares the caller-supplied ID verbatim, while the mail-source contract says bare and bracketed Message-IDs are the same input form. I plan to normalize at the operation boundary, check thread_url in the same pass, and add regression coverage for both forms across string and CLI-facing entry points.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions