Las aplicaciones de software modernas a menudo dependen de la comunicación por correo electrónico para interactuar con los usuarios. Pueden enviar códigos de autenticación durante intentos de inicio de sesión, correos electrónicos de marketing o boletines informativos, por ejemplo. Esto significa que las notificaciones por correo electrónico suelen ser el medio de comunicación más común con los usuarios.

En este tutorial, aprenderás cómo diseñar impresionantes plantillas de correo electrónico con React Email y enviarlas usando Resend, una plataforma de API de correo electrónico simple y potente.

Requisitos previos

Para sacar el máximo provecho de este tutorial, deberías tener un entendimiento básico de React o Next.js.

También haremos uso de las siguientes herramientas:

  • React Email: Una biblioteca que te permite crear plantillas de correo electrónico bellamente diseñadas utilizando componentes de React.

  • Resend: Una plataforma de API simple y potente para enviar correos electrónicos desde tus aplicaciones.

Cómo Construir la Aplicación con Next.js

En esta sección, crearás una sencilla aplicación de soporte al cliente. La aplicación incluirá un formulario para que los usuarios envíen sus consultas, lo que desencadenará una notificación por correo electrónico confirmando que se ha creado un ticket de soporte.

Para empezar, primero configuraremos la interfaz de usuario y un punto final de API.

Ejecuta el siguiente comando para crear un nuevo proyecto de Next.js TypeScript:

npx create-next-app react-email-resend

Actualiza el archivo app/page.tsx para renderizar un formulario que recopile los detalles del cliente, incluyendo su nombre completo, dirección de correo electrónico, el asunto del ticket y un mensaje detallado describiendo el problema. Cuando se envíe el formulario, los datos ingresados se registran en la consola utilizando la función 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();
        //👇🏻 registrar la entrada del usuario
        console.log({ name, email, subject, content });
    };
return ({/** -- elementos de UI -- */})
}

Devuelve los elementos de la interfaz del formulario que aceptan el nombre completo del usuario, dirección de correo electrónico, asunto del ticket y un mensaje detallado describiendo el 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>
    );

Aquí está la página resultante del componente:

A continuación, crea un punto final de API (/api/route.ts) que acepte la entrada del cliente.

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

Copia el siguiente código en el archivo api/route.ts. El punto final de la API registra la entrada del cliente en la consola al recibirla.

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

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

Actualiza la función handleSubmit para enviar los datos del cliente al punto final de la API y devolver la respuesta 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("");
};

¡Felicidades! Has configurado la recopilación y envío de datos. En las próximas secciones, te guiaré a través de la creación y envío de plantillas de correo electrónico con React Email y Resend.

Cómo crear plantillas de correo electrónico usando React Email

React Email te permite construir y enviar componentes de correo electrónico utilizando React y TypeScript. Admite múltiples clientes de correo electrónico, incluidos Gmail, Yahoo Mail, Outlook y Apple Mail.

React Email también proporciona múltiples componentes de UI que te permiten personalizar las plantillas de correo electrónico según el diseño que prefieras utilizando componentes React JSX/TSX.

Instala el paquete React Email y sus componentes ejecutando el fragmento de código a continuación:

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

Incluye este script en tu archivo package.json. Indica a React Email dónde se encuentran las plantillas de correo electrónico en tu proyecto.

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

Una de las características de React Email es la capacidad de previsualizar la plantilla de correo electrónico en tu navegador durante el desarrollo, lo que te permite ver cómo aparecerá en el correo electrónico del destinatario.

Por lo tanto, a continuación, crea una carpeta emails que contenga un archivo TicketCreated.tsx dentro de la carpeta src de Next.js y copia el siguiente fragmento de código en el archivo:

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";

En el fragmento de código anterior, importamos los componentes necesarios para construir la plantilla de correo electrónico.

A continuación, agrega el componente TicketCreated al archivo para renderizar la plantilla de correo electrónico utilizando componentes de 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>
    );
};

Finalmente, exporta y añade valores predeterminados para las props:

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

export default TicketCreated;

Ejecuta npm run email en tu terminal para previsualizar la plantilla de correo electrónico.

Este template de correo electrónico notifica a los clientes que su ticket de soporte ha sido creado y que alguien del equipo de soporte se pondrá en contacto con ellos.

React Email ofrece una variedad de plantillas de correo electrónico pre-diseñadas, facilitando la creación de correos electrónicos bellamente estilizados para diferentes propósitos. Puedes consultar la demostración disponible para ver ejemplos de lo que es posible.

Cómo enviar correos electrónicos con Resend

Resend es una API de correo electrónico simple que te permite enviar correos electrónicos dentro de tu aplicación de software. Soporta una variedad de lenguajes de programación, incluyendo JavaScript (Next.js, Express, Node.js), Python, PHP, Go y Rust, entre otros.

Resend y React Email se pueden integrar fácilmente ya que el cofundador de Resend, Bu Kinoshita, es también el creador de React Email.

Crea una cuenta en Resend. Una vez que hayas iniciado sesión, navega a la sección de claves API en tu panel y copia tu clave API en un archivo .env.local.

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

//👇🏻 archivo .env.local file

import { NextRequest, NextResponse } from "next/server";
Actualiza el punto final de la API para enviar un correo electrónico utilizando la plantilla de React Email, como se muestra a continuación:
import { v4 as generateID } from "uuid";
//👇🏻 función generadora de ID de ticket
import TicketCreated from "@/emails/TicketCreated";
//👇🏻 importa la plantilla de correo electrónico
import { Resend } from "resend";
const resend = new Resend(process.env.RESEND_API_KEY);

export async function POST(req: NextRequest) {
    //👇🏻 importa Reenviar
    const { name, email, subject, content } = await req.json();
    //👇🏏 acepta la entrada del cliente desde el frontend
    console.log({ name, email, subject, content });
    //👇🏻 los registra
    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,
    });
}

//👇🏻 envía un correo electrónico usando la plantilla de correo electrónico

Felicitaciones!🥳 ¡Has completado este tutorial!

Aquí tienes una breve demostración de la aplicación:

Próximos Pasos

En este tutorial, aprendiste cómo crear plantillas de correo electrónico con React Email y enviarlas usando Reenviar. Ambos paquetes te permiten integrar fácilmente la comunicación por correo electrónico dentro de tus aplicaciones.

Ya sea notificaciones por correo electrónico simples, boletines informativos o campañas de marketing, React Email y Reenviar ofrecen una solución eficiente y personalizable para satisfacer tus necesidades.

Cómo instalar Resend en aplicaciones Next.js