Send Email with Gmail API via Service Account in Node.js

In this tutorial, I covered how to send email with Gmail API using Service Account in Node.js.

Sending emails programmatically is a common requirement for web applications. The Gmail API provides a powerful way to send emails through your Gmail account using a service account. In this tutorial, I’ll show you how to use the Gmail API to send email with Service account in Node.js, leveraging the popular Nodemailer library to prepare MIME messages.

Table of Contents

Introduction

 

 

Send Email with Gmail API via Service Account in Node.js

Prerequisites

Before we begin, make sure you have the following:

  • Node.js installed on your system.
  • A Gmail account with access to the Google Developers Console.
  • Basic understanding of JavaScript and Node.js.

Setting Up a Service Account

First, you need to create a service account in the Google Developers Console:

  1. Go to the Google Developers Console and create a new project.
  2. Enable the Gmail API for your project.
  3. Go to ‘Credentials’ and create a new service account.
  4. Download the JSON key file for your service account and keep it secure; you’ll need it in your Node.js application.

Configuring Nodemailer

Nodemailer is a Node.js library for sending emails. It supports many mail transport systems, but here we’ll use it to generate MIME messages that can be sent via the Gmail API.

First, install Nodemailer using npm:

  npm install nodemailer

We’ll configure Nodemailer to create a stream transport that we can use to generate raw MIME messages:

  const nodemailer = require('nodemailer');
  const mailTransport = nodemailer.createTransport({
    streamTransport: true,
    newline: "unix",
    buffer: true
  });

Sending Email

To send an email using the Gmail API, you must first create a raw MIME message. You can use Nodemailer to do this, then send it using the Gmail API’s users.messages.send method.

Here’s a basic example of using Nodemailer to create a MIME message:

  const message = {
    to: '[email protected]',
    subject: 'Hello!',
    text: 'Hello world!',
    html: '<p><b>Hello</b> world!</p>'
  };
  
  mailTransport.sendMail(message, (err, info) => {
    if (err) {
      console.error('Error generating email MIME', err);
    } else {
      // Send the MIME message via Gmail API
      sendMimeMessage(info.message.toString('base64'));
    }
  });

Now, you need to implement the sendMimeMessage function to send the MIME message using the Gmail API and your service account.

Here’s an example of how you would use the Gmail API with a service account to send an email:

  const { google } = require('googleapis');
  
  async function sendMimeMessage(mimeMessage) {
    const gmail = google.gmail('v1');
  
    const auth = new google.auth.JWT(
      credentials.client_email, // From your JSON key file
      null,
      credentials.private_key, // From your JSON key file
      ['https://www.googleapis.com/auth/gmail.send']
    );
  
    await auth.authorize();
  
    const response = await gmail.users.messages.send({
      auth: auth,
      userId: 'me',
      resource: {
        raw: mimeMessage
      }
    });
  
    console.log(response);
  }

Output: Your console will display the response from the Gmail API which contains the ID of the sent message and other details.

Complete Example

Here is a complete example that includes the creation of the MIME message and sending it using the Gmail API. Remember to populate the credentials object with your service account details from the JSON key file.

const { google } = require('googleapis');
const nodemailer = require('nodemailer');

  // Credentials obtained from your service account JSON key file
  const credentials = {
    client_email: 'YOUR_SERVICE_ACCOUNT_EMAIL',
    private_key: 'YOUR_SERVICE_ACCOUNT_PRIVATE_KEY'
  };

  // Configure Nodemailer to generate an SMTP configuration
  const mailTransport = nodemailer.createTransport({
    streamTransport: true,
    newline: 'unix',
    buffer: true
  });

  // Email contents
  const mailOptions = {
    from: '[email protected]',
    to: '[email protected]',
    subject: 'Test Email via Gmail API',
    text: 'Hello! This is a test email sent via Gmail API with a service account.',
    html: '<p> Hello. This is using <strong>Gmail API</strong></p>'
  };

  // Function to send the email using Gmail API
  async function sendMimeMessage(mimeMessage) {
    const gmail = google.gmail({ version: 'v1' });
    const jwtClient = new google.auth.JWT(
      credentials.client_email,
      null,
      credentials.private_key,
      ['https://www.googleapis.com/auth/gmail.send'],
      // Specify the email address of the user the service account is impersonating.
      // Ensure the service account has domain-wide authority to impersonate this user.
      '[email protected]'
    );

    // Authorize the JWT client and get a token to make API calls
    await jwtClient.authorize();

    // Send the email using the Gmail API
    const response = await gmail.users.messages.send({
      auth: jwtClient,
      userId: 'me',
      resource: { raw: mimeMessage }
    });

    console.log('Email sent:', response.data);
  }

  // Generate MIME message and send email
  mailTransport.sendMail(mailOptions, (err, info) => {
    if (err) {
      return console.error('Failed to send mail:', err);
    }

    const mimeMessage = info.message.toString('base64');
    sendMimeMessage(mimeMessage)
      .then(() => console.log('Email sent successfully.'))
      .catch(error => console.error('Error sending email:', error));
  });

 

Summary

In this tutorial, we’ve explored how to send email with the Gmail API using a service account in Node.js. We configured Nodemailer to create the necessary MIME message and used the Gmail API’s users.messages.send method to send the email. This allows for secure and efficient email delivery directly from your Node.js application.

References