Major Changes
-
#1325
d47ee96Thanks @juandav! - Template engines are no longer installed automatically.ejs,handlebars,liquidjs,mjml,nunjucks,preview-email,pugand their@types/*packages were listed both as optionalpeerDependenciesand asoptionalDependencies. npm, pnpm and yarn installoptionalDependenciesby default, so every project got all of them (and their transitive dependencies) even when using a single engine. They are now only optional peer dependencies, as the documentation already described (#1320).Migration: install the engine used by your adapter, e.g.
pnpm add handlebarsforHandlebarsAdapter, andpreview-emailif you use thepreviewoption. Projects that already followed the installation guide need no changes. -
#1328
647406dThanks @juandav! - Secure defaults for 3.0.- Breaking:
{{key}}placeholders in an inlinehtmlstring are now HTML-escaped. Use{{{key}}}to insert trusted markup. Subject and text templates are not escaped. - Breaking: CSS inlining no longer fetches remote stylesheets.
loadRemoteStylesheetsdefaults tofalseand is kept when you pass your owninlineCssOptions; set it totrueto opt back in. - Breaking: the Pug adapter compiles with
template.optionsonly. Context values can no longer change compiler options such asbasedir,filenameorplugins. They are still available as template variables. - Breaking:
MailerHealthIndicatorno longer returns the error message when transporter verification throws. The error is logged instead. - Placeholder interpolation only reads the context's own properties, so keys like
constructorare never rendered.
- Breaking:
Minor Changes
- #1326
6cc304fThanks @juandav! - Support NestJS 12. The module is tested against NestJS 11 and 12 in CI, and Nest types are now imported from the@nestjs/commonentrypoint instead of the internal@nestjs/common/interfacespath, so the published declarations resolve withnode16/bundlermodule resolution on NestJS 12. NestJS 12 requires Node.js >= 20.19 (or >= 22.12).
Patch Changes
-
#1327
6c9356dThanks @juandav! - Security hardening:- External stylesheet inlining (
<link rel="stylesheet">in Handlebars/EJS templates) now only reads.cssfiles located insidetemplate.dir(orcssBaseUrl). Previously an absolute or../href — including one injected through an unescaped context value — could inline any readable file from the server into the email. The tag matcher also runs in linear time now (it was vulnerable to ReDoS on large rendered output). - i18n: locales that are not BCP 47-like tags (e.g.
../../uploads) are ignored and the default locale is used, preventing path traversal through a user-providedlocale. textTemplatefiles must live insidetemplate.dir.- Template caches no longer inherit from
Object.prototype. - Raise the optional peer floors to
ejs >= 3.1.10andpug >= 3.0.3, which fix known template-injection CVEs.
If you reference stylesheets outside the template directory, set
cssBaseUrlto a common parent directory. - External stylesheet inlining (