DEV Community

Cover image for How to Integrate SMTP in Next.js 14 Using Nodemailer
Devam Chaudhari
Devam Chaudhari

Posted on

How to Integrate SMTP in Next.js 14 Using Nodemailer

Introduction to SMTP

  • SMTP (Simple Mail Transfer Protocol) is the standard protocol for sending emails over the internet. It defines how emails are transmitted from one server to another. SMTP is responsible for routing and ensuring the secure delivery of emails, making it an essential part of email communication in web applications.

  • When developing a web application, integrating SMTP allows you to send emails for purposes like account verification, notifications, or inquiry responses. In this guide, we will walk through how to set up SMTP email sending in a Next.js 14 application using Nodemailer, a popular Node.js package for handling emails.


Step 1: Install Nodemailer

npm install nodemailer
Enter fullscreen mode Exit fullscreen mode

Step 2: Set Up Environment Variables

  • For security, sensitive SMTP credentials should not be hard-coded into your application. Instead, store them in environment variables. Create a .env.local file in the root directory of your project and add the following configuration:
SMTP_HOST=smtp.example.com
SMTP_PORT=587 // Typically 587 (for TLS) or 465 (for SSL).
SMTP_USER=your-smtp-username
SMTP_PASS=your-smtp-password
NEXT_PUBLIC_EMAIL_TO=from@example.com

Enter fullscreen mode Exit fullscreen mode

Step 3: Create the API Route for Sending Emails

  • Next.js allows you to create API routes to handle server-side logic. We'll use this feature to send emails using Nodemailer
src/
  app/
    api/
      sendEmail/
        route.ts   # API Route for handling email sending
    component/     # Frontend components for the UI

Enter fullscreen mode Exit fullscreen mode

In the src/app/api/sendEmail/route.ts file, add the following code:

import { NextRequest, NextResponse } from 'next/server';
import nodemailer from 'nodemailer';

export async function POST(req: NextRequest) {
    try {
        const { to, cc, bcc, message } = await req.json();

        const transporter = nodemailer.createTransport({
            host: process.env.SMTP_HOST,
            port: Number(process.env.SMTP_PORT),
            secure: false, // Set to true for port 465, otherwise false
            auth: {
                user: process.env.SMTP_USER,
                pass: process.env.SMTP_PASS,
            },
        });

        const info = await transporter.sendMail({
            from: process.env.NEXT_PUBLIC_EMAIL_TO,
            to,                                    
            cc,                                    
            bcc,                                   
            subject: message.subject || 'No Subject', 
            text: message.text,        
            html: message.html,                  
        });

        return NextResponse.json({ message: 'Email sent successfully', info }, { status: 200 });
    } catch (error: any) {
        console.error('Error sending email:', error);
        return NextResponse.json({ message: 'Failed to send email', error: error.message }, { status: 500 });
    }
}

Enter fullscreen mode Exit fullscreen mode

Explanation:

  • POST Method: Handles HTTP POST requests sent to the /api/sendEmail/route.ts.

  • Nodemailer Transporter: Configures your SMTP credentials (from the .env.local file) to send emails.

  • Email Content: Takes input such as to, cc, bcc, subject, text, and html to define the structure and content of the email.

  • Error Handling: Returns an appropriate error message if email sending fails.


Step 4: Frontend Form to Send Emails

import { useState } from 'react';

export default function EmailForm() {
    const [formData, setFormData] = useState({
        name: '',
        email: '',
        phoneNo: '',
        message: ''
    });

    const handleSubmit = async (e) => {
        e.preventDefault();
        try {
            const response = await fetch('/api/sendEmail', {
                method: 'POST',
                headers: { 'Content-Type': 'application/json' },
                body: JSON.stringify({
                  to: [process.env.NEXT_PUBLIC_EMAIL_TO],
                  cc: [''], 
                  bcc: [process.env.NEXT_PUBLIC_EMAIL_BCC],
                  message: {
                     subject: `YOUR SUBJECT`,
                     text: 'YOUR TEXT',
                     html: `
                     <html>
                        <head></head>
                        <body>
                           <p>Hello user</p>
                           <p><b>Full Name:</b> ${formData.name}</p>
                           <p><b>Email:</b> ${formData.email}</p>
                           <p><b>Phone number: </b> ${formData.phoneNo}</p>
                           <p><b>Message:</b> ${formData.message}</p>
                           <br>
                           <p>Thank you & Regards,<br><b>Team</b></p>
                        </body>
                     </html>`,
                  },
               }),
            });

            const result = await response.json();
            alert(result.message); // You can also add route instead of alert  route.push() add you own page.
        } catch (error) {
            console.error('Error sending email:', error);
        }
    };

    return (
        <form onSubmit={handleSubmit}>
            <input
                type="text"
                placeholder="Your Name"
                value={formData.name}
                onChange={(e) => setFormData({ ...formData, name: e.target.value })}
                required
            />
            <input
                type="email"
                placeholder="Your Email"
                value={formData.email}
                onChange={(e) => setFormData({ ...formData, email: e.target.value })}
                required
            />
            <input
                type="text"
                placeholder="Your Phone Number"
                value={formData.phoneNo}
                onChange={(e) => setFormData({ ...formData, phoneNo: e.target.value })}
            />
            <textarea
                placeholder="Your Message"
                value={formData.message}
                onChange={(e) => setFormData({ ...formData, message: e.target.value })}
                required
            />
            <button type="submit">Send Message</button>
        </form>
    );
}

Enter fullscreen mode Exit fullscreen mode

Top comments (2)

Collapse
 
cookiemonsterdev profile image
Mykhailo Toporkov πŸ‡ΊπŸ‡¦ • Edited

Also for testing purposes can be used ethereal.emai, it fakes SMTP service for you.

And in markdown you can specify lang right after opening code block e.g:

function MyComponent() {
  return <div>MyComponent</div>
}
Enter fullscreen mode Exit fullscreen mode
Collapse
 
chaudharidevam profile image
Devam Chaudhari

I appreciate your feedback. Thank you for your input! πŸ˜€