EmailSender With Nodemailer
Registered members can download the FREE Get Started App. This is the project I used to compose articles about setting up VS Code and developing Node with Express and the Embedded JavaScript (EJS) view engine.
This article describes how to implement an EmailSender utility with the nodemailer library configured to use an existing SMTP server. The nodemailer's default transport is SMTP. A transport is the mechanism Nodemailer uses to deliver a fully-constructed email message. This could involve piping the message to the local sendmail binary, posting it to an HTTPS API like Amazon SES, or using any other delivery method you choose.
When I decided to learn Express, I found a lot of articles and AI suggestions which did not implement ES6 standards. ES6 or ECMAScript 2015 changed the landscape of JavaScript with the ability to create promises for asynchronous programming. I am familiar with ASP.NET Core and C# web applications and SQL Server databases. I developed this Express application with KenHaggerty.Com as a model. Registered members can download the FREE Get Started PostgreSQL app and Get Started MySQL app which implement this getting started with Express EJS tutorial.
Let's Talk About Express
Development Environment Setup
Features Since ECMAScript 2015(ES6)
Express EJS Template Engine
Express EJS Views, Layouts, and Partials
Express Error Handling
Express Routers and Controllers
Express Environment Variables
MySQL and Services
PostgreSQL and Services
EmailSender With Nodemailer
You need to add the nodemailer package to the project. From a Terminal window opened in the project folder, execute the npm CLI (Node Package Manager Command Line Interface) install command.
npm install nodemailer
This configuration requires an existing SMTP server. Many hosting services offer a SMTP server with a domain name registration. Other services like Amazon SES (SES), SendGrid, or Mailgun offer SMTP servers. If you have an SMTP server, use the .env file to pass the SMTP configuration to the application's process.env object.
.env
SMTP_CONFIGURED=true SMTP_HOST=smtp.example.com SMTP_PORT=587 SMTP_SECURE=false SMTP_AUTH_USER=support@example.com SMTP_AUTH_PASSWORD=P@ssword SMTP_ADMIN_EMAIL=admin@example.com
Add a new root directory named Utilities and add a new file named email-sender.mjs. Import nodemailer.
email-sender.mjs
import nodemailer from 'nodemailer';
const EmailSender = {};
// Transporter configuration
const transporter = nodemailer.createTransport({
host: process.env.SMTP_HOST,
port: process.env.SMTP_PORT,
secure: process.env.SMTP_SECURE === 'true',
auth: {
user: process.env.SMTP_AUTH_USER,
pass: process.env.SMTP_AUTH_PASSWORD,
},
});
EmailSender.verify = async () => {
try {
await transporter.verify();
console.log("The Transporter verified successfully.");
return { success: true };
} catch (error) {
console.error("Verification failed", error);
return { success: false };
}
};
EmailSender.send = async (mailOptions) => {
try {
const info = await transporter.sendMail(mailOptions);
console.log('Message sent: %s', info.messageId);
return { success: true, info: info };
} catch (error) {
console.error('Error sending email:', error.message);
return { success: false, error: error.message };
}
};
export default EmailSender;
The Get Started App has a contact us form in a modal complete with client-side validation. If SMTP_CONFIGURED=true the modal is enabled.
The modal posts the form data to a contact-us route. You need to configure a mailOptions parameter to pass to the EmailSender.send function. The mailOptions include a text formatted and a html formatted message. The Get Started App has an InputValidator module for server-side validation. The Get Started App also has a Formatter module with a getContactUsTemplate function which provides a HTML formatted message.
Import the EmailSender.
import EmailSender from '../utilities/email-sender.mjs';
Validate client form inputs, configure the mailOptions, and send both text and html messages with the EmailSender.
const { email, subject, message, verifyhuman } = req.body;
if (parseInt(verifyhuman) != 2) throw new Error("Human verification failed.");
let validatorResult = InputValidator.emailAddress(email);
if (!validatorResult.valid) throw new Error("Email validation failed.");
if (subject.length < 8 || subject.length > 100) throw new Error("Subject length validation failed.");
validatorResult = InputValidator.containsHTML(subject);
if (!validatorResult.valid) throw new Error("Subject validation failed.");
if (message.length < 20 || message.length > 500) throw new Error("Message length validation failed.");
validatorResult = InputValidator.containsHTML(message);
if (!validatorResult.valid) throw new Error("Message validation failed.");
const contaxtUsSubject = 'New Contact from Get Started App';
const textMessage = `Contact's Email: ${email}\nContact's Subject: ${subject}\nContact's Message:\n${message}`;
const htmlMessage = Formatter.getContactUsTemplate(contaxtUsSubject, email, subject, message);
const mailOptions = {
from: process.env.SMTP_AUTH_USER, // The authorized sender email address
to: process.env.SMTP_ADMIN_EMAIL, // The administrator email address you want to receive emails
subject: contaxtUsSubject,
text: textMessage,
html: htmlMessage
};
const senderResult = await EmailSender.send(mailOptions);
if (senderResult != null && senderResult.success) {
console.log("Email sent: ", senderResult.info.response);
return res.status(201).redirect('/about?statusalert=Email sent. We will respond ASAP.');
} else {
let error = "Error: result is null.";
if (senderResult != null) { error = "Error: " + senderResult.error; }
console.error(error);
return res.status(201).redirect('/about?statusalert=Error: There was a problem sending the email.');
}