Replying to a thread whose last message I sent addressed the reply back to me — Reply put my own address in To, Reply all put me in To and demoted everyone I had actually written to into Cc.
There was already a guard for this, and the guard was sound. What it rested on was not: it asked whether an address was in the identity list, and that question has a wrong answer in more situations than it has a right one.
The five ways in
Situation
Why the guard missed it
Identities not loaded yet
Empty list, so nothing is ever mine
Alias or shared mailbox Identity/get does not list
The address genuinely isn't there
Identity address stored with whitespace
Compared lowercased strings with includes, where the rest of the codebase uses sameAddress
My own message carries a Reply-To
The check ran on the address the reply was headed for, not on the sender, so it was skipped — my reply went to my own desk
I was among my own recipients
Reply all never filtered my address out of To, though Reply did
Every one failed silently. That is how five accumulated.
What changed
Ask the folder first. 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 this costs no extra request. The identity list stays as a second opinion, compared with sameAddress, and the whole test keys off the sender rather than the computed recipient — 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 the message was addressed only to me or only in Cc.
What is still unanswerable
Stated in a comment rather than papered over — a message from an unlisted alias that is also not 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.
Tests
Reply addressing had no tests at all — compose-as-new and forward-as-attachment have suites, reply had none. There are now 15, and 7 of them fail against the old code. The other 8 cover behaviour that was already correct (replying to somebody else's message, honouring their Reply-To, forwarding addressing nobody), so the fix is fenced in on both sides.
1049 web tests, 142 server tests, typecheck clean.
Fixes #275.
Replying to a thread whose last message I sent addressed the reply back to me — **Reply** put my own address in To, **Reply all** put me in To and demoted everyone I had actually written to into Cc.
There was already a guard for this, and the guard was sound. What it rested on was not: it asked whether an address was in the identity list, and that question has a wrong answer in more situations than it has a right one.
## The five ways in
| Situation | Why the guard missed it |
| --- | --- |
| Identities not loaded yet | Empty list, so nothing is ever mine |
| Alias or shared mailbox `Identity/get` does not list | The address genuinely isn't there |
| Identity address stored with whitespace | Compared lowercased strings with `includes`, where the rest of the codebase uses `sameAddress` |
| My own message carries a Reply-To | The check ran on the address the reply was headed for, not on the sender, so it was skipped — my reply went to my own desk |
| I was among my own recipients | Reply all never filtered my address out of To, though Reply did |
Every one failed silently. That is how five accumulated.
## What changed
**Ask the folder first.** 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 this costs no extra request. The identity list stays as a second opinion, compared with `sameAddress`, and the whole test keys off the *sender* rather than the computed recipient — 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 the message was addressed only to me or only in Cc.
## What is still unanswerable
Stated in a comment rather than papered over — a message from an unlisted alias that is *also* not 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.
## Tests
Reply addressing had **no tests at all** — `compose-as-new` and `forward-as-attachment` have suites, `reply` had none. There are now 15, and **7 of them fail against the old code**. The other 8 cover behaviour that was already correct (replying to somebody else's message, honouring *their* Reply-To, forwarding addressing nobody), so the fix is fenced in on both sides.
1049 web tests, 142 server tests, typecheck clean.
**Merged** 2026-09-04 as coffey-labs/ihasmail@f201b09e90c6
<sub>Rebuilt from: git history, session transcript.</sub>
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.
Fixes #275.
Replying to a thread whose last message I sent addressed the reply back to me — Reply put my own address in To, Reply all put me in To and demoted everyone I had actually written to into Cc.
There was already a guard for this, and the guard was sound. What it rested on was not: it asked whether an address was in the identity list, and that question has a wrong answer in more situations than it has a right one.
The five ways in
Identity/getdoes not listincludes, where the rest of the codebase usessameAddressEvery one failed silently. That is how five accumulated.
What changed
Ask the folder first. A message in Sent is mine whatever address it went out as.
mailboxIdsis already inLIST_PROPSandroleId("sent")is on the mail store, so this costs no extra request. The identity list stays as a second opinion, compared withsameAddress, and the whole test keys off the sender rather than the computed recipient — 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 the message was addressed only to me or only in Cc.
What is still unanswerable
Stated in a comment rather than papered over — a message from an unlisted alias that is also not 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.
Tests
Reply addressing had no tests at all —
compose-as-newandforward-as-attachmenthave suites,replyhad none. There are now 15, and 7 of them fail against the old code. The other 8 cover behaviour that was already correct (replying to somebody else's message, honouring their Reply-To, forwarding addressing nobody), so the fix is fenced in on both sides.1049 web tests, 142 server tests, typecheck clean.
Merged 2026-09-04 as coffey-labs/ihasmail@f201b09e90
Rebuilt from: git history, session transcript.