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
, andLink
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 athttp://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 informData.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: