From 09eb34e8fe23648d5050cf8f868d13767b0cf3b2 Mon Sep 17 00:00:00 2001 From: lsimone Date: Wed, 25 Sep 2019 16:04:08 +0200 Subject: [PATCH] feat(email-plugin): Added `from` field to the email config (#168) * feat(email-plugin): Added `from` field to the email config * test(email-plugin): Fix tests and raise error for missing field --- .../src/default-email-handlers.ts | 18 +++++++++++-- packages/email-plugin/src/email-sender.ts | 2 ++ packages/email-plugin/src/event-listener.ts | 26 ++++++++++++++++--- .../src/handlebars-mjml-generator.ts | 10 +++---- .../email-plugin/src/noop-email-generator.ts | 8 ++---- packages/email-plugin/src/plugin.spec.ts | 25 ++++++++++++++++++ packages/email-plugin/src/plugin.ts | 7 ++++- packages/email-plugin/src/types.ts | 2 ++ 8 files changed, 79 insertions(+), 19 deletions(-) diff --git a/packages/email-plugin/src/default-email-handlers.ts b/packages/email-plugin/src/default-email-handlers.ts index 2e1f6fae9e..d1306ed507 100644 --- a/packages/email-plugin/src/default-email-handlers.ts +++ b/packages/email-plugin/src/default-email-handlers.ts @@ -1,13 +1,24 @@ /* tslint:disable:no-non-null-assertion */ -import { AccountRegistrationEvent, IdentifierChangeRequestEvent, OrderStateTransitionEvent, PasswordResetEvent } from '@vendure/core'; +import { + AccountRegistrationEvent, + IdentifierChangeRequestEvent, + OrderStateTransitionEvent, + PasswordResetEvent, +} from '@vendure/core'; import { EmailEventListener } from './event-listener'; -import { mockAccountRegistrationEvent, mockEmailAddressChangeEvent, mockOrderStateTransitionEvent, mockPasswordResetEvent } from './mock-events'; +import { + mockAccountRegistrationEvent, + mockEmailAddressChangeEvent, + mockOrderStateTransitionEvent, + mockPasswordResetEvent, +} from './mock-events'; export const orderConfirmationHandler = new EmailEventListener('order-confirmation') .on(OrderStateTransitionEvent) .filter(event => event.toState === 'PaymentSettled' && !!event.order.customer) .setRecipient(event => event.order.customer!.emailAddress) + .setFrom(`{{ fromAddress }}`) .setSubject(`Order confirmation for #{{ order.code }}`) .setTemplateVars(event => ({ order: event.order })) .setMockEvent(mockOrderStateTransitionEvent); @@ -15,6 +26,7 @@ export const orderConfirmationHandler = new EmailEventListener('order-confirmati export const emailVerificationHandler = new EmailEventListener('email-verification') .on(AccountRegistrationEvent) .setRecipient(event => event.user.identifier) + .setFrom(`{{ fromAddress }}`) .setSubject(`Please verify your email address`) .setTemplateVars(event => ({ user: event.user })) .setMockEvent(mockAccountRegistrationEvent); @@ -22,6 +34,7 @@ export const emailVerificationHandler = new EmailEventListener('email-verificati export const passwordResetHandler = new EmailEventListener('password-reset') .on(PasswordResetEvent) .setRecipient(event => event.user.identifier) + .setFrom(`{{ fromAddress }}`) .setSubject(`Forgotten password reset`) .setTemplateVars(event => ({ user: event.user })) .setMockEvent(mockPasswordResetEvent); @@ -29,6 +42,7 @@ export const passwordResetHandler = new EmailEventListener('password-reset') export const emailAddressChangeHandler = new EmailEventListener('email-address-change') .on(IdentifierChangeRequestEvent) .setRecipient(event => event.user.pendingIdentifier!) + .setFrom(`{{ fromAddress }}`) .setSubject(`Please verify your change of email address`) .setTemplateVars(event => ({ user: event.user })) .setMockEvent(mockEmailAddressChangeEvent); diff --git a/packages/email-plugin/src/email-sender.ts b/packages/email-plugin/src/email-sender.ts index 4f35fc4f31..37eede7554 100644 --- a/packages/email-plugin/src/email-sender.ts +++ b/packages/email-plugin/src/email-sender.ts @@ -66,6 +66,7 @@ export class EmailSender { private async sendMail(email: EmailDetails, transporter: Mail): Promise { return transporter.sendMail({ + from: email.from, to: email.recipient, subject: email.subject, html: email.body, @@ -75,6 +76,7 @@ export class EmailSender { private async sendFileJson(email: EmailDetails, pathWithoutExt: string) { const output = { date: new Date().toLocaleString(), + from: email.from, recipient: email.recipient, subject: email.subject, body: email.body, diff --git a/packages/email-plugin/src/event-listener.ts b/packages/email-plugin/src/event-listener.ts index 74ee60252b..0fde0b0699 100644 --- a/packages/email-plugin/src/event-listener.ts +++ b/packages/email-plugin/src/event-listener.ts @@ -117,6 +117,7 @@ export class EmailEventHandler boolean> = []; private configurations: EmailTemplateConfig[] = []; private defaultSubject: string; + private from: string; private _mockEvent: Omit | undefined; constructor(public listener: EmailEventListener, public event: Type) {} @@ -170,6 +171,16 @@ export class EmailEventHandler { + this.from = from; + return this; + } + /** * @description * Add configuration for another template other than the default `"body.hbs"`. Use this method to define specific @@ -189,7 +200,9 @@ export class EmailEventHandler { .on(MockEvent) .filter(event => event.shouldSend === true) .setRecipient(() => 'test@test.com') + .setFrom('"test from" ') .setSubject('test subject'); const module = await initPluginWithHandlers([handler]); @@ -74,6 +75,7 @@ describe('EmailPlugin', () => { .on(MockEvent) .filter(event => event.shouldSend === true) .filter(event => !!event.ctx.user) + .setFrom('"test from" ') .setRecipient(() => 'test@test.com') .setSubject('test subject'); @@ -99,6 +101,7 @@ describe('EmailPlugin', () => { it('interpolates subject', async () => { const handler = new EmailEventListener('test') .on(MockEvent) + .setFrom('"test from" ') .setRecipient(() => 'test@test.com') .setSubject('Hello {{ subjectVar }}') .setTemplateVars(event => ({ subjectVar: 'foo' })); @@ -114,6 +117,7 @@ describe('EmailPlugin', () => { it('interpolates body', async () => { const handler = new EmailEventListener('test') .on(MockEvent) + .setFrom('"test from" ') .setRecipient(() => 'test@test.com') .setSubject('Hello') .setTemplateVars(event => ({ testVar: 'this is the test var' })); @@ -129,6 +133,7 @@ describe('EmailPlugin', () => { it('interpolates globalTemplateVars', async () => { const handler = new EmailEventListener('test') .on(MockEvent) + .setFrom('"test from" ') .setRecipient(() => 'test@test.com') .setSubject('Hello {{ globalVar }}'); @@ -142,9 +147,27 @@ describe('EmailPlugin', () => { await module.close(); }); + it('interpolates from', async () => { + const handler = new EmailEventListener('test') + .on(MockEvent) + .setFrom('"test from {{ globalVar }}" ') + .setRecipient(() => 'test@test.com') + .setSubject('Hello'); + + const module = await initPluginWithHandlers([handler], { + globalTemplateVars: { globalVar: 'baz' }, + }); + + eventBus.publish(new MockEvent(ctx, true)); + await pause(); + expect(onSend.mock.calls[0][0].from).toBe('"test from baz" '); + await module.close(); + }); + it('globalTemplateVars available in setTemplateVars method', async () => { const handler = new EmailEventListener('test') .on(MockEvent) + .setFrom('"test from" ') .setRecipient(() => 'test@test.com') .setSubject('Hello {{ testVar }}') .setTemplateVars((event, globals) => ({ testVar: globals.globalVar + ' quux' })); @@ -162,6 +185,7 @@ describe('EmailPlugin', () => { it('setTemplateVars overrides globals', async () => { const handler = new EmailEventListener('test') .on(MockEvent) + .setFrom('"test from" ') .setRecipient(() => 'test@test.com') .setSubject('Hello {{ name }}') .setTemplateVars((event, globals) => ({ name: 'quux' })); @@ -184,6 +208,7 @@ describe('EmailPlugin', () => { it('additional LanguageCode', async () => { const handler = new EmailEventListener('test') .on(MockEvent) + .setFrom('"test from" ') .setSubject('Hello, {{ name }}!') .setRecipient(() => 'test@test.com') .setTemplateVars(() => ({ name: 'Test' })) diff --git a/packages/email-plugin/src/plugin.ts b/packages/email-plugin/src/plugin.ts index 50d9916cba..cb84b47316 100644 --- a/packages/email-plugin/src/plugin.ts +++ b/packages/email-plugin/src/plugin.ts @@ -230,7 +230,12 @@ export class EmailPlugin implements OnVendureBootstrap, OnVendureClose { return; } const bodySource = await this.templateLoader.loadTemplate(type, result.templateFile); - const generated = await this.generator.generate(result.subject, bodySource, result.templateVars); + const generated = await this.generator.generate( + result.from, + result.subject, + bodySource, + result.templateVars, + ); const emailDetails = { ...generated, recipient: result.recipient }; await this.emailSender.send(emailDetails, this.transport); } diff --git a/packages/email-plugin/src/types.ts b/packages/email-plugin/src/types.ts index 61b46e75df..ac6950808e 100644 --- a/packages/email-plugin/src/types.ts +++ b/packages/email-plugin/src/types.ts @@ -206,6 +206,7 @@ export interface NoopTransportOptions { * @docsPage Email Plugin Types */ export interface EmailDetails { + from: string; recipient: string; subject: string; body: string; @@ -244,6 +245,7 @@ export interface EmailGenerator