Sending emails from your web app is a standard task, whether it’s a welcome message, a password reset, or an email notification. In this blog, we are going to show how to add email functionality to a Remix app using Nodemailer, a Node.js module for sending emails. This blog is aimed at new developers with simple steps to follow along.

What is Remix and Nodemailer?
- Remix: A full-stack web framework to build fast, modern web apps with React. Remix handles both your front-end with React as well as your back-end. This is good for sending emails since emailing is mostly a server-side function.
- Nodemailer: A Node.js module used for letting you send emails very easily. Nodemailer works with many different email services, such as using an application with Gmail, Sendgrid, or even Mailgun.
By combining the server capabilities of Remix with Nodemailer, we will be able to send an email directly from the web app.
Prerequisites
Before we get started, please make sure you have:
- Node.js (v18 or higher) installed.
- Remix app created. If you do not have a Remix app yet, please create one using npx create-remix@latest.
- Email service account (we will be using a Gmail account in this tutorial). You’ll need an App Password if you’re using Gmail with 2-factor authentication.
- Basic understanding of JavaScript and React.
Steps to Add Email Functionality in a Remix App Using Nodemailer:
Step 1: Set Up Your Remix App
If you don’t already have a Remix app, you can create one. Run the following command:
npx create-remix@latest
Then just follow the prompts to set up your project. For simplicity, you can take all of the defaults (like choosing “Just the basics” and “Remix App Server”). When you finish the setup, use your terminal to navigate to the project folder you created and run the development server:
cd your-app-name
npm run dev
Now the app should be running at https://localhost:3000.
Step 2: Install Nodemailer
Nodemailer is a Node.js package, so we need to install it in the Remix project. In your terminal, execute:
npm install nodemailer
This will add Nodemailer as a dependency to your project.
Step 3: Configure Nodemailer with Gmail
To send emails, Nodemailer needs an email service to work with. We’ll use Gmail for this example, but you can adapt the steps for other providers like SendGrid or Mailgun.
Get Gmail App Password
If you’re using Gmail with 2-factor authentication, you’ll need an App Password:
- Go to your Google Account settings.
- Enable 2-factor authentication if it’s not already on.
- Navigate to Security > 2-Step Verification > App passwords.
- Create a new app password for “Mail” and copy the 16-character code.
Set Up Environment Variables
To keep your email credentials secure, store them in a .env file. Create a file named .env in the root of your Remix project and add:
EMAIL_USER=your-email@gmail.com
EMAIL_PASS=your-app-password
Replace your-email@gmail.com with your Gmail address and your-app-password with the App Password you generated.
Install the dotenv package to load these variables:
npm install dotenv
Remix automatically loads .env files, so you don’t need to configure dotenv manually.
Step 4: Create an Email-Sending Route
In Remix, routes handle both the UI and server-side logic. Let’s create a route to send emails when a user submits a form.
Create the Route File
In the app/routes folder, create a new file called send-email.jsx. This route will display a form and handle email sending.
Add the following code to app/routes/send-email.jsx:
import { Form, useActionData } from "@remix-run/react";
import nodemailer from "nodemailer";
export const action = async ({ request }) => {
const formData = await request.formData();
const to = formData.get("to");
const subject = formData.get("subject");
const text = formData.get("text");
// Create a Nodemailer transporter
const transporter = nodemailer.createTransport({
service: "gmail",
auth: {
user: process.env.EMAIL_USER,
pass: process.env.EMAIL_PASS,
},
});
// Define email options
const mailOptions = {
from: process.env.EMAIL_USER,
to,
subject,
text,
};
// Send the email
try {
await transporter.sendMail(mailOptions);
return { message: "Email sent successfully!" };
} catch (error) {
return { error: "Failed to send email: " + error.message };
}
};
export default function SendEmail() {
const actionData = useActionData();
return (
<div style={{ padding: "20px", fontFamily: "Arial" }}>
<h1>Send an Email</h1>
<Form method="post">
<div>
<label htmlFor="to">Recipient Email:</label>
<input type="email" name="to" id="to" required />
</div>
<div>
<label htmlFor="subject">Subject:</label>
<input type="text" name="subject" id="subject" required />
</div>
<div>
<label htmlFor="text">Message:</label>
<textarea name="text" id="text" required></textarea>
</div>
<button type="submit">Send Email</button>
</Form>
{actionData?.message && <p style={{ color: "green" }}>{actionData.message}</p>}
{actionData?.error && <p style={{ color: "red" }}>{actionData.error}</p>}
</div>
);
}
Explanation of the Code
- Action Function: The action function runs on the server when the form is submitted. It:
- Retrieves form data (to, subject, text).
- Sets up a Nodemailer transporter using Gmail credentials from the .env file.
- Sends the email using transporter.sendMail.
- Returns a success or error message.
- Form Component: The UI includes a form with fields for the recipient’s email, subject, and message. The useActionData hook displays feedback (success or error) after submission.
Step 5: Test the Email Functionality
- Start your Remix app if it’s not already running:
npm run dev
- Open your browser and go to https://localhost:3000/send-email.
- Fill out the form with a valid recipient email, subject, and message.
- Click “Send Email” and check if the recipient receives the email. You should also see a success or error message on the page.
If you’re using Gmail, check your Sent folder to confirm the email was sent. If you encounter errors, double-check your .env file credentials and ensure your Gmail App Password is correct.
Conclusion
Adding email functionality to a Remix app with Nodemailer is straightforward. By setting up a route, configuring Nodemailer with an email service, and creating a simple form, you can send emails directly from your app. This is just the beginning—you can enhance this feature by adding email templates, handling attachments, or integrating with other email providers like SendGrid or Mailgun.

Try experimenting with different email services or adding more features to the form, like CC/BCC fields or HTML email content.
Happy Coding!