Reply to a thread whose last message is one I sent, and the reply comes back to me: Reply puts my own address in To, and Reply all puts me in To with everyone I actually wrote to demoted to Cc. The people the conversation is with are never in To, and on a plain Reply they are not on the message at all.
Following up on your own last message is an ordinary thing to do, which is why this is worth a p1.
Why it happens
reply() in web/src/store/compose.ts does have a guard for this — it asks whether the address it is about to reply to is one of mine, and if so addresses the original recipients instead. The guard is sound; what it relies on is not. It tests membership of the identity list, and that test fails silently in several ordinary situations, each of which produces exactly the behaviour above.
Reproduced with a probe against the store — five distinct ways in, all giving To: me:
Situation
Why the guard misses it
Identity address stored with surrounding whitespace
isOwn compares with a lowercased includes, while the rest of the codebase uses sameAddress, which trims. A hand-typed identity address is enough.
Identities not loaded yet
The list is empty, so nothing is ever "mine".
Sent from an alias or shared mailbox Identity/get does not list
The address is genuinely absent from the list.
I was among the recipients as well as the sender
The Reply-all branch does not filter my own address out of To, though the Reply branch does.
My identity carries a Reply-To
The guard runs on the address it computed rather than on the sender, so a message of mine with a Reply-To skips the check entirely and my reply goes to my own desk address.
The fix
Ask the folder before asking the addresses. A message in Sent is mine whatever address it went out as, and that signal is already fetched — mailboxIds is in LIST_PROPS and roleId("sent") is available on the mail store. The address test stays as a second opinion, using sameAddress so whitespace stops mattering, and the whole thing keys off the sender rather than off the address the reply was about to go to, which is what fixes the Reply-To case.
Then: reply to the people I wrote to, drop my own address from both fields, and fall back sensibly when I addressed the thing only to myself or only in Cc.
Two cases stay unfixable and should be stated rather than hidden: a message sent from an alias that is neither in the identity list nor in Sent (moved to Archive, say), and any message at all when the identities failed to load and the message is not in Sent. Neither signal exists, so nothing can be inferred. Both are much narrower than what is broken today.
Not covered here
There are no tests over reply addressing at all — compose-as-new and forward-as-attachment have suites, reply does not. That is how a guard this load-bearing came to be wrong in five ways at once, and the fix should arrive with them.
Rebuilt from: GH Archive, session transcript.
Reply to a thread whose last message is one I sent, and the reply comes back to me: **Reply** puts my own address in To, and **Reply all** puts me in To with everyone I actually wrote to demoted to Cc. The people the conversation is with are never in To, and on a plain Reply they are not on the message at all.
Following up on your own last message is an ordinary thing to do, which is why this is worth a p1.
## Why it happens
`reply()` in `web/src/store/compose.ts` does have a guard for this — it asks whether the address it is about to reply to is one of mine, and if so addresses the original recipients instead. The guard is sound; what it relies on is not. It tests membership of the identity list, and that test fails silently in several ordinary situations, each of which produces exactly the behaviour above.
Reproduced with a probe against the store — five distinct ways in, all giving `To: me`:
| Situation | Why the guard misses it |
| --- | --- |
| Identity address stored with surrounding whitespace | `isOwn` compares with a lowercased `includes`, while the rest of the codebase uses `sameAddress`, which trims. A hand-typed identity address is enough. |
| Identities not loaded yet | The list is empty, so nothing is ever "mine". |
| Sent from an alias or shared mailbox `Identity/get` does not list | The address is genuinely absent from the list. |
| I was among the recipients as well as the sender | The Reply-all branch does not filter my own address out of To, though the Reply branch does. |
| My identity carries a Reply-To | The guard runs on the address it computed rather than on the sender, so a message of mine with a Reply-To skips the check entirely and my reply goes to my own desk address. |
## The fix
Ask the folder before asking the addresses. A message in Sent is mine whatever address it went out as, and that signal is already fetched — `mailboxIds` is in `LIST_PROPS` and `roleId("sent")` is available on the mail store. The address test stays as a second opinion, using `sameAddress` so whitespace stops mattering, and the whole thing keys off the *sender* rather than off the address the reply was about to go to, which is what fixes the Reply-To case.
Then: reply to the people I wrote to, drop my own address from both fields, and fall back sensibly when I addressed the thing only to myself or only in Cc.
**Two cases stay unfixable and should be stated rather than hidden**: a message sent from an alias that is neither in the identity list *nor* in Sent (moved to Archive, say), and any message at all when the identities failed to load and the message is not in Sent. Neither signal exists, so nothing can be inferred. Both are much narrower than what is broken today.
## Not covered here
There are no tests over reply addressing at all — `compose-as-new` and `forward-as-attachment` have suites, `reply` does not. That is how a guard this load-bearing came to be wrong in five ways at once, and the fix should arrive with them.
<sub>Rebuilt from: GH Archive, session transcript.</sub>
What shipped. The folder is asked before the addresses: a message in Sent is mine whatever address it went out as. mailboxIds is already in LIST_PROPS and roleId("sent") is on the mail store, so it costs no extra request. The identity list stays as a second opinion, compared with sameAddress instead of a lowercased includes, and the whole test keys off the sender rather than the address the reply was about to go to — which is what fixes the Reply-To case, where the check was being skipped entirely.
Replying to something I sent now writes to the people I wrote to, drops my own address from both fields, and falls back sensibly when the message was addressed only to me or only in Cc.
What is still unanswerable, and is commented in the code rather than papered over: a message from an alias that is neither in the identity list nor in Sent (moved to Archive, say), and any message at all when identities failed to load and it is not in Sent. Neither signal exists, so nothing can be inferred. Both are far narrower than what was broken, but they are not nothing — if a reply from an archived alias message comes back addressed to the alias, that is this, not a regression.
The gap that let five bugs accumulate. Reply addressing had no tests at all — compose-as-new and forward-as-attachment had suites, reply had none. There are 15 now. Seven fail against the old code; the other eight cover behaviour that was already correct — replying to somebody else's message, honouring their Reply-To, forwarding addressing nobody — so the change is fenced on both sides rather than only pushed forward.
Closed by #276 and live now as `2026.9.4+pr276`.
**What shipped.** The folder is asked before the addresses: a message in Sent is mine whatever address it went out as. `mailboxIds` is already in `LIST_PROPS` and `roleId("sent")` is on the mail store, so it costs no extra request. The identity list stays as a second opinion, compared with `sameAddress` instead of a lowercased `includes`, and the whole test keys off the *sender* rather than the address the reply was about to go to — which is what fixes the Reply-To case, where the check was being skipped entirely.
Replying to something I sent now writes to the people I wrote to, drops my own address from both fields, and falls back sensibly when the message was addressed only to me or only in Cc.
**What is still unanswerable**, and is commented in the code rather than papered over: a message from an alias that is neither in the identity list nor in Sent (moved to Archive, say), and any message at all when identities failed to load and it is not in Sent. Neither signal exists, so nothing can be inferred. Both are far narrower than what was broken, but they are not nothing — if a reply from an archived alias message comes back addressed to the alias, that is this, not a regression.
**The gap that let five bugs accumulate.** Reply addressing had no tests at all — `compose-as-new` and `forward-as-attachment` had suites, `reply` had none. There are 15 now. Seven fail against the old code; the other eight cover behaviour that was already correct — replying to somebody else's message, honouring *their* Reply-To, forwarding addressing nobody — so the change is fenced on both sides rather than only pushed forward.
What shipped. The folder is asked before the addresses: a message in Sent is mine whatever address it went out as. mailboxIds is already in LIST_PROPS and roleId("sent") is on the mail store, so it costs no extra request. The identity list stays as a second opinion, compared with sameAddress instead of a lowercased includes, and the whole test keys off the sender rather than the address the reply was about to go to — which is what fixes the Reply-To case, where the check was being skipped entirely.
Replying to something I sent now writes to the people I wrote to, drops my own address from both fields, and falls back sensibly when the message was addressed only to me or only in Cc.
What is still unanswerable, and is commented in the code rather than papered over: a message from an alias that is neither in the identity list nor in Sent (moved to Archive, say), and any message at all when identities failed to load and it is not in Sent. Neither signal exists, so nothing can be inferred. Both are far narrower than what was broken, but they are not nothing — if a reply from an archived alias message comes back addressed to the alias, that is this, not a regression.
The gap that let five bugs accumulate. Reply addressing had no tests at all — compose-as-new and forward-as-attachment had suites, reply had none. There are 15 now. Seven fail against the old code; the other eight cover behaviour that was already correct — replying to somebody else's message, honouring their Reply-To, forwarding addressing nobody — so the change is fenced on both sides rather than only pushed forward.
Closed by #276 and live now as `2026.9.4+pr276`.
**What shipped.** The folder is asked before the addresses: a message in Sent is mine whatever address it went out as. `mailboxIds` is already in `LIST_PROPS` and `roleId("sent")` is on the mail store, so it costs no extra request. The identity list stays as a second opinion, compared with `sameAddress` instead of a lowercased `includes`, and the whole test keys off the *sender* rather than the address the reply was about to go to — which is what fixes the Reply-To case, where the check was being skipped entirely.
Replying to something I sent now writes to the people I wrote to, drops my own address from both fields, and falls back sensibly when the message was addressed only to me or only in Cc.
**What is still unanswerable**, and is commented in the code rather than papered over: a message from an alias that is neither in the identity list nor in Sent (moved to Archive, say), and any message at all when identities failed to load and it is not in Sent. Neither signal exists, so nothing can be inferred. Both are far narrower than what was broken, but they are not nothing — if a reply from an archived alias message comes back addressed to the alias, that is this, not a regression.
**The gap that let five bugs accumulate.** Reply addressing had no tests at all — `compose-as-new` and `forward-as-attachment` had suites, `reply` had none. There are 15 now. Seven fail against the old code; the other eight cover behaviour that was already correct — replying to somebody else's message, honouring *their* Reply-To, forwarding addressing nobody — so the change is fenced on both sides rather than only pushed forward.
This repo is archived. You cannot comment on issues.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Reply to a thread whose last message is one I sent, and the reply comes back to me: Reply puts my own address in To, and Reply all puts me in To with everyone I actually wrote to demoted to Cc. The people the conversation is with are never in To, and on a plain Reply they are not on the message at all.
Following up on your own last message is an ordinary thing to do, which is why this is worth a p1.
Why it happens
reply()inweb/src/store/compose.tsdoes have a guard for this — it asks whether the address it is about to reply to is one of mine, and if so addresses the original recipients instead. The guard is sound; what it relies on is not. It tests membership of the identity list, and that test fails silently in several ordinary situations, each of which produces exactly the behaviour above.Reproduced with a probe against the store — five distinct ways in, all giving
To: me:isOwncompares with a lowercasedincludes, while the rest of the codebase usessameAddress, which trims. A hand-typed identity address is enough.Identity/getdoes not listThe fix
Ask the folder before asking the addresses. A message in Sent is mine whatever address it went out as, and that signal is already fetched —
mailboxIdsis inLIST_PROPSandroleId("sent")is available on the mail store. The address test stays as a second opinion, usingsameAddressso whitespace stops mattering, and the whole thing keys off the sender rather than off the address the reply was about to go to, which is what fixes the Reply-To case.Then: reply to the people I wrote to, drop my own address from both fields, and fall back sensibly when I addressed the thing only to myself or only in Cc.
Two cases stay unfixable and should be stated rather than hidden: a message sent from an alias that is neither in the identity list nor in Sent (moved to Archive, say), and any message at all when the identities failed to load and the message is not in Sent. Neither signal exists, so nothing can be inferred. Both are much narrower than what is broken today.
Not covered here
There are no tests over reply addressing at all —
compose-as-newandforward-as-attachmenthave suites,replydoes not. That is how a guard this load-bearing came to be wrong in five ways at once, and the fix should arrive with them.Rebuilt from: GH Archive, session transcript.
Closed by #276 and live now as
2026.9.4+pr276.What shipped. The folder is asked before the addresses: a message in Sent is mine whatever address it went out as.
mailboxIdsis already inLIST_PROPSandroleId("sent")is on the mail store, so it costs no extra request. The identity list stays as a second opinion, compared withsameAddressinstead of a lowercasedincludes, and the whole test keys off the sender rather than the address the reply was about to go to — which is what fixes the Reply-To case, where the check was being skipped entirely.Replying to something I sent now writes to the people I wrote to, drops my own address from both fields, and falls back sensibly when the message was addressed only to me or only in Cc.
What is still unanswerable, and is commented in the code rather than papered over: a message from an alias that is neither in the identity list nor in Sent (moved to Archive, say), and any message at all when identities failed to load and it is not in Sent. Neither signal exists, so nothing can be inferred. Both are far narrower than what was broken, but they are not nothing — if a reply from an archived alias message comes back addressed to the alias, that is this, not a regression.
The gap that let five bugs accumulate. Reply addressing had no tests at all —
compose-as-newandforward-as-attachmenthad suites,replyhad none. There are 15 now. Seven fail against the old code; the other eight cover behaviour that was already correct — replying to somebody else's message, honouring their Reply-To, forwarding addressing nobody — so the change is fenced on both sides rather than only pushed forward.Closed by #276 and live now as
2026.9.4+pr276.What shipped. The folder is asked before the addresses: a message in Sent is mine whatever address it went out as.
mailboxIdsis already inLIST_PROPSandroleId("sent")is on the mail store, so it costs no extra request. The identity list stays as a second opinion, compared withsameAddressinstead of a lowercasedincludes, and the whole test keys off the sender rather than the address the reply was about to go to — which is what fixes the Reply-To case, where the check was being skipped entirely.Replying to something I sent now writes to the people I wrote to, drops my own address from both fields, and falls back sensibly when the message was addressed only to me or only in Cc.
What is still unanswerable, and is commented in the code rather than papered over: a message from an alias that is neither in the identity list nor in Sent (moved to Archive, say), and any message at all when identities failed to load and it is not in Sent. Neither signal exists, so nothing can be inferred. Both are far narrower than what was broken, but they are not nothing — if a reply from an archived alias message comes back addressed to the alias, that is this, not a regression.
The gap that let five bugs accumulate. Reply addressing had no tests at all —
compose-as-newandforward-as-attachmenthad suites,replyhad none. There are 15 now. Seven fail against the old code; the other eight cover behaviour that was already correct — replying to somebody else's message, honouring their Reply-To, forwarding addressing nobody — so the change is fenced on both sides rather than only pushed forward.