Aplicativos de software modernos frequentemente dependem da comunicação por e-mail para interagir com os usuários. Eles podem enviar códigos de autenticação durante tentativas de login, e-mails de marketing ou newsletters, por exemplo. Isso significa que notificações por e-mail são tipicamente o meio mais comum de comunicação com os usuários.

Neste tutorial, você aprenderá como projetar modelos de e-mail deslumbrantes com React Email e enviá-los usando Resend – uma plataforma de API de e-mail simples e poderosa.

Pré-requisitos

Para aproveitar ao máximo este tutorial, você deve ter um entendimento básico de React ou Next.js.

Também faremos uso das seguintes ferramentas:

  • React Email: Uma biblioteca que permite criar modelos de e-mail lindamente projetados usando componentes React.

  • Resend: Uma plataforma de API simples e poderosa para enviar e-mails de suas aplicações.

Como Construir a Aplicação com Next.js

Nesta seção, você criará uma simples aplicação de suporte ao cliente. O aplicativo incluirá um formulário para os usuários enviarem suas consultas, o que acionará uma notificação por e-mail confirmando que um ticket de suporte foi criado.

Para começar, primeiro configuraremos a interface do usuário e um endpoint de API.

Execute o seguinte comando para criar um novo projeto Next.js TypeScript:

npx create-next-app react-email-resend

Atualize o arquivo app/page.tsx para renderizar um formulário que coleta os detalhes do cliente, incluindo seu nome completo, endereço de e-mail, assunto do ticket e uma mensagem detalhada descrevendo o problema. Quando o formulário é enviado, os dados de entrada são registrados no console usando a função handleSubmit.

"use client";
import support from "@/app/images/support.jpg";
import { useState } from "react";
import Image from "next/image";

export default function Page() {
    //👇🏻 estados de entrada
    const [name, setName] = useState<string>("");
    const [email, setEmail] = useState<string>("");
    const [subject, setSubject] = useState<string>("");
    const [content, setContent] = useState<string>("");

    const handleSubmit = async (e: React.FormEvent) => {
        e.preventDefault();
        //👇🏻 registre a entrada do usuário
        console.log({ name, email, subject, content });
    };
return ({/** -- Elementos da UI -- */})
}

Retorne os elementos da UI do formulário que aceitam o nome completo do usuário, endereço de e-mail, assunto do ticket e uma mensagem detalhada descrevendo o problema.

    return (
        <main className='w-full min-h-screen flex items-center justify-between'>
                <form className='w-full' onSubmit={handleSubmit}>
                    <label htmlFor='name' className='opacity-60'>
                        Full Name
                    </label>
                    <input
                        type='text'
                        className='w-full px-4 py-3 border-[1px] mb-3 border-gray-300 rounded-sm'
                        id='name'
                        required
                        value={name}
                        onChange={(e) => setName(e.target.value)}
                    />

                    <label htmlFor='email' className='opacity-60'>
                        Email Address
                    </label>
                    <input
                        type='email'
                        className='w-full px-4 py-3 border-[1px] mb-3 border-gray-300 rounded-sm'
                        id='email'
                        value={email}
                        onChange={(e) => setEmail(e.target.value)}
                        required
                    />

                    <label htmlFor='subject' className='opacity-60'>
                        Subject
                    </label>
                    <input
                        type='text'
                        className='w-full px-4 py-3 border-[1px] mb-3 border-gray-300 rounded-sm'
                        id='subject'
                        value={subject}
                        onChange={(e) => setSubject(e.target.value)}
                        required
                    />

                    <label htmlFor='message' className='opacity-60'>
                        Message
                    </label>
                    <textarea
                        rows={7}
                        className='w-full px-4 py-3 border-[1px] mb-3 border-gray-300 rounded-sm'
                        id='message'
                        required
                        value={content}
                        onChange={(e) => setContent(e.target.value)}
                    />

                    <button className='w-full bg-blue-500 py-4 px-3 rounded-md font-bold text-blue-50'>
                        SEND MESSAGE
                    </button>
                </form>
            </div>
        </main>
    );

Aqui está a página resultante do componente:

Em seguida, crie um endpoint de API (/api/route.ts) que aceite a entrada do cliente.

cd app
mkdir api && cd api
touch route.ts

Copie o seguinte código para o arquivo api/route.ts. O endpoint da API registra a entrada do cliente no console ao recebê-la.

import { NextRequest, NextResponse } from "next/server";

export async function POST(req: NextRequest) {
    const { name, email, subject, content } = await req.json();
    //👇🏻 registre o conteúdo
    console.log({ name, email, subject, content });
    return NextResponse.json({
        message: "Email sent successfully",
        data,
 });
}

Atualize a função handleSubmit para enviar os dados do cliente para o endpoint de API e retornar a resposta JSON:

const handleSubmit = async (e: React.FormEvent) => {
    e.preventDefault();

    try {
        const response = await fetch("/api", {
            method: "POST",
            headers: {
                "Content-Type": "application/json",
            },
            body: JSON.stringify({ name, email, subject, content }),
        });
        const data = await response.json();
        alert(data.message);
    } catch (error) {
        console.error(error);
        alert("An error occurred, please try again later");
    }
    setName("");
    setEmail("");
    setSubject("");
    setContent("");
};

Parabéns! Você configurou a coleta e envio de dados. Nas próximas seções, vou guiá-lo na criação e envio de modelos de e-mail com React Email e Resend.

Como Criar Modelos de E-mail usando React Email

React Email permite que você construa e envie componentes de email usando React e TypeScript. Ele suporta vários clientes de email, incluindo Gmail, Yahoo Mail, Outlook e Apple Mail.

O React Email também fornece múltiplos componentes de interface do usuário que permitem que você personalize os modelos de email de acordo com o layout preferido usando componentes React JSX/TSX.

Instale o pacote React Email e seus componentes executando o trecho de código abaixo:

npm install react-email -D -E
npm install @react-email/components -E

Inclua este script no seu arquivo package.json. Ele direciona o React Email para onde os modelos de email estão localizados no seu projeto.

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

Uma das funcionalidades do React Email é a capacidade de visualizar o modelo de email no navegador durante o desenvolvimento, permitindo que você veja como ele aparecerá no email do destinatário.

Então, a seguir, crie uma pasta emails contendo um arquivo TicketCreated.tsx dentro da pasta src do Next.js e copie o trecho de código a seguir para o arquivo:

import * as React from "react";
import {
    Body,
    Container,
    Head,
    Heading,
    Hr,
    Html,
    Link,
    Preview,
    Text,
    Tailwind,
} from "@react-email/components";

interface TicketCreatedProps {
    username: string;
    ticketID: string;
}

const baseUrl = process.env.VERCEL_URL || "http://localhost:3000";

No trecho de código acima, importamos os componentes necessários para construir o modelo de email.

Em seguida, adicione o componente TicketCreated ao arquivo para renderizar o modelo de email usando componentes do React Email.

export const TicketCreated = ({ username, ticketID }: TicketCreatedProps) => {
    return (
        <Html>
            <Head />
            <Preview>Support Ticket Confirmation Email 🎉</Preview>
            <Tailwind>
                <Body className='bg-white my-auto mx-auto font-sans px-2'>
                    <Container className='border border-solid border-[#eaeaea] rounded my-[40px] mx-auto p-[20px] max-w-[465px]'>
                        <Heading className='text-black text-[24px] font-normal text-center p-0 my-[30px] mx-0'>
                            Your Ticket has been created
                        </Heading>
                        <Text className='text-black text-[14px] leading-[24px]'>
                            Hello {username},
                        </Text>
                        <Text className='text-black text-[14px] leading-[24px]'>
                            <strong>Support Ticket</strong> (
                            <Link
                                href={`${baseUrl}/ticket/${ticketID}`}
                                className='text-blue-600 no-underline'
                            >
                                {`#${ticketID}`}
                            </Link>
                            ) has been created successfully.
                        </Text>

                        <Text className='text-black text-[14px] leading-[24px]'>
                            The Support team will review your ticket and get back to you
                            shortly.
                        </Text>

                        <Hr className='border border-solid border-[#eaeaea] my-[26px] mx-0 w-full' />
                        <Text className='text-[#666666] text-[12px] leading-[24px]'>
                            This message was intended for{" "}
                            <span className='text-black'>{username}</span>. If you did not
                            create this ticket, please ignore this email.
                        </Text>
                    </Container>
                </Body>
            </Tailwind>
        </Html>
    );
};

Por fim, exporte e adicione valores padrão para as props:

TicketCreated.PreviewProps = {
    username: "alanturing",
    ticketID: "9083475",
} as TicketCreatedProps;

export default TicketCreated;

Execute npm run email no seu terminal para visualizar o modelo de email.

Este modelo de email notifica os clientes que seu ticket de suporte foi criado e que alguém da equipe de suporte entrará em contato com eles.

O React Email oferece uma variedade de modelos de email pré-designados, facilitando a criação de emails lindamente estilizados para diferentes propósitos. Você pode conferir o demo disponível para ver exemplos do que é possível.

Como Enviar Emails com Resend

O Resend é uma API de email simples que permite enviar emails dentro da sua aplicação de software. Ele suporta uma variedade de linguagens de programação, incluindo JavaScript (Next.js, Express, Node.js), Python, PHP, Go e Rust, entre outras.

O Resend e o React Email podem ser facilmente integrados, uma vez que o co-fundador do Resend, Bu Kinoshita, também é o criador do React Email.

Crie uma conta no Resend. Depois de logar, acesse a seção de chaves da API no seu painel e copie sua chave de API para um arquivo .env.local.

//👇🏻 .env.local file
RESEND_API_KEY=<RESEND_API_KEY>

//👇🏻 .env.local arquivo

import { NextRequest, NextResponse } from "next/server";
Atualize o endpoint da API para enviar um email usando o modelo do React Email, como mostrado abaixo:
import { v4 as generateID } from "uuid";
//👇🏻 função geradora de ID de ticket
import TicketCreated from "@/emails/TicketCreated";
//👇🏻 importa o modelo de e-mail
import { Resend } from "resend";
const resend = new Resend(process.env.RESEND_API_KEY);

export async function POST(req: NextRequest) {
    //👇🏻 importa o Reenvio
    const { name, email, subject, content } = await req.json();
    //👇🏻 aceita a entrada do cliente do frontend
    console.log({ name, email, subject, content });
    //👇🏻 registra eles
    const { data, error } = await resend.emails.send({
        from: "Acme <[email protected]>",
        to: [email],
        subject: "Ticket Confirmation Email 🎉",
        react: TicketCreated({ username: name, ticketID: generateID() }),
    });

    if (error) {
        return NextResponse.json(
            { message: "Error sending email" },
            { status: 500 }
        );
    }

    return NextResponse.json({
        message: "Email sent successfully",
        data,
    });
}

//👇🏻 envia um e-mail usando o modelo de e-mail

Parabéns!🥳 Você completou este tutorial.

Aqui está uma breve demonstração do aplicativo:

Próximos Passos

Neste tutorial, você aprendeu como criar modelos de e-mail com React Email e enviá-los usando o Reenvio. Ambos os pacotes permitem que você integre facilmente a comunicação por e-mail em suas aplicações.

Seja para notificações simples por e-mail, newsletters ou campanhas de marketing, o React Email e o Reenvio oferecem uma solução eficiente e personalizável para atender às suas necessidades.

Como instalar o Reenvio em aplicações Next.js