The Easiest Way to Make Emails in JavaScript

Posted on October 12, 2023
Introduction

If you have ever had to write and style an email using code, you know the pain of the email HTML. Its a mess of different compatibility and not as simple as just making a webpage. React email aims to solve this in JavaScript (not just React) and is one of the easiest ways I have seen to make a styled email with great compatibility, and even supports some of Tailwind.

To start, we need to install react-email and its components. You can install all the components separately, but for now I will install a package with all of them.

Terminal window
npm install react-email @react-email/components @react-email/render -E

2. Add a script to your package.json

Section titled 2. Add a script to your package.json

Next, react-email has a preview mode to easily test your emails design. We are going to add a script to our package.json to easily run this. You can run the command manually if wanted.

package.json
{
"scripts": {
//...
"dev": "email dev"
}
}

If you are using NextJs I recommend making the script email dev --port 3001. This is because the email preview site also uses next, so it defaults to port 3000 which could conflict with your dev server.

By default, React-Email looks for a folder called emails for its email templates. You can change this by appending --dir [FOLDER] if wanted.

Once created we can add our first email template. This can have any name but must be a jsx or tsx.

example-email.tsx
import * as React from "react"
import { Button, Html } from "@react-email/components"
export default function Email() {
return (
<Html>
<Button
href="https://example.com"
style={{ background: "#000", color: "#fff", padding: "12px 20px" }}
>
Click me
</Button>
</Html>
)
}

See here for more complex examples.

If you added the script to your package.json above, all we have to do is:

Terminal window
npm run email

Now visit localhost:3000 to preview your emails.

Now that you have your template working, how do you utilize this in your email sender, such as nodemailer?

For this we need to make use of the render function. The example below is built using nodemailer, in a NextJS API Route.

api/send-mail/route.ts
import type { NextApiRequest, NextApiResponse } from "next"
import Email from "@/emails/example-email"
import { render } from "@react-email/render"
export default async function handler(
req: NextApiRequest,
res: NextApiResponse
) {
await sendEmail({
to: "hello@world.com",
subject: "Hello",
html: render(Email()),
})
return res.status(200).json({ message: "Success" })
}

This render function will return a string of the HTML of your email. You can pass in props to the Email() function too, for example if you needed to address someone by name, it would look like this Email({ name }), and the Email template would just have name as a React prop.

React-Email has some support for tailwind. See their docs. Its worth noting it will only work with basic styling needs as email css support varies.

That is all you need to get started writing email easily in JavaScript. The react-email docs have lots of example, and show you how to integrate with things such as Nodemailer, SendGrid, Postmark, AWS SES, MailerSend, Plunk and more.

Its also worth checking out Resend. They are the maintainers of React-Email and have made a service to send messages with easy-to-use APIs/SDKs without having to worry about emails going to the spam folder.