Skip to content

React Email

React Email is a library that allows you to use React components to create emails.

As Elysia is using Bun as runtime environment, we can directly write a React Email component and import the JSX directly to our code to send emails.

Installation

To install React Email, run the following command:

bash
bun add -d react-email
bun add @react-email/components react react-dom

Then add this script to package.json:

json
{
  "scripts": {
    "email": "email dev --dir src/emails"
  }
}

We recommend adding email templates into the src/emails directory as we can directly import the JSX files.

TypeScript

If you are using TypeScript, you may need to add the following to your tsconfig.json:

json
{
  "compilerOptions": {
	"jsx": "react"
  }
}

Your first email

Create file src/emails/otp.tsx with the following code:

tsx
import * as React from 'react'
import { Tailwind, Section, Text } from '@react-email/components'

export default function OTPEmail({ otp }: { otp: number }) {
    return (
        <Tailwind>
            <Section className="flex justify-center items-center w-full min-h-screen font-sans">
                <Section className="flex flex-col items-center w-76 rounded-2xl px-6 py-1 bg-gray-50">
                    <Text className="text-xs font-medium text-violet-500">
                        Verify your Email Address
                    </Text>
                    <Text className="text-gray-500 my-0">
                        Use the following code to verify your email address
                    </Text>
                    <Text className="text-5xl font-bold pt-2">{otp}</Text>
                    <Text className="text-gray-400 font-light text-xs pb-4">
                        This code is valid for 10 minutes
                    </Text>
                    <Text className="text-gray-600 text-xs">
                        Thank you joining us
                    </Text>
                </Section>
            </Section>
        </Tailwind>
    )
}

OTPEmail.PreviewProps = {
    otp: 123456
}

You may notice that we are using @react-email/components to create the email template.

This library provides a set of components including styling with Tailwind that are compatible with email clients like Gmail, Outlook, etc.

We also added a PreviewProps to the OTPEmail function. This is only apply when previewing the email on our playground.

Preview your email

To preview your email, run the following command:

bash
bun email

This will open a browser window with the preview of your email.

React Email playground showing an OTP email we have just written

Sending email

To send an email, we can use react-dom/server to render the the email then submit using a preferred provider:

tsx
import { Elysia, t } from 'elysia'

import * as React from 'react'
import { renderToStaticMarkup } from 'react-dom/server'

import OTPEmail from './emails/otp'

import nodemailer from 'nodemailer'

const transporter = nodemailer.createTransport({ 
  	host: 'smtp.gehenna.sh', 
  	port: 465, 
  	auth: { 
  		user: 'makoto', 
  		pass: '12345678'
  	} 
}) 

new Elysia()
	.get('/otp', ({ body }) => {
		// Random between 100,000 and 999,999
  		const otp = ~~(Math.random() * (900_000 - 1)) + 100_000

		const html = renderToStaticMarkup(<OTPEmail otp={otp} />)

        await transporter.sendMail({ 
        	from: '[email protected]', 
           	to: body, 
           	subject: 'Verify your email address', 
            html, 
        }) 

        return { success: true }
	}, {
		body: t.String({ format: 'email' })
	})
	.listen(3000)
tsx
import { Elysia, t } from 'elysia'

import OTPEmail from './emails/otp'

import Resend from 'resend'

const resend = new Resend('re_123456789') 

new Elysia()
	.get('/otp', ({ body }) => {
		// Random between 100,000 and 999,999
  		const otp = ~~(Math.random() * (900_000 - 1)) + 100_000

        await resend.emails.send({ 
        	from: '[email protected]', 
           	to: body, 
           	subject: 'Verify your email address', 
            html: <OTPEmail otp={otp} />, 
        }) 

        return { success: true }
	}, {
		body: t.String({ format: 'email' })
	})
	.listen(3000)
tsx
import { Elysia, t } from 'elysia'

import * as React from 'react'
import { renderToStaticMarkup } from 'react-dom/server'

import OTPEmail from './emails/otp'

import { type SendEmailCommandInput, SES } from '@aws-sdk/client-ses'
import { fromEnv } from '@aws-sdk/credential-providers'

const ses = new SES({ 
    credentials: 
        process.env.NODE_ENV === 'production' ? fromEnv() : undefined
}) 

new Elysia()
	.get('/otp', ({ body }) => {
		// Random between 100,000 and 999,999
  		const otp = ~~(Math.random() * (900_000 - 1)) + 100_000

		const html = renderToStaticMarkup(<OTPEmail otp={otp} />)

        await ses.sendEmail({ 
            Source: '[email protected]', 
            Destination: { 
                ToAddresses: [body] 
            }, 
            Message: { 
                Body: { 
                    Html: { 
                        Charset: 'UTF-8', 
                        Data: html 
                    } 
                }, 
                Subject: { 
                    Charset: 'UTF-8', 
                    Data: 'Verify your email address'
                } 
            } 
        } satisfies SendEmailCommandInput) 

        return { success: true }
	}, {
		body: t.String({ format: 'email' })
	})
	.listen(3000)
tsx
import { Elysia, t } from 'elysia'

import OTPEmail from './emails/otp'

import sendgrid from "@sendgrid/mail"

sendgrid.setApiKey(process.env.SENDGRID_API_KEY) 

new Elysia()
	.get('/otp', ({ body }) => {
		// Random between 100,000 and 999,999
  		const otp = ~~(Math.random() * (900_000 - 1)) + 100_000

    	const html = renderToStaticMarkup(<OTPEmail otp={otp} />)

        await sendgrid.send({ 
        	from: '[email protected]', 
           	to: body, 
           	subject: 'Verify your email address', 
            html 
        }) 

        return { success: true }
	}, {
		body: t.String({ format: 'email' })
	})
	.listen(3000)

TIP

Notice that we can directly import the email component out of the box thanks to Bun

You may see all of the available integration with React Email in the React Email Integration, and learn more about React Email in React Email documentation