How to work with NodeMailer

To handle email sending, we utilize the nodemailer library. The primary logic for initializing and sending emails is located in backend/src/services/email/index.js.

Email Sending Logic

In the index.js file, the core functionality for sending emails is implemented as follows:

...
async send() {
  if (!EmailSender.isConfigured) {
    console.error(
      `Email provider is not configured. Please configure it in backend/config/<environment>.json.`,
    );
    return;
  }

  assert(this.email, 'email is required');
  assert(this.email.to, 'email.to is required');
  assert(this.email.subject, 'email.subject is required');
  assert(this.email.html, 'email.html is required');

  const transporter = nodemailer.createTransport(this.transportConfig);

  const mailOptions = {
    from: this.from,
    to: this.email.to,
    subject: this.email.subject,
    html: this.email.html,
  };

  return transporter.sendMail(mailOptions);
}
...

This function verifies if the email configuration is set up properly before sending an email. It ensures that the email object contains the necessary fields: to, subject, and html.

Configuration Checks

The file also includes several utility functions to check for email configuration settings:

const config = require('../../config');
...
...
...
static get isConfigured() {
  return !!config.email?.auth?.pass && !!config.email?.auth?.user;
}

get transportConfig() {
  return config.email;
}

get from() {
  return config.email.from;
}
...

These functions help determine if the email settings are properly configured in the configuration file backend/src/config.js.

Email Configuration

You can set your email configurations in the aforementioned configuration file backend/src/config.js as follows:

email: {
  from: 'ReactTemplateExample <[email protected]>',
  host: 'email-smtp.us-east-1.amazonaws.com',
  port: 587,
  auth: {
    user: 'authKey',
    pass: process.env.EMAIL_PASS,
  },
  tls: {
    rejectUnauthorized: false,
  },
},

Adding a Custom Email Template

Next, let’s explore how to add a custom email template, using the existing emailAddressVerification template as an example.

Step 1: Create a New Email Template Class

First, add a new class for your email template in the backend/src/services/email/list folder, such as EmailAddressVerificationEmail:

module.exports = class EmailAddressVerificationEmail {
  constructor(to, link) {
    this.to = to;
    this.link = link;
  }

  get subject() {
    return getNotification(
      'emails.emailAddressVerification.subject',
      getNotification('app.title'),
    );
  }

  get html() {
    return getNotification(
      'emails.emailAddressVerification.body',
      this.link,
      getNotification('app.title'),
    );
  }
};

In this class, two key functions, subject and html, are used to set the subject and content of the email.

Step 2: Define the Email Template

The subject and html for the email are added to the backend/src/services/notifications/list.js file, where the main email templates are stored:

emails: {
  ...
  emailAddressVerification: {
    subject: `Verify your email for {0}`,
    body: `
      <p>Hello,</p>
      <p>Follow this link to verify your email address:</p>
      <p><a href='{1}'>{1}</a></p>
      <p>If you didn't request this verification, please ignore this email.</p>
      <p>Thanks,</p>
      <p>Your {2} team</p>
    `,
  },
  ...
},

Here are the key parameters:

  • subject: The subject of the email.
  • body: The content of the email in HTML format.

You can also pass parameters into the email content, as shown in this line:

<p><a href='{1}'>{1}</a></p>

Step 3: Use the Email Template

Finally, you can use the created email template class to send emails:

...
const emailAddressVerificationEmail = new EmailAddressVerificationEmail(
  email,
  link,
);

return new EmailSender(emailAddressVerificationEmail).send();
...

The complete code using EmailAddressVerificationEmail can be found in the backend/src/services/auth.js file.