email-processor.ts 2.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364
  1. import { InternalServerError } from '@vendure/core';
  2. import fs from 'fs-extra';
  3. import { isDevModeOptions } from './common';
  4. import { EmailSender } from './email-sender';
  5. import { HandlebarsMjmlGenerator } from './handlebars-mjml-generator';
  6. import { TemplateLoader } from './template-loader';
  7. import { EmailPluginOptions, EmailTransportOptions, IntermediateEmailDetails } from './types';
  8. /**
  9. * This class combines the template loading, generation, and email sending - the actual "work" of
  10. * the EmailPlugin. It is arranged this way primarily to accomodate easier testing, so that the
  11. * tests can be run without needing all the JobQueue stuff which would require a full e2e test.
  12. */
  13. export class EmailProcessor {
  14. protected templateLoader: TemplateLoader;
  15. protected emailSender: EmailSender;
  16. protected generator: HandlebarsMjmlGenerator;
  17. protected transport: EmailTransportOptions;
  18. constructor(protected options: EmailPluginOptions) {}
  19. async init() {
  20. this.templateLoader = new TemplateLoader(this.options.templatePath);
  21. this.emailSender = new EmailSender();
  22. this.generator = new HandlebarsMjmlGenerator();
  23. if (this.generator.onInit) {
  24. await this.generator.onInit.call(this.generator, this.options);
  25. }
  26. if (isDevModeOptions(this.options)) {
  27. this.transport = {
  28. type: 'file',
  29. raw: false,
  30. outputPath: this.options.outputPath,
  31. };
  32. } else {
  33. if (!this.options.transport) {
  34. throw new InternalServerError(
  35. `When devMode is not set to true, the 'transport' property must be set.`,
  36. );
  37. }
  38. this.transport = this.options.transport;
  39. }
  40. if (this.transport.type === 'file') {
  41. // ensure the configured directory exists before
  42. // we attempt to write files to it
  43. const emailPath = this.transport.outputPath;
  44. await fs.ensureDir(emailPath);
  45. }
  46. }
  47. async process(data: IntermediateEmailDetails) {
  48. const bodySource = await this.templateLoader.loadTemplate(data.type, data.templateFile);
  49. const generated = await this.generator.generate(
  50. data.from,
  51. data.subject,
  52. bodySource,
  53. data.templateVars,
  54. );
  55. const emailDetails = { ...generated, recipient: data.recipient };
  56. await this.emailSender.send(emailDetails, this.transport);
  57. return true;
  58. }
  59. }