Emails
Send emails with React Email and a provider-agnostic email worker. Easily switch between Resend, SES, Mailgun, SparkPost, or custom SMTP.
Nuxflare Pro ships with a robust email system that works on Cloudflare Workers.
Note from Tanay: Under the hood, this email system uses a port of the AdonisJS Mailer that I adapted to work on Cloudflare Workers. It's called
@tanayvk/mailer
. While I haven't tested all the advanced features yet, you can check out the AdonisJS Mailer docs for more details. If you run into any issues or have feature requests, please let me know!
Architecture
- Email Templates (
packages/emails
) - Type-safe email templates using React Email - Email Worker (
packages/functions/src/emails.ts
) - Cloudflare Worker that handles provider-agnostic email sending - Infrastructure (
infra/emails.ts
) - Infrastructure configuration for the Cloudflare Worker
Email Templates
Templates are built using React Email and Tailwind (optional). For example:
import { Body, Container, Html, Text } from "@react-email/components";
export const WelcomeEmail = ({ username }: { username: string }) => (
<Html>
<Body>
<Tailwind>
<Container class="p-4 border border-solid border-[#eaeaea] rounded my-[40px] mx-auto max-w-[465px]">
<Text>Welcome {username}!</Text>
</Container>
</Tailwind>
</Body>
</Html>
);
Provider Configuration
Email providers are configured in config.ts
and the emails worker
packages/functions/src/emails.ts
:
// ...
export const authEmail = {
name: "Tanay Karnik",
address: "auth@pro.nuxflare.com",
};
export const authEmailDomain = "pro.nuxflare.com";
export const flags: {
// ...
resend?: boolean;
mailgun?: boolean;
ses?: boolean;
sparkPost?: boolean;
smtp?: boolean;
// ...
} = {
// ...
resend: true,
mailgun: true,
};
const config: Parameters<typeof generateMailer>[0] = {
default: "resend",
// NOTE: you can also set defaults here
// from: {
// address: "example@domain.com",
// name: "Tanay Karnik",
// },
// replyTo: {
// address: "example@domain.com",
// name: "Tanay Karnik",
// },
mailers: {
...(flags.resend && {
resend: () =>
new ResendTransport({
key: Resource.ResendApiKey.value || "",
baseUrl: "https://api.resend.com",
}),
}),
...(flags.mailgun && {
mailgun: () =>
new MailgunTransport({
key: Resource.MailgunApiKey.value || "",
domain: authEmailDomain,
baseUrl: "https://api.mailgun.net/v3",
}),
}),
},
};
Setting Up Secrets
Secrets for email providers are managed using SST.
# Resend
bun sst secrets set ResendApiKey sk_123...
# Mailgun
bun sst secrets set MailgunApiKey key-123...
Sending Emails
Use the sendEmail
function to send emails:
async ({ ctx: { user, origin, authorize, sendEmail }, input }) => {
// ...
// pass the from email, to email, template name and template props to send emails
await sendEmail(authEmail, invite.email, "Invitation", {
teamName: team.name,
invitedBy: user.name,
inviteLink,
});
// ...
};
Emails worker can be used from any package:
import { sender } from "@nuxflare-pro/functions/sender";
const sendEmail = sender(event.context?.cloudflare?.env?.Emails); // pass the Emails binding