Sending Emails from Express Application

Using Nodemailer and Gmail

Sending Emails from Express Application

by John Vincent


Posted on July 01, 2017



This is not a trivial task. Let's discuss.

Sending emails from an Express Application is a standard requirement.

Nodemailer

Npm package Nodemailer is the standard.

npm install nodemailer --save

Gmail variables are defined in the environment. Thus, to access

email.js

const {
    GMAIL_SERVICE, GMAIL_AUTH_TYPE, GMAIL_AUTH_USER, GMAIL_AUTH_CLIENT_ID, GMAIL_AUTH_CLIENT_SECRET,
    GMAIL_AUTH_REFRESH_TOKEN, GMAIL_AUTH_ACCESS_TOKEN, GMAIL_FROM_EMAIL, GMAIL_SUPPORT_EMAIL
} = process.env;

All email tasks are performed in class EmailUtils, email.js

const nodemailer = require('nodemailer');

The actual sending of the email

sendEmail(emailData) {

    let auth = {
        "type": GMAIL_AUTH_TYPE,
        "user": GMAIL_AUTH_USER,
        "clientId": GMAIL_AUTH_CLIENT_ID,
        "clientSecret": GMAIL_AUTH_CLIENT_SECRET,
        "refreshToken": GMAIL_AUTH_REFRESH_TOKEN,
        "accessToken": GMAIL_AUTH_ACCESS_TOKEN
    };

    const transporter = nodemailer.createTransport({
        service: GMAIL_SERVICE,
        auth
    });

    logger.info(`Attempting to send email from ${emailData.from}`);
    transporter
        .sendMail(emailData)
        .then(info => console.log(`Email sent: ${info.response}`))
        .catch(err => console.log(`Problem sending email: ${err}`));
}

emailData has a specific structure

const subject = 'Subject';
const text = template.replace('', email_url);
const html = `<p>Html email </p><ul><li>Name: abcd</li><li>Email:  abc@def.com</li><li>Message: Hi</li></ul>`;
var mailOptions = {
    from: '"My Title"' + GMAIL_FROM_EMAIL,
    to,
    subject,
    text
};

Note that Html is optional, if it is not defined the text variable will be used.

Nodemailer Configuration

Nodemailer OAuth2 document is a good reference. I will configure using 3. Set up 3LO authentication

Gmail Configuration

This YouTube video was nearly there.

This is slightly useful

The Gmail variables are stored in the environment

GMAIL_SERVICE=Gmail
GMAIL_AUTH_TYPE=OAuth2
GMAIL_AUTH_USER=<gmail address used for the authentication, see below>

GMAIL_FROM_EMAIL=email@johnvincent.io
GMAIL_SUPPORT_EMAIL=support@johnvincent.io

GMAIL_AUTH_CLIENT_ID
GMAIL_AUTH_CLIENT_SECRET
GMAIL_AUTH_REFRESH_TOKEN
GMAIL_AUTH_ACCESS_TOKEN
  1. Google API Manager
  2. Select or add a project, Project = johnvincentio
  3. Gmail API
    1. Enable
  4. Credentials
  5. OAuth consent Screen.
    1. Product name: your Project
    2. Save
  6. Credentials
  7. Create Credentials
    1. OAuth client id
    2. Web Application, name = johnvincentio
      1. or maybe: Other, name = johnvincentio
    3. Authorized redirect URIs:
      1. https://developers.google.com/oauthplayground/
      2. Create>
      3. Copy the clientId to GMAIL_AUTH_CLIENT_ID
      4. Copy clientSecret to GMAIL_AUTH_CLIENT_SECRET
  8. Google Developers OAuth 2.0 Playground
  9. Click gear icon (top right)
  10. Check: Use your own OAuth credentials
  11. Enter the client id and Client Secret fields from OAuth Client id (same as above).
  12. Left pane, input your own scopes
    1. https://mail.google.com
    2. Authorize APIs
      1. Allow my email address to access my email.
      2. Exchange authorization code for tokens.
      3. Check: Auto-refresh the token before it expires
      4. Copy refresh token to GMAIL_AUTH_REFRESH_TOKEN

Extra Gmail Addresses using G Suite

This Google doc helps

  1. Login to Gmail
  2. Settings
  3. Accounts
  4. Add another email address
    1. support@johnvincent.io
      1. Check: treat as an alias
      2. Specify a different “reply-to” address
      3. Reply to address:
        1. support@johnvincent.io
      4. next step»>
      5. send verification>
    2. Email will arrive. Click on the link
      1. Confirm>
    3. Refresh Gmail
      1. Settings
      2. Accounts

Repeat for email@johnvincent.io

Random Strings

email.js

const randomstring = require('randomstring');

To create the URL

userTaskEmail(id, req, to) {
    let random = randomstring.generate({
        length: 20,
        charset: 'alphanumeric'
    });

    let email_url = `${req.protocol}://${req.get('host')}/user/a/b/${id}/${random}`;