From 7f78d4837a47a0728d9d9db2ccbd67819cb59273 Mon Sep 17 00:00:00 2001 From: Linus Rath <139418639+rathlinus@users.noreply.github.com> Date: Tue, 6 Oct 2026 23:31:03 +0200 Subject: [PATCH] fix: don't offer the auto-reply audience on a shared account #1152 --- .../settings/__tests__/vacation-forward.test.tsx | 10 ++++++++++ components/settings/vacation-settings.tsx | 6 ++++-- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/components/settings/__tests__/vacation-forward.test.tsx b/components/settings/__tests__/vacation-forward.test.tsx index ffc1cc568..3c1fed339 100644 --- a/components/settings/__tests__/vacation-forward.test.tsx +++ b/components/settings/__tests__/vacation-forward.test.tsx @@ -8,6 +8,7 @@ import { STALWART_VACATION_SCRIPT, mockStalwartAccount } from '@/lib/filters/__t import { useAuthStore } from '@/stores/auth-store'; import { useFilterStore } from '@/stores/filter-store'; import { useIdentityStore } from '@/stores/identity-store'; +import { useManagedAccountStore } from '@/stores/managed-account-store'; import { useVacationStore } from '@/stores/vacation-store'; import { VacationSettings } from '../vacation-settings'; @@ -62,6 +63,7 @@ const initial = { vacation: useVacationStore.getState(), filter: useFilterStore.getState(), identity: useIdentityStore.getState(), + managed: useManagedAccountStore.getState(), }; beforeEach(() => { toast.error.mockClear(); @@ -72,6 +74,7 @@ afterEach(() => { useVacationStore.setState(initial.vacation, true); useFilterStore.setState(initial.filter, true); useIdentityStore.setState(initial.identity, true); + useManagedAccountStore.setState(initial.managed, true); }); async function openCard(server: ReturnType) { @@ -390,6 +393,13 @@ describe('who gets the auto-reply, in the vacation card', () => { expect(screen.queryByRole('combobox', { name: 'audience.label' })).toBeNull(); }); + it('is not offered on a shared account, whose domains the signed-in identities do not tell', async () => { + withIdentities(); + useManagedAccountStore.setState({ managedAccountId: 'b' } as never); + await openCard(stalwart([rule('a')])); + expect(screen.queryByRole('combobox', { name: 'audience.label' })).toBeNull(); + }); + it('answers external senders only', async () => { withIdentities(); const server = stalwart([rule('a')]); diff --git a/components/settings/vacation-settings.tsx b/components/settings/vacation-settings.tsx index 20c48a0f9..523f61534 100644 --- a/components/settings/vacation-settings.tsx +++ b/components/settings/vacation-settings.tsx @@ -167,8 +167,10 @@ export function VacationSettings() { }; // Who gets the auto-reply as a save stores it: everyone, or the senders - // from (or not from) the account's domains as they are now. - const canNarrow = audienceAvailable && domains.length > 0; + // from (or not from) the account's domains as they are now. The domains + // come from the signed-in user's identities, so a managed (shared) account + // offers no narrowing rather than one built from the wrong domains. + const canNarrow = audienceAvailable && !managedAccountId && domains.length > 0; const audienceSettings = !canNarrow ? undefined : audienceOnly === 'all' ? null : { only: audienceOnly, domains };