mirror of
https://github.com/bulwarkmail/webmail.git
synced 2026-11-01 08:12:43 +00:00
Message ids repeat across accounts, so a hook payload naming only an emailId could not tell a plugin which mailbox the message lies in when it is a shared or group account's. onBeforeEmailStarToggle and onEmailStarToggle now carry accountId when the starred message is not in the user's own account, as the message-row-actions click context does. Every star (the row's button, the reader's star, the key, the menu) goes through toggleStar, one message at a time, so one accountId names it; the account is resolved before the plugins are asked. An own message's payload is unchanged. onAfterEmailSend now carries accountId, the JMAP account the sent message lies in (a mail sent from a shared or group identity lies in that account), so api.email.get finds it. sendEmail returns that account as emailAccountId, the S/MIME send too. The hook also carries composerId, the id the sending composer's slots and actions gave plugins, so a plugin can act on what the user chose in that composer.
59 lines
2.2 KiB
TypeScript
59 lines
2.2 KiB
TypeScript
// @vitest-environment node
|
|
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
|
|
import { emailHooks, clearAllHooks } from '../plugin-hooks';
|
|
import { announceSent, cancelAnnouncedSend, releaseAnnouncedSend, resetAnnouncedSends } from '../plugin-after-send';
|
|
|
|
const message = { to: ['bob@example.com'], cc: [], bcc: [], subject: 'Hi' };
|
|
|
|
beforeEach(() => {
|
|
vi.useFakeTimers();
|
|
clearAllHooks();
|
|
resetAnnouncedSends();
|
|
});
|
|
afterEach(() => vi.useRealTimers());
|
|
|
|
describe('announceSent for a send held back for undo', () => {
|
|
const held = () => ({ scheduled: true, emailId: 'e1', emailSubmissionId: 's1', sendAt: new Date(Date.now() + 10_000).toISOString() });
|
|
|
|
it('reports when the hold runs out', () => {
|
|
const sent = vi.fn();
|
|
emailHooks.onAfterEmailSend.register('t', sent);
|
|
announceSent(held(), message);
|
|
vi.advanceTimersByTime(9_000);
|
|
expect(sent).not.toHaveBeenCalled();
|
|
vi.advanceTimersByTime(1_000);
|
|
expect(sent).toHaveBeenCalledWith({ emailId: 'e1', accountId: null, submissionId: 's1', ...message, scheduledFor: null, composerId: null });
|
|
});
|
|
|
|
it('reports at once on "Send now"', () => {
|
|
const sent = vi.fn();
|
|
emailHooks.onAfterEmailSend.register('t', sent);
|
|
announceSent(held(), message);
|
|
releaseAnnouncedSend('s1');
|
|
expect(sent).toHaveBeenCalledTimes(1);
|
|
vi.advanceTimersByTime(20_000);
|
|
expect(sent).toHaveBeenCalledTimes(1);
|
|
});
|
|
|
|
it('never reports an undone send', () => {
|
|
const sent = vi.fn();
|
|
emailHooks.onAfterEmailSend.register('t', sent);
|
|
announceSent(held(), message);
|
|
cancelAnnouncedSend('s1');
|
|
vi.advanceTimersByTime(20_000);
|
|
expect(sent).not.toHaveBeenCalled();
|
|
});
|
|
});
|
|
|
|
describe('announceSent names the message and the composer', () => {
|
|
it("gives the account the message lies in and the sending composer's id", () => {
|
|
const sent = vi.fn();
|
|
emailHooks.onAfterEmailSend.register('t', sent);
|
|
announceSent(
|
|
{ scheduled: false, emailId: 'e9', emailAccountId: 'group', emailSubmissionId: 's9' },
|
|
{ ...message, composerId: 'composer-1' },
|
|
);
|
|
expect(sent).toHaveBeenCalledWith(expect.objectContaining({ emailId: 'e9', accountId: 'group', composerId: 'composer-1' }));
|
|
});
|
|
});
|