diff --git a/packages/email-plugin/src/handler/event-handler.ts b/packages/email-plugin/src/handler/event-handler.ts index 773f8f651f..4764f0c153 100644 --- a/packages/email-plugin/src/handler/event-handler.ts +++ b/packages/email-plugin/src/handler/event-handler.ts @@ -14,6 +14,7 @@ import { LoadDataFn, SetAttachmentsFn, SetOptionalAddressFieldsFn, + SetSubjectFn, SetTemplateVarsFn, } from '../types'; @@ -135,6 +136,7 @@ import { export class EmailEventHandler { private setRecipientFn: (event: Event) => string; private setLanguageCodeFn: (event: Event) => LanguageCode | undefined; + private setSubjectFn?: SetSubjectFn; private setTemplateVarsFn: SetTemplateVarsFn; private setAttachmentsFn?: SetAttachmentsFn; private setOptionalAddressFieldsFn?: SetOptionalAddressFieldsFn; @@ -214,8 +216,12 @@ export class EmailEventHandler { - this.defaultSubject = defaultSubject; + setSubject(defaultSubject: string | SetSubjectFn): EmailEventHandler { + if (typeof defaultSubject === 'string') { + this.defaultSubject = defaultSubject; + } else { + this.setSubjectFn = defaultSubject; + } return this; } @@ -370,7 +376,11 @@ export class EmailEventHandler { let eventBus: EventBus; @@ -913,6 +915,53 @@ describe('EmailPlugin', () => { expect(transport.type).toBe('testing'); }); }); + + describe('Dynamic subject handling', () => { + it('With string', async () => { + const ctx = RequestContext.deserialize({ + _channel: { code: DEFAULT_CHANNEL_CODE }, + _languageCode: LanguageCode.en, + } as any); + const handler = new EmailEventListener('test') + .on(MockEvent) + .setFrom('"test from" ') + .setRecipient(() => 'test@test.com') + .setSubject('Hello') + .setTemplateVars(event => ({ subjectVar: 'foo' })); + + await initPluginWithHandlers([handler]); + + eventBus.publish(new MockEvent(ctx, true)); + await pause(); + expect(onSend.mock.calls[0][0].subject).toBe('Hello'); + expect(onSend.mock.calls[0][0].recipient).toBe('test@test.com'); + expect(onSend.mock.calls[0][0].from).toBe('"test from" '); + }); + it('With callback function', async () => { + const ctx = RequestContext.deserialize({ + _channel: { code: DEFAULT_CHANNEL_CODE }, + _languageCode: LanguageCode.en, + } as any); + const handler = new EmailEventListener('test') + .on(MockEvent) + .setFrom('"test from" ') + .setRecipient(() => 'test@test.com') + .setSubject(async (_e, _ctx, _i) => { + const service = _i.get(MockService) + const mockData = await service.someAsyncMethod() + return `Hello from ${mockData} and {{ subjectVar }}`; + }) + .setTemplateVars(event => ({ subjectVar: 'foo' })); + + await initPluginWithHandlers([handler]); + + eventBus.publish(new MockEvent(ctx, true)); + await pause(); + expect(onSend.mock.calls[0][0].subject).toBe('Hello from loaded data and foo'); + expect(onSend.mock.calls[0][0].recipient).toBe('test@test.com'); + expect(onSend.mock.calls[0][0].from).toBe('"test from" '); + }); + }) }); class FakeCustomSender implements EmailSender { @@ -931,4 +980,4 @@ class MockService { someAsyncMethod() { return Promise.resolve('loaded data'); } -} +} \ No newline at end of file diff --git a/packages/email-plugin/src/types.ts b/packages/email-plugin/src/types.ts index b1bc82a82e..6db628e7d6 100644 --- a/packages/email-plugin/src/types.ts +++ b/packages/email-plugin/src/types.ts @@ -4,9 +4,9 @@ import { Injector, RequestContext, SerializedRequestContext, VendureEvent } from import { Attachment } from 'nodemailer/lib/mailer'; import SESTransport from 'nodemailer/lib/ses-transport'; import SMTPTransport from 'nodemailer/lib/smtp-transport'; -import { EmailEventHandler } from './handler/event-handler'; import { EmailGenerator } from './generator/email-generator'; +import { EmailEventHandler } from './handler/event-handler'; import { EmailSender } from './sender/email-sender'; import { TemplateLoader } from './template-loader/template-loader'; @@ -387,6 +387,14 @@ export type SetTemplateVarsFn = ( */ export type SetAttachmentsFn = (event: Event) => EmailAttachment[] | Promise; +/** + * @description + * A function used to define the subject to be sent with the email. + * @docsCategory core plugins/EmailPlugin + * @docsPage Email Plugin Types + */ +export type SetSubjectFn = (event: Event, ctx: RequestContext, injector: Injector) => string | Promise; + /** * @description * Optional address-related fields for sending the email.