packages/mail (@repo/mail). Templates are React Email components rendered to HTML and plain text, then handed to one provider.
Provider
packages/mail/src/provider/index.ts is a single line:
ZeptoMail
packages/mail/src/provider/zeptomail.ts posts JSON to the ZeptoMail send API.
parseAddress accepts both a bare address and the Name <address> form, so MAIL_FROM can carry a display name.
Environment variables
These are read straight from
process.env inside the package. They are not part of the validated env schema in apps/core-api/src/config.ts, so a missing ZEPTOMAIL_TOKEN does not stop the API from booting. It shows up only as failed sends.
sendEmail
packages/mail/src/lib/send.ts. Two call shapes:
It never throws
sendEmail returns false on a provider failure and logs it. It does not throw.
Template rendering happens before the try, so a rendering error does throw.
Templates
Defined inpackages/mail/src/emails/index.ts as mailTemplates. Each is a React component under packages/mail/src/emails/.
Rendering
getTemplate in packages/mail/src/lib/templates.ts:
- Loads the mail translations for the locale with
getMessagesForLocale. - Calls the component with the context, the locale and the translations.
- Takes the subject from the translations under the template id. For
notification, a non-emptycontext.titlereplaces it. - Renders HTML and a plain-text version with
@react-email/render.
packages/mail/src/components (Wrapper, Logo, PrimaryButton). lib/direction.ts handles right-to-left layout for Hebrew, including which way the button arrow points.
Who sends email
Login by email OTP is a fallback path. The primary login OTP goes over WhatsApp. See SmartSend WhatsApp.
Adding a template
1
Create the component
Add a file under
packages/mail/src/emails/. Its props are your context plus locale and translations.2
Register it
Add it to
mailTemplates in packages/mail/src/emails/index.ts. The key becomes the templateId, and TemplateId picks it up automatically.3
Add the subject and strings
Add an entry under the same key in the mail translations of every locale in
packages/i18n. getTemplate reads subject from there. A missing subject sends an email with an empty subject line.4
Rebuild the package
Consumers import the built output of
@repo/mail.