Built-in templates
The mailer ships five transactional templates out of the box. Both the SendGrid and local providers render all of them:| Template | Trigger |
|---|---|
VERIFY_EMAIL | New user registration — prompts email confirmation |
LOST_PASSWORD | User initiates a forgotten-password flow |
PASSWORD_RESET | Confirmation after a successful password reset |
ORGANIZATION_INVITATION | Member invited to join an organisation |
WELCOME | First sign-in after email verification |
apps/backend/src/tools/mailer/emails/.
Sending vs queuing
TheMailerType contract exposes two methods:
| Method | How | When to use |
|---|---|---|
tools.mailer.send() | Delivers immediately and synchronously | Webhooks, admin triggers, tests |
tools.mailer.queue() | Enqueues onto the EMAIL queue | Everything else — keeps the request fast |
send() from inside the EMAIL queue consumer — it causes an infinite loop.
Why
SendGrid is a reliable, scalable email delivery service with detailed delivery analytics, bounce handling, and suppression list management. It’s the right choice for production transactional email — API key setup takes under five minutes and the SDK handles retries at the HTTP layer.Setup
- In
apps/backend/src/configuration/production.ts, settools.mailer: - In your production environment, set:
- Keep
development.tsandtest.tsusing thelocalclient. - Run
make test module=backend.
Adding a new email template
- Create
apps/backend/src/tools/mailer/emails/<templateName>.ts. Export a<TemplateName>TemplateAttributestype and a render function that returns{ to, from, subject, html }. - Add the template key to
AvailableTemplatesinapps/backend/src/tools/mailer/emails/index.tsand register the render function in thetemplatesmap. - Add a
case AvailableTemplates.<YOUR_TEMPLATE>in thesendswitch insideapps/backend/src/tools/mailer/twilioSendgrid.tsandapps/backend/src/tools/mailer/local.ts. - Export the new
TemplateAttributestype fromapps/backend/src/tools/mailer/index.ts. - Write a test in
apps/backend/src/tools/mailer/emails/__tests__/<templateName>.spec.ts. - Run
make test module=backend.
Gotchas
SENDGRID_API_KEYmust be set at server startup. A missing key throws immediately insidebuildTwilioSendgridMailerbefore any emails are attempted.- SendGrid returns HTTP 202 for accepted messages — the implementation throws if it receives anything else. Check logs if emails go missing.
- The
queuemethod enqueues onto theEMAILqueue. The consumer that processes that queue callssend— never callsendagain from inside the consumer. - Domain authentication in SendGrid (DKIM/SPF) is required to avoid spam folder placement. Configure it in the SendGrid dashboard before going to production.
What’s next?
- Local mailer — the dev stub to use in
development.tsandtest.ts. - Configuration — environment-level config.