Building a Serverless Email Handler with SMTP and Sitecore Send

Learn how to send emails using SMTP with Sitecore Send, Next.js and Nodemailer.

April 11, 2025

By John Flores

Why SMTP Matters in Modern Projects

Effective communication is essential for businesses, whether it's sending transactional emails, notifications, or critical alerts. Emails also serve as a direct channel between customers and stakeholders handling specific requests. This is especially true for smaller companies that prefer a simple, reliable email-based workflow instead of complex third-party systems.

To protect these communication channels from exposure and potential security threats, businesses rely on SMTP (Simple Mail Transfer Protocol). SMTP not only ensures secure and controlled email delivery but also helps safeguard sensitive addresses from direct customer access.

If you're using Sitecore Send, you already have a built-in solution for handling SMTP without the need for additional third-party tools. In this blog, I'll guide you through setting up SMTP with Sitecore Send and implementing a serverless function in Next.js to streamline your email operations. We’ll first have to find the credentials found in Sitecore Send that is commonly needed for SMTP.

Finding the SMTP Credentials in Sitecore Send

Each organization has its own Sitecore Send URL, which follows this format:

https://<unique-identifier>.sitecoresend.io.

When you visit this URL, you'll see a login screen similar to the one below:

Sitecore Send login screen with fields for email address and password

You should have login credentials provided by the account owner. Once successfully logged in, you'll be redirected to the Home page. Here's an example of what it looks like:

Sitecore Send dashboard showing latest automation campaign analytics with metrics for recipients

  1. In the top menu, click More.
  2. From the dropdown, select Settings.

Sitecore Send dashboard with navigation dropdown open under 'More' and a red arrow pointing to the 'Settings' option for accessing SMTP configuration

This will open the Settings page. On the left-hand navigation menu, click Direct SMTP.

Sitecore Send settings page with a red arrow pointing to the 'Direct SMTP' option in the left-hand menu

You should now see the SMTP configuration screen. Ensure that the Use SMTP toggle is enabled.

Sitecore Send settings page with 'Direct SMTP' selected and the 'Use SMTP' toggle enabled

Below this toggle, you'll find the required SMTP credentials:

  • SMTP Hostname
  • SMTP Port
  • SMTP Username
  • SMTP Password

These are the details needed to configure SMTP within Sitecore Send. Next, we'll proceed with setting it up in Next.js.

Sitecore Send 'Direct SMTP' settings page with SMTP credentials section highlighted, showing fields for hostname, port, username, and password with the 'Use SMTP' toggle enabled

Integrating SMTP with Next.js Using Sitecore Send

To avoid diving too deep into the entire development process, let’s establish some assumptions. Our function will consume two key data sets:

  • Environment Variables – These store credentials retrieved from Sitecore Send, following a standard naming convention: SEND_PORT, SEND_HOSTNAME, SEND_USERNAME, and SEND_PASSWORD.
  • Request Data – This consists of a POST request body containing essential details, including stakeholder-required information and necessary email parameters.

Email Next.js Serverless Function

Below is the complete serverless function, which leverages nodemailer to configure SMTP using Sitecore Send credentials. The request body is then used to populate and send the email to the specified recipient.

I’ll walk through the code and break down each part in detail.

import { NextApiRequest, NextApiResponse } from 'next';
import nodemailer from 'nodemailer';
import axios from 'axios';

export default async function handler(req: NextApiRequest, res: NextApiResponse): Promise<void> {
  if (req.method !== 'POST') {
    return res.status(405).json({ error: 'Method not allowed' });
  }

  const { subject, recipient, ...data } = req.body;

  if (
    !process.env.SEND_USERNAME||
    !process.env.SEND_PASSWORD||
    !process.env.SEND_PORT||
    !process.env.SEND_HOSTNAME
  ) {
    console.error('Environment variables are not set');
    return res.status(500).send('Internal server error');
  }

  const transporter = nodemailer.createTransport({
    port: process.env.SEND_PORT,
    host: process.env.SEND_HOSTNAME,
    auth: {
      user: process.env.SEND_USERNAME,
      pass: process.env.SEND_PASSWORD,
    },
    secure: false,
  });

  const mailData = {
    from: 'noreply@sample_company.com',
    to: recipient,
    subject: subject,
    html: generateHtmlFromFormData(data),
  };

  try {
    const info = await transporter.sendMail(mailData);
    console.log('Email sent successfully:', info);
    res.status(200).end();
  } catch (err) {
    console.error('Error sending email:', err);
    res.status(500).send('Internal Server Error');
  }
}

function generateHtmlBody() {
  return `
    <html>
      <body>
         ... HTML BODY FOR YOUR EMAIL ...
      </body>
    </html>
  `;
}

Step-by-Step Guide to Email Handling in Next.js

Importing Dependencies

At the very top we have the packages we are using for our serverless function. NextApiRequest & NextApiResponse are used to define the API routes in Next.js. Nodemailer is used to setup the SMTP and actually send the emails, and axios for sending HTTP requests.

import { NextApiRequest, NextApiResponse } from 'next';
import nodemailer from 'nodemailer';
import axios from 'axios';

Defining the API Handler

We then have the common code format for serverless function which is to define the API Handler.

export default async function handler(req: NextApiRequest, res: NextApiResponse): Promise<void> {
  if (req.method !== 'POST') {
    return res.status(405).json({ error: 'Method not allowed' });
  }

  const { subject, recipient, ...data } = req.body;

Right below the function opening, we’ve added a flag to only allow a POST method. Next, we extract the request body. This contains the information needed to construct the email and the rest of the data used to populate the email body.

Validating Environment Variables

Before proceeding, we ensure that all required environment variables are present. If any are missing, the function logs an error and stops execution to prevent misconfigurations.

  if (
    !process.env.SEND_USERNAME||
    !process.env.SEND_PASSWORD||
    !process.env.SEND_PORT||
    !process.env.SEND_HOSTNAME
  ) {
    console.error('Environment variables are not set');
    return res.status(500).send('Internal server error');
  }
  • If any of the required environment variables are missing, the function logs an error and stops execution by returning a 500 Internal Server Error response.
  • This ensures that email sending does not proceed with incomplete credentials, preventing potential misconfigurations or security risks.

Configuring SMTP Transport

Next, we configure the SMTP transport using nodemailer. This transport object will handle the email delivery.

  const transporter = nodemailer.createTransport({
    port: process.env.SEND_PORT,
    host: process.env.SEND_HOSTNAME,
    auth: {
      user: process.env.SEND_USERNAME,
      pass: process.env.SEND_PASSWORD,
    },
    secure: false,
  });
  • nodemailer.createTransport() - This initializes an SMTP transporter with the necessary credentials.
  • port and **host - These define the SMTP server’s connection details, retrieved from the environment variables.
  • auth - Specifies the username and password required for authentication.
  • secure: false - The secure flag determines whether SSL/TLS is used for the connection. Setting it to false is fine for most cases, but if your SMTP provider requires SSL/TLS (e.g., port 465), you may need to set it to true.

Constructing the Email Content

With the SMTP transporter configured, the next step is to define the email content. The recipient's email is dynamically assigned based on the configuration in Sitecore, ensuring flexibility. To keep the code organized, the email body (html value) is generated using a separate function, which will be covered in the next section. This approach ensures each email includes the correct recipient and content while maintaining a clean and modular structure.

  const mailData = {
    from: 'noreply@sample_company.com',
    to: recipient,
    subject: subject,
    html: generateHtmlFromFormData(data),
  };

Sending Emails and Error Handling

Once the email is prepared, the function attempts to send it using transporter.sendMail().

  try {
    const info = await transporter.sendMail(mailData);
    console.log('Email sent successfully:', info);
    res.status(200).end();
  } catch (err) {
    console.error('Error sending email:', err);
    res.status(500).send('Internal Server Error');
  }

This ensures the function gracefully handles failures instead of crashing the application.

Dynamically Constructing the Email Content

To keep the main function clean and modular, we define a separate function to generate the email’s HTML content.

function generateHtmlBody() {
  return `
    <html>
      <body>
       ... HTML BODY FOR YOUR EMAIL ...
      </body>
    </html>
  `;
}

Exploring SMTP and Sitecore Send in Depth

In the world of marketing and communication, email remains a crucial tool. So far, we’ve covered just one aspect of SMTP—sending a basic email. However, there’s much more to explore.

One key challenge in email delivery is handling attachments. How do you securely and efficiently send files along with your emails? We’ll take a closer look at how SMTP supports attachments and how to implement them in your setup. We can even further improve our current function to also handle bounced emails in case there’s a failure.

Beyond SMTP, Sitecore Send offers additional features that can enhance your email-sending capabilities. From advanced templating options to analytics and automation, we’ll dive deeper into how Sitecore Send can streamline and optimize your email workflows.

John Headshot

John Flores

Front-End Developer | Sitecore Technology MVP

John is a Senior Front-End Developer who is passionate about design and development. Outside of work, John has wide range of hobbies, from his plant collection, being a dog daddy, and a foodie. John is also a Sitecore Technology MVP!