types.ts 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394
  1. import { LanguageCode } from '@vendure/common/lib/generated-types';
  2. import { Omit } from '@vendure/common/lib/omit';
  3. import { Injector, RequestContext, VendureEvent } from '@vendure/core';
  4. import { Attachment } from 'nodemailer/lib/mailer';
  5. import SMTPTransport from 'nodemailer/lib/smtp-transport';
  6. import { EmailGenerator } from './email-generator';
  7. import { EmailSender } from './email-sender';
  8. import { EmailEventHandler } from './event-handler';
  9. import SESTransport from 'nodemailer/lib/ses-transport'
  10. /**
  11. * @description
  12. * A VendureEvent which also includes a `ctx` property containing the current
  13. * {@link RequestContext}, which is used to determine the channel and language
  14. * to use when generating the email.
  15. *
  16. * @docsCategory EmailPlugin
  17. * @docsPage Email Plugin Types
  18. */
  19. export type EventWithContext = VendureEvent & { ctx: RequestContext };
  20. /**
  21. * @description
  22. * A VendureEvent with a {@link RequestContext} and a `data` property which contains the
  23. * value resolved from the {@link EmailEventHandler}`.loadData()` callback.
  24. *
  25. * @docsCategory EmailPlugin
  26. * @docsPage Email Plugin Types
  27. */
  28. export type EventWithAsyncData<Event extends EventWithContext, R> = Event & { data: R };
  29. /**
  30. * @description
  31. * Configuration for the EmailPlugin.
  32. *
  33. * @docsCategory EmailPlugin
  34. * @docsPage EmailPluginOptions
  35. * */
  36. export interface EmailPluginOptions {
  37. /**
  38. * @description
  39. * The path to the location of the email templates. In a default Vendure installation,
  40. * the templates are installed to `<project root>/vendure/email/templates`.
  41. */
  42. templatePath: string;
  43. /**
  44. * @description
  45. * Configures how the emails are sent.
  46. */
  47. transport: EmailTransportOptions;
  48. /**
  49. * @description
  50. * An array of {@link EmailEventHandler}s which define which Vendure events will trigger
  51. * emails, and how those emails are generated.
  52. */
  53. handlers: Array<EmailEventHandler<string, any>>;
  54. /**
  55. * @description
  56. * An object containing variables which are made available to all templates. For example,
  57. * the storefront URL could be defined here and then used in the "email address verification"
  58. * email.
  59. */
  60. globalTemplateVars?: { [key: string]: any };
  61. /**
  62. * @description
  63. * An optional allowed EmailSender, used to allow custom implementations of the send functionality
  64. * while still utilizing the existing emailPlugin functionality.
  65. *
  66. * @default NodemailerEmailSender
  67. */
  68. emailSender?: EmailSender;
  69. /**
  70. * @description
  71. * An optional allowed EmailGenerator, used to allow custom email generation functionality to
  72. * better match with custom email sending functionality.
  73. *
  74. * @default HandlebarsMjmlGenerator
  75. */
  76. emailGenerator?: EmailGenerator;
  77. }
  78. /**
  79. * @description
  80. * Configuration for running the EmailPlugin in development mode.
  81. *
  82. * @docsCategory EmailPlugin
  83. * @docsPage EmailPluginOptions
  84. */
  85. export interface EmailPluginDevModeOptions extends Omit<EmailPluginOptions, 'transport'> {
  86. devMode: true;
  87. /**
  88. * @description
  89. * The path to which html email files will be saved rather than being sent.
  90. */
  91. outputPath: string;
  92. /**
  93. * @description
  94. * The route to the dev mailbox server.
  95. */
  96. route: string;
  97. }
  98. /**
  99. * @description
  100. * A union of all the possible transport options for sending emails.
  101. *
  102. * @docsCategory EmailPlugin
  103. * @docsPage Transport Options
  104. */
  105. export type EmailTransportOptions =
  106. | SMTPTransportOptions
  107. | SendmailTransportOptions
  108. | FileTransportOptions
  109. | NoopTransportOptions
  110. | SESTransportOptions
  111. | TestingTransportOptions;
  112. /**
  113. * @description
  114. * The SMTP transport options of [Nodemailer](https://nodemailer.com/smtp/)
  115. *
  116. * @docsCategory EmailPlugin
  117. * @docsPage Transport Options
  118. */
  119. export interface SMTPTransportOptions extends SMTPTransport.Options {
  120. type: 'smtp';
  121. /**
  122. * @description
  123. * If true, uses the configured {@link VendureLogger} to log messages from Nodemailer as it interacts with
  124. * the SMTP server.
  125. *
  126. * @default false
  127. */
  128. logging?: boolean;
  129. }
  130. /**
  131. * @description
  132. * The SES transport options of [Nodemailer](https://nodemailer.com/transports/ses//)
  133. *
  134. * See [Nodemailers's SES docs](https://nodemailer.com/transports/ses/) for more details
  135. *
  136. * @example
  137. * ```TypeScript
  138. * import { SES, SendRawEmailCommand } from '\@aws-sdk/client-ses'
  139. *
  140. * const ses = new SES({
  141. * apiVersion: '2010-12-01',
  142. * region: 'eu-central-1',
  143. * credentials: {
  144. * accessKeyId: process.env.SES_ACCESS_KEY || '',
  145. * secretAccessKey: process.env.SES_SECRET_KEY || '',
  146. * },
  147. * })
  148. *
  149. * const config: VendureConfig = {
  150. * // Add an instance of the plugin to the plugins array
  151. * plugins: [
  152. * EmailPlugin.init({
  153. * handlers: defaultEmailHandlers,
  154. * templatePath: path.join(__dirname, 'static/email/templates'),
  155. * transport: {
  156. * type: 'ses',
  157. * SES: { ses, aws: { SendRawEmailCommand } },
  158. * sendingRate: 10, // optional messages per second sending rate
  159. * },
  160. * }),
  161. * ],
  162. * };
  163. * ```
  164. * @docsCategory EmailPlugin
  165. * @docsPage Transport Options
  166. */
  167. export interface SESTransportOptions extends SESTransport.Options {
  168. type: 'ses';
  169. }
  170. /**
  171. * @description
  172. * Uses the local Sendmail program to send the email.
  173. *
  174. * @docsCategory EmailPlugin
  175. * @docsPage Transport Options
  176. */
  177. export interface SendmailTransportOptions {
  178. type: 'sendmail';
  179. /** path to the sendmail command (defaults to ‘sendmail’) */
  180. path?: string;
  181. /** either ‘windows’ or ‘unix’ (default). Forces all newlines in the output to either use Windows syntax <CR><LF> or Unix syntax <LF> */
  182. newline?: string;
  183. }
  184. /**
  185. * @description
  186. * Outputs the email as an HTML file for development purposes.
  187. *
  188. * @docsCategory EmailPlugin
  189. * @docsPage Transport Options
  190. */
  191. export interface FileTransportOptions {
  192. type: 'file';
  193. /** The directory in which the emails will be saved */
  194. outputPath: string;
  195. /** When set to true, a raw text file will be output rather than an HTML file */
  196. raw?: boolean;
  197. }
  198. /**
  199. * @description
  200. * Does nothing with the generated email. Intended for use in testing where we don't care about the email transport,
  201. * or when using a custom {@link EmailSender} which does not require transport options.
  202. *
  203. * @docsCategory EmailPlugin
  204. * @docsPage Transport Options
  205. */
  206. export interface NoopTransportOptions {
  207. type: 'none';
  208. }
  209. /**
  210. * @description
  211. * The final, generated email details to be sent.
  212. *
  213. * @docsCategory EmailPlugin
  214. * @docsPage Email Plugin Types
  215. */
  216. export interface EmailDetails<Type extends 'serialized' | 'unserialized' = 'unserialized'> {
  217. from: string;
  218. recipient: string;
  219. subject: string;
  220. body: string;
  221. attachments: Array<Type extends 'serialized' ? SerializedAttachment : Attachment>;
  222. cc?: string;
  223. bcc?: string;
  224. replyTo?: string;
  225. }
  226. /**
  227. * @description
  228. * Forwards the raw GeneratedEmailContext object to a provided callback, for use in testing.
  229. *
  230. * @docsCategory EmailPlugin
  231. * @docsPage Transport Options
  232. */
  233. export interface TestingTransportOptions {
  234. type: 'testing';
  235. /**
  236. * @description
  237. * Callback to be invoked when an email would be sent.
  238. */
  239. onSend: (details: EmailDetails) => void;
  240. }
  241. /**
  242. * @description
  243. * A function used to load async data for use by an {@link EmailEventHandler}.
  244. *
  245. * @docsCategory EmailPlugin
  246. * @docsPage Email Plugin Types
  247. */
  248. export type LoadDataFn<Event extends EventWithContext, R> = (context: {
  249. event: Event;
  250. injector: Injector;
  251. }) => Promise<R>;
  252. export type OptionalToNullable<O> = {
  253. [K in keyof O]-?: undefined extends O[K] ? NonNullable<O[K]> | null : O[K];
  254. };
  255. /**
  256. * @description
  257. * An object defining a file attachment for an email. Based on the object described
  258. * [here in the Nodemailer docs](https://nodemailer.com/message/attachments/), but
  259. * only uses the `path` property to define a filesystem path or a URL pointing to
  260. * the attachment file.
  261. *
  262. * @docsCategory EmailPlugin
  263. * @docsPage Email Plugin Types
  264. */
  265. export type EmailAttachment = Omit<Attachment, 'raw'> & { path?: string };
  266. export type SerializedAttachment = OptionalToNullable<
  267. Omit<EmailAttachment, 'content'> & { content: string | null }
  268. >;
  269. export type IntermediateEmailDetails = {
  270. type: string;
  271. from: string;
  272. recipient: string;
  273. templateVars: any;
  274. subject: string;
  275. templateFile: string;
  276. attachments: SerializedAttachment[];
  277. cc?: string;
  278. bcc?: string;
  279. replyTo?: string;
  280. };
  281. /**
  282. * @description
  283. * Configures the {@link EmailEventHandler} to handle a particular channel & languageCode
  284. * combination.
  285. *
  286. * @docsCategory EmailPlugin
  287. * @docsPage Email Plugin Types
  288. */
  289. export interface EmailTemplateConfig {
  290. /**
  291. * @description
  292. * Specifies the channel to which this configuration will apply. If set to `'default'`, it will be applied to all
  293. * channels.
  294. */
  295. channelCode: string | 'default';
  296. /**
  297. * @description
  298. * Specifies the languageCode to which this configuration will apply. If set to `'default'`, it will be applied to all
  299. * languages.
  300. */
  301. languageCode: LanguageCode | 'default';
  302. /**
  303. * @description
  304. * Defines the file name of the Handlebars template file to be used to when generating this email.
  305. */
  306. templateFile: string;
  307. /**
  308. * @description
  309. * A string defining the email subject line. Handlebars variables defined in the `templateVars` object may
  310. * be used inside the subject.
  311. */
  312. subject: string;
  313. }
  314. /**
  315. * @description
  316. * A function used to define template variables available to email templates.
  317. * See {@link EmailEventHandler}.setTemplateVars().
  318. *
  319. * @docsCategory EmailPlugin
  320. * @docsPage Email Plugin Types
  321. */
  322. export type SetTemplateVarsFn<Event> = (
  323. event: Event,
  324. globals: { [key: string]: any },
  325. ) => { [key: string]: any };
  326. /**
  327. * @description
  328. * A function used to define attachments to be sent with the email.
  329. * See https://nodemailer.com/message/attachments/ for more information about
  330. * how attachments work in Nodemailer.
  331. *
  332. * @docsCategory EmailPlugin
  333. * @docsPage Email Plugin Types
  334. */
  335. export type SetAttachmentsFn<Event> = (event: Event) => EmailAttachment[] | Promise<EmailAttachment[]>;
  336. /**
  337. * @description
  338. * Optional address-related fields for sending the email.
  339. *
  340. * @since 1.1.0
  341. * @docsCategory EmailPlugin
  342. * @docsPage Email Plugin Types
  343. */
  344. export interface OptionalAddressFields {
  345. /**
  346. * @description
  347. * Comma separated list of recipients email addresses that will appear on the _Cc:_ field
  348. */
  349. cc?: string;
  350. /**
  351. * @description
  352. * Comma separated list of recipients email addresses that will appear on the _Bcc:_ field
  353. */
  354. bcc?: string;
  355. /**
  356. * @description
  357. * An email address that will appear on the _Reply-To:_ field
  358. */
  359. replyTo?: string;
  360. }
  361. /**
  362. * @description
  363. * A function used to set the {@link OptionalAddressFields}.
  364. *
  365. * @since 1.1.0
  366. * @docsCategory EmailPlugin
  367. * @docsPage Email Plugin Types
  368. */
  369. export type SetOptionalAddressFieldsFn<Event> = (
  370. event: Event,
  371. ) => OptionalAddressFields | Promise<OptionalAddressFields>;