fix(email): restore the sender identity when reopening a draft
Reopening a draft reset the composer's From to the default identity. The edit-draft handler matched the draft's saved From against the active-account identity list by email only, so two identities sharing an address (a default + an alias differing by name) collided — the wrong one was picked, or with cross-account namespaced ids none was. Add findDraftIdentityId (name+email, normalized, +tag fallback) and match against the same list the composer renders (the flat cross-account list when multi- account is on). Wired into both the classic and Pro edit-draft paths. Unit tests plus the un-pinned 07-drafts integration spec.
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
import { describe, expect, it } from 'vitest';
|
||||
import { findComposeIdentityId, findReplyIdentityId, resolveReplyFrom } from '../reply-identity';
|
||||
import { findComposeIdentityId, findDraftIdentityId, findReplyIdentityId, resolveReplyFrom } from '../reply-identity';
|
||||
import type { Identity } from '../jmap/types';
|
||||
|
||||
const identities: Identity[] = [
|
||||
@@ -17,6 +17,36 @@ const identities: Identity[] = [
|
||||
},
|
||||
];
|
||||
|
||||
describe('findDraftIdentityId', () => {
|
||||
// Two identities on the SAME address, differing only by display name — the
|
||||
// reopen-draft regression: an email-only match picks the default, not the one
|
||||
// the draft was written with.
|
||||
const sameAddress: Identity[] = [
|
||||
{ id: 'default', name: 'Harry Primary', email: 'harry@primary.com', mayDelete: false },
|
||||
{ id: 'team', name: 'Harry Team', email: 'harry@primary.com', mayDelete: false },
|
||||
];
|
||||
|
||||
it('restores the exact identity by name when several share an address', () => {
|
||||
expect(findDraftIdentityId(sameAddress, { name: 'Harry Team', email: 'harry@primary.com' })).toBe('team');
|
||||
expect(findDraftIdentityId(sameAddress, { name: 'Harry Primary', email: 'harry@primary.com' })).toBe('default');
|
||||
});
|
||||
|
||||
it('matches by email (normalized) when the name is absent or unique', () => {
|
||||
expect(findDraftIdentityId(identities, { email: 'HARRY@Secondary.com' })).toBe('secondary');
|
||||
expect(findDraftIdentityId(identities, { name: 'Whatever', email: 'harry@secondary.com' })).toBe('secondary');
|
||||
});
|
||||
|
||||
it('falls back to the +tag-stripped base address', () => {
|
||||
expect(findDraftIdentityId(identities, { email: 'harry+promo@secondary.com' })).toBe('secondary');
|
||||
});
|
||||
|
||||
it('returns null when nothing matches or there is no From', () => {
|
||||
expect(findDraftIdentityId(identities, { email: 'nobody@elsewhere.com' })).toBeNull();
|
||||
expect(findDraftIdentityId(identities, null)).toBeNull();
|
||||
expect(findDraftIdentityId([], { email: 'harry@primary.com' })).toBeNull();
|
||||
});
|
||||
});
|
||||
|
||||
describe('findReplyIdentityId', () => {
|
||||
it('matches the identity that received the original message', () => {
|
||||
const selected = findReplyIdentityId(identities, {
|
||||
|
||||
Reference in New Issue
Block a user