images
14th May, 2019

How to access Gmail using NodeJS and the Gmail API

Prerequisites:

A Google account with Gmail enabled

Step 1: Turn on the Gmail API

First, need to enable Gmail API and get the required OAuth credentials from Google account.

1.    Use this wizard to create or select a project in the Google Developers Console and automatically turn on the API. Click Continue, then Go to credentials.

2.    On the Add credentials to your project page, click the Cancel button.

3.    At the top of the page, select the OAuth consent screen tab. Select an Email address, enter a Product name if not already set, and click the Save button.

4.    Select the Credentials tab, click the Create credentials button and select OAuth client ID.

5.    Select the application type Other, enter the name “Gmail API Quickstart”, and click the Create button.

6.    Click OK to dismiss the resulting dialog.

7.    Click the Download JSON button to the right of the client ID.

8.    Save the file credentials.json to your working directory.

 

Step 2: Install the client library

npm install googleapis@27 –save

 

Step 3: Set up the sample

Create a file named index.js in your working directory and copy in the following code:

const fs = require('fs');
const readline = require('readline');
const {google} = require('googleapis');
// If modifying these scopes, delete token.json.
const SCOPES = ['https://www.googleapis.com/auth/gmail.readonly'];
// The file token.json stores the user's access and refresh tokens, and is // created automatically when the authorization flow completes for the first // time.
const TOKEN_PATH = 'token.json';
// Load client secrets from a local file.
fs.readFile(
'credentials.json', (err, content) => {
 
if (err) return console.log('Error loading client secret file:', err);
 
// Authorize a client with credentials, then call the Gmail API.
  authorize(JSON.parse(content), listLabels);
});
/**  * Create an OAuth2 client with the given credentials, and then execute the  * given callback function.  * @param {Object} credentials The authorization client credentials.  * @param {function} callback The callback to call with the authorized client.  */
function authorize(credentials, callback) {
 
const {client_secret, client_id, redirect_uris} = credentials.installed;
 
const oAuth2Client = new google.auth.OAuth2(
      client_id, client_secret, redirect_uris[
0]);
 
// Check if we have previously stored a token.
  fs.readFile(TOKEN_PATH, (err, token) => {
   
if (err) return getNewToken(oAuth2Client, callback);
    oAuth2Client.setCredentials(JSON.parse(token));
    callback(oAuth2Client);
  });
}
/**  * Get and store new token after prompting for user authorization, and then  * execute the given callback with the authorized OAuth2 client.  * @param {google.auth.OAuth2} oAuth2Client The OAuth2 client to get token for.  * @param {getEventsCallback} callback The callback for the authorized client.  */
function getNewToken(oAuth2Client, callback) {
 
const authUrl = oAuth2Client.generateAuthUrl({
    access_type:
'offline',
    scope: SCOPES,
  });
  console.log(
'Authorize this app by visiting this url:', authUrl);
 
const rl = readline.createInterface({
    input: process.stdin,
    output: process.stdout,
  });
  rl.question(
'Enter the code from that page here: ', (code) => {
    rl.close();
    oAuth2Client.getToken(code, (err, token) => {
     
if (err) return console.error('Error retrieving access token', err);
      oAuth2Client.setCredentials(token);
     
// Store the token to disk for later program executions
      fs.writeFile(TOKEN_PATH, JSON.stringify(token), (err) => {
       
if (err) return console.error(err);
        console.log(
'Token stored to', TOKEN_PATH);
      });
      callback(oAuth2Client);
    });
  });
}
/**  * Lists the labels in the user's account.  * @param {google.auth.OAuth2} auth An authorized OAuth2 client.  */
function listLabels(auth) {
 
const gmail = google.gmail({version: 'v1', auth});
  gmail.users.labels.list({
    userId:
'me',
  }, (err, res) => {
   
if (err) return console.log('The API returned an error: ' + err);
   
const labels = res.data.labels;
   
if (labels.length) {
      console.log(
'Labels:');
      labels.forEach((label) => {
        console.log(`- ${label.name}`);
      });
    }
else {
      console.log(
'No labels found.');
    }
  });
}

 

Step 4: Run the sample

Run the sample using the following command:

node .

Once the above code is executed from the command line it will return a OAuth url which you need to copy to your browser for authentication. (Before pasting the url into the browser make sure that it is well formed and does not contain any line breaks. To make sure of that copy the url into a text editor first.) The url will then authenticate and return a OAuth credential token string which you will need to then paste at the given prompt. Once this is correctly done, the code will store the access token into a file called ‘token.json’. The next time you execute the above code Google will use this file and the access token therein to login and authenticate.

If you have done everything correctly, you will see a list of category labels for your account.

CATEGORY_PERSONAL

CATEGORY_SOCIAL

Notes

CATEGORY_FORUMS

Receipts

Work

IMPORTANT

CATEGORY_UPDATES

CHAT

SENT

INBOX

TRASH

CATEGORY_PROMOTIONS

DRAFT

SPAM

STARRED

UNREAD

 

Now that we have a proper working Gmail API setting, we will next see how to access your emails. All the authentication code remains the same, we just keep adding various Gmail methods as required for our purpose. In this post, I will only show the function to retrieve and read emails.

/**
 * Get the recent email from your Gmail account
 * @param {google.auth.OAuth2} auth An authorized OAuth2 client.
 */
function getRecentEmail(auth) {
    // Only get the recent email - 'maxResults' parameter
    gmail.users.messages.list({auth: auth, userId: 'me', maxResults: 1,}, function(err, response) {
        if (err) {
            console.log('The API returned an error: ' + err);
            return;
        }
      // Get the message id which we will need to retreive tha actual message next.
      var message_id = response['data']['messages'][0]['id'];
      // Retreive the actual message using the message id
      gmail.users.messages.get({auth: auth, userId: 'me', 'id': message_id}, function(err, response) {
          if (err) {
              console.log('The API returned an error: ' + err);
              return;
          }
         console.log(response['data']);
      });
    });
}

 

Call the function from the main code from where before we called the ‘listLabels’ function.

// Authorize a client with the loaded credentials, then call the
// Gmail API.
authorize(JSON.parse(content), getRecentEmail);

 

This will return something like the following, depending on your email type. You will then need to parse the following user message resource to get to the data.

 

{ id: '162bca5abe3acbf5',
  threadId: '162bca5315t5yc28',
  labelIds: [ 'IMPORTANT', 'SENT', 'INBOX' ],
  snippet: '',
  historyId: '5076456',
  internalDate: '1523876396000',
  payload:
   { partId: '',
     mimeType: 'multipart/mixed',
     filename: '',
     headers:
      [ [Object],
        [Object],
        [Object],
        [Object],
        [Object],
        [Object],
        [Object] ],
     body: { size: 0 },
     parts: [ [Object], [Object] ] },
  sizeEstimate: 4841772 }

 

The main part we are interested in is the payload section. This contains the primary message along with attachments. We can access that part using the following. Note that the email body content is encoded in base64 so we will need to decode it to display the email content.

// Access the email body content, like this...
message_raw = response['data']['payload']['parts'][0].body.data;
// or like this
message_raw = response.data.payload.parts[0].body.data;

 Then we will need to decode the base64 encoded message.

data = message_raw;  
buff = new Buffer(data, 'base64');  
text = buff.toString();
console.log(text);

 This will then give us the actual human-readable text message. Using the other API methods follows the same calling pattern with different parameters. The authentication code remains the same.

For further details visit :

- Google APIs Client for Node.js documentation

https://github.com/googleapis/google-api-nodejs-client#google-apis-nodejs-client

 

Gmail API reference documentation

https://developers.google.com/gmail/api/v1/reference/