Build Emails in React and Send Them with SendGrid

March 22, 2024
Written by
Phil Nash
Twilion
Reviewed by

Build Emails in React and Send Them with SendGrid

Writing good looking HTML emails that work in all the major email clients is really hard. Thankfully there are projects like React Email that not only make it easy, but give us familiar tools, like React and Tailwind CSS, to work with. In this post, you will see how to build emails with React Email and send them using Twilio SendGrid.

Prerequisites

To build and send emails using React Email and SendGrid, you will need:

Creating a new email project

You will need a Node.js project in which to build your emails. In your terminal, create a new directory called react-email-sendgrid and change into it.

mkdir react-email-sendgrid
cd react-email-sendgrid

Initialise a new Node.js application.

npm init --yes

Install the dependencies that you will need.

npm install react react-email @react-email/components @react-email/render @sendgrid/mail 

Scaffold out the directories and files we're going to use.

mkdir src src/emails
touch src/send.js src/config.js src/emails/Welcome.jsx

Open up the project directory using your preferred text editor and navigate to the package.json file. Set the type to "module" and add a script we can use to preview our emails:

  ...
  "type": "module",
  "scripts": {
    "emails": "email dev --dir ./src/emails"
  },
  ...

The script email is a command line tool provided by React Email that helps you preview your emails in the browser before sending them. To preview an email, we must first create one.

Building emails in React

Earlier you created the file src/emails/Welcome.jsx, open that up. Since we're going to build this email in React, we'll start by importing the React library at the top of the file.

import * as React from "react";

The only thing this file needs to do is export a default function that will render an email. To start, let's just return some text.

export default function Email() {
  return "Hello world";
}

Start up the preview server by running the following command in your terminal:

npm run emails

Once it finishes compiling, you can open the preview app at http://localhost:3000/ . Choose the email called "Welcome" in the navigation. You will see the email rendered in the preview window.

The email preview tool by React Email. On the left is a list of available emails. Along the top you can choose between desktop, mobile or code view. In the middle is the rendered email.

This email isn't much to look at, but this already shows one of the powers of React Email. This preview app will show you your emails as you work on them, including hot reloading when you change things. You can test that out by changing the text in your Email function, you will see the preview automatically reload.

Building emails with React components

So far our email is just text and it doesn't look very nice. To help you build an HTML email that works, React Email provides a number of components . The components abstract away the hassle of working with HTML tables and inlining styles that building email templates requires.

There are display components, like <Text> , <Heading> and <Button> , and layout components, like <Container> , <Column> and <Row>. There are also some special components, like <Preview> which configures preview text in email clients and <Tailwind> which allows you to use Tailwind CSS classes in your emails. Check out all the available components in the React Email documentation

Let's grab a few of these components and put a nice looking email together.

At the top of the file, import the following components:

import {
  Body,
  Container,
  Head,
  Html,
  Preview,
  Heading,
  Text,
  Link,
  Hr,
  Row,
  Column,
  Img,
} from "@react-email/components";

Update the Email function to the following:

export default function Email() {
  return (
    <Html>
      <Head />
      <Preview>Welcome to the site</Preview>
      <Body>
        <Container>
          <Heading as="h1">Welcome</Heading>
          <Text>Hello,</Text>
          <Text>Now you're using React Email to create your emails.</Text>
          <Text>
            <Link href="https://react.email/docs/">
              Go to the documentation to learn more
            </Link>
            .
          </Text>
          <Hr />
          <Text>This email was sent by me, to myself.</Text>
        </Container>
      </Body>
    </Html>
  );
}

Take a look at the preview now.

The React Email preview view. In the email preview section a default styled email is shown.

There is clearly some structure, but the styling is very default. This is the base level that React Email provides for us. We can add some style by using style attributes. Update the code to the following:

const fontFamily = {
  fontFamily: "Helvetica Neue, Helvetica, Arial, sans-serif",
};

const h1 = {
  fontSize: "3em",
  ...fontFamily,
};

const text = {
  fontSize: "16px",
  ...fontFamily,
};

const footerText = {
  fontSize: "12px",
  textAlign: "center",
  color: "#999",
  ...fontFamily,
};

const container = {
  backgroundColor: "#FFF",
  padding: "0 20px",
  borderRadius: "6px",
};

export default function Email() {
  return (
    <Html>
      <Head />
      <Preview>Welcome to the site</Preview>
      <Body style={{ backgroundColor: "#f5ecc1" }}>
        <Container style={container}>
          <Heading as="h1" style={h1}>
            Welcome
          </Heading>
          <Text style={text}>Hello,</Text>
          <Text style={text}>
            Now you're using React Email to create your emails.
          </Text>
          <Text style={text}>
            <Link href="https://react.email/docs/">
              Go to the documentation to learn more
            </Link>
            .
          </Text>
          <Hr />
          <Text style={footerText}>This email was sent by me, to myself.</Text>
         </Container>
       </Body>
    </Html>
  );
}

Check the preview again and the email looks a bit more like something you'd be used to sending to your users.

The email preview tool again. This time the email has a yellow background colour and the font is a sans-serif.

The email looks better, but the most engaging emails are personalised and this is very generic for now. To personalise the content of the email, you can pass in props just like in any other React application.

Update the Email function signature to the following:

export default function Email({ name = "Phil" }) {
...

You can then update the <Text> that says "hello" to:

...
<Text style={text}>Hello {name},</Text>
...

We have set a default name for our email, so checking the preview will show that the email now says "Hello Phil".

The email preview tool again. This time, because we used React props to pass in a name, the email reads "Hello Phil".

When we come to send the email with SendGrid, we'll pass in a name so that we can personalise each email we send.

For more inspiration, you can check out more examples of emails built with React Email.

Sending React emails with SendGrid

Now that you have an email that's ready to send, let's set up sending with SendGrid. There are a few steps we need to perform here:

  • Build the React emails from JSX into plain JavaScript
  • Configure the application with SendGrid credentials
  • Write the code to import the email, render it and send it with SendGrid

Compiling from JSX to JavaScript

We built the email in a JSX file, but a regular Node.js application can't read JSX by default. So first we need a build process that can turn JSX into regular JavaScript. For this we'll use Babel .

Install the following Babel dependencies through your terminal:

npm install @babel/core @babel/cli @babel/preset-react --save-dev

Create a file called .babelrc.json in the root of your application and copy in the following:

{
  "presets": [["@babel/preset-react", { "runtime": "automatic" }]]
}

This sets up Babel to use the React preset that will compile our JSX code to JavaScript.

You can do the same in a TypeScript project using TSX files , but you should use @babel/preset-typescript instead.

Open your package.json file and in the "scripts" section add a build script.

  "scripts": {
    "emails": "email dev –-dir ./src/emails",
    "build": "babel --out-dir build ./src"
  },

This command uses Babel to build everything from the src directory to the build directory, running it through the React compiler. Run this script now with:

npm run build

You should see a build directory appear in your project with the same structure as your src directory, but the emails directory now contains Welcome.js instead of Welcome.jsx.

Configuring the application with SendGrid credentials

To send emails with SendGrid we need to set up a SendGrid API key. Start by creating a file called .env in the root of the project. In this .env file you'll want to add three variables, one for your SendGrid API key and, for this application, email addresses to send to and from. Your from email address will need to be verified (either Single Sender Verification or via Domain Authentication ).

SENDGRID_API_KEY=
SENDGRID_FROM=
SENDGRID_TO=

Fill in your own details in the .env file. Now, open src/config.js and enter the following:

export const sendgrid = {
  apiKey: process.env.SENDGRID_API_KEY || "",
  from: process.env.SENDGRID_FROM || "",
  to: process.env.SENDGRID_TO || "",
};

This code reads the entries from the environment and exports them to be used elsewhere in the application. Now we're ready to send the email.

Sending a React Email with SendGrid

Open src/send.js in your editor. Start by importing the dependencies:

import { render } from "@react-email/render";
import sgMail from "@sendgrid/mail";
import { sendgrid } from "./config.js";
import Email from "./emails/Welcome.js";

We'll use the `render` function from React Email to create HTML and text output that we can send as an email. Configure the SendGrid API client with the API key:

sgMail.setApiKey(sendgrid.apiKey);

Create an options object that holds the email options. Then use the `render` function to turn the React Email into HTML:

const emailOptions = { name: "Dhruv" };

const emailHTML = render(Email(emailOptions));

React Email can also render a text version of the email too.

const emailText = render(Email(emailOptions), { plainText: true });

Now, put all of that together with the emails you set in the config and use the SendGrid client to send the email like this:

await sgMail.send({
  from: sendgrid.from,
  to: sendgrid.to,
  subject: "React email",
  html: emailHTML,
  text: emailText,
});

If you want to read more about using the SendGrid Node library to send emails, check out the documentation . Finally, to send this, we'll create one more package.json script to send out an email:

  "scripts": {
    "emails": "email dev –-dir ./src/emails",
    "build": "babel --out-dir build ./src",
    "send": "npm run build && node --env-file=.env ./build/send.js"
  },

The "send" script will first run the "build" script and then run build/send.js. It uses the new support in Node.js to load the values in .env file into the environment and executes the code to send the email. Run it with:

npm run send

You should then receive the email shortly. For me, it arrived in my Gmail account looking like this:

A single email in Gmail. It has the same design as the email we've been working on.

Build emails like you build your front-end

In this article you created a new application in which you could build, preview and send emails using React Email and SendGrid . You used React Email's components which make the job of building table based layouts in emails much easier and you used Babel to compile JSX files, so that they could be imported in a Node.js program and sent using SendGrid.

For more inspiration on designs you can create with React Email check out their demos , and make sure to view the source of the email and the HTML output. Check out the Tailwind CSS example if you like using Tailwind for your styling.

If you're looking for other ways to send HTML emails without dealing directly with table layouts, check out this tutorial on using Inky to send beautiful emails , or if you're looking for something to combine your new React templates with, check out this tutorial on creating a contact form in Node.js with SendGrid .

Phil Nash is a developer advocate for DataStax and Google Developer Expert, based in Melbourne, Australia. You can get in touch with Phil on Twitter at @philnash and follow his writing on JavaScript and web development at https://philna.sh .