In this tutorial, we'll explore how to send emails from a Next.js application using Resend, including custom email templates, domain verification, scheduling, and file attachments.

What are Resend and React Email?

Resend is an email API service that allows developers to send emails from their applications with minimal setup. React Email provides components for building responsive email templates using React.

You can check the video tutorial on the Cules Coding channel here:

Project Setup

Let's start with a basic Next.js application. Our project structure looks like this:

src/
├── actions/
│   └── sendEmail.js  // Server action to handle email sending
├── app/
│   ├── page.jsx      // Simple form to collect user input
│   ├── layout.js     // Root layout
│   └── globals.css
└── emails/
    └── MyEmail.jsx   // Email template component

This structure separates our concerns nicely — server actions for backend logic, the app directory for Next.js pages, and a dedicated emails directory for our email templates.

First, install the required packages:

npm install resend @react-email/components react-email

We're installing three packages:

  • resend for the email API.
  • @react-email/components for pre-built email components.
  • react-email for the environment to preview our emails.

Creating Email Templates with React Email

React Email provides components for building responsive email templates. Let's create a template in src/emails/MyEmail.jsx:

import {
  Tailwind,
  Body,
  Container,
  Head,
  Heading,
  Html,
  Img,
  Link,
  Preview,
  Section,
  Text,
  Font,
} from '@react-email/components'

const MyEmail = ({ name = 'Anjan' }) => {
  const previewText = 'Your free guide is here! Download now.'
  const downloadUrl = 'https://reallygreatsite.com/download'

  return (
    <Html>
      <Tailwind>
        <Head>
          <title>Your Free Guide Is Heretitle>
          <Font
            fontFamily='Inter'
            fallbackFontFamily='Arial'
            webFont={{
              url: 'https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&display=swap',
              format: 'woff2',
            }}
            fontWeight={400}
            fontStyle='normal'
          />
        Head>
        <Preview>{previewText}Preview>
        <Body className="bg-[#e5e5e3] font-['Inter',Arial,sans-serif] py-10">
          <Container className='mx-auto max-w-[600px] text-center'>
            {/* Email content here */}
            <Heading className="text-5xl leading-tight font-extrabold text-[#333333] my-8 font-['Inter',Arial,sans-serif] uppercase tracking-tight">
              YOUR FREE GUIDE IS HERE {name.toUpperCase()} 🎉
            Heading>

            {/* More content... */}

            <Section className='my-10'>
              <Link
                href={downloadUrl}
                className='bg-[#333333] rounded-full text-white text-base font-semibold no-underline uppercase py-4 px-10 inline-block'
              >
                DOWNLOAD NOW
              Link>
            Section>
          Container>
        Body>
      Tailwind>
    Html>
  )
}

export default MyEmail

Explanation:

  • This template uses React Email components like Html, Body, Heading, and Link to create a responsive email that works across email clients.
  • The Tailwind component allows us to use Tailwind CSS for styling.
  • We're also accepting a name prop to personalize the email, illustrating how to make dynamic email templates.

Preview Email Templates

To preview your email templates during development, add this script to your package.json:

"scripts": {
  "email:dev": "email dev --dir ./src/emails --port 4000"
}

Explanation:

  • This script sets up a development server specifically for previewing email templates.
  • We're pointing it to our src/emails directory.
  • The server runs on port 4000 to avoid conflicts with Next.js on port 3000.
  • You can run npm run email:dev to see your templates at http://localhost:4000.

Sending Emails with Resend

Create a server action to handle email sending in src/actions/sendEmail.js:

'use server'

import MyEmail from '@/emails/MyEmail'
import { Resend } from 'resend'

const sendEmail = async formData => {
  const name = formData.get('name')

  const resend = new Resend(process.env.RESEND_API_KEY)

  const { data, error } = await resend.emails.send({
    from: '[email protected]', // Development only
    to: '[email protected]',
    subject: 'Welcome to Resend!',
    react: <MyEmail name={name} />,
  })

  if (error) {
    console.error(error)
    return { success: false }
  }

  console.log(data)
  return { success: true }
}

export default sendEmail

Explanation:

  • This server action uses the 'use server' directive to ensure it runs on the server.
  • It extracts the name from the form data.
  • It initializes Resend with your API key.
  • It sends an email with your React template.
  • For development, you can use the [email protected] email address.
  • The user's name is passed to the template to personalize it.

Then create a form in src/app/page.jsx to trigger the email:

import sendEmail from '@/actions/sendEmail'

export default function Home() {
  return (
    <div>
      <form
        action={sendEmail}
        className='flex flex-col items-center justify-center h-screen'
      >
        <input
          type='text'
          name='name'
          placeholder='Name'
          className='border border-gray-500 rounded mb-3 p-4'
        />
        <button className='bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded'>
          Send Email
        button>
      form>
    div>
  )
}

Explanation:

  • This simple form collects a name.
  • The action attribute invokes our server action when submitted.
  • In Next.js, the form data is passed directly to our server action, making it straightforward to handle user input.

Setting Up a Custom Domain

For production, you'll need to use and verify a custom domain with Resend:

Please check the YouTube video:

Once verified, update your sender email:

from: '@yourdomain.com', //  can be anything

Scheduling Emails

Resend allows scheduling emails using natural language or date formats:

const { data, error } = await resend.emails.send({
  from: '[email protected]',
  to: '[email protected]',
  subject: 'Scheduled Email',
  react: <MyEmail name={name} />,
  scheduledAt: 'in 2 min', // or specific date: '2023-04-30T09:30:00Z'
})

Explanation:

  • The scheduledAt parameter supports natural language like "in 2 min" or "tomorrow at 9am."
  • It's useful for sending reminders, welcome sequences, or other time-sensitive emails.

Adding Attachments

To include file attachments, use the attachments array in the send method. Here is an example where we are expecting an image file from the form:

Add a file input to your form:

<input
  className='border border-gray-500 rounded mb-3 p-4'
  type='file'
  accept='image/*'
  name='image'
/>

Explanation:

  • This file input restricts uploads to images.
  • The name="image" attribute must match the name we use in formData.get('image') in our server action.
const sendEmail = async formData => {
  const name = formData.get('name')
  const imageFile = formData.get('image')

  // Convert file to base64
  const arrayBuffer = await imageFile.arrayBuffer()
  const buffer = Buffer.from(arrayBuffer)
  const base64Image = buffer.toString('base64')

  const resend = new Resend(process.env.RESEND_API_KEY)

  const { data, error } = await resend.emails.send({
    from: '[email protected]',
    to: '[email protected]',
    subject: 'Email with Attachment',
    react: <MyEmail name={name} />,
    attachments: [
      {
        filename: imageFile.name,
        content: base64Image,
      },
    ],
  })
}

Explanation:

  • This code handles file uploads through the form.
  • It converts files to base64 (required for email attachments).
  • It adds the base64-encoded file to the email.
  • Be aware of file size limits — Next.js server actions have a 1MB default limit per request.

Limitations and Considerations

  • Styling: React Email only supports inline styles or Tailwind CSS.
  • UI Libraries: External libraries like Material UI or Chakra UI aren't supported by React Email.
  • Scheduling + Attachments: Attachments cannot be used with scheduled emails.

Conclusion

Sending emails from your Next.js application is straightforward with Resend and React Email. You can:

  • Create dynamic, responsive templates using React Email.
  • Handle all the sending logic through Resend’s simple API.

For more information, check out the: