Build an Auto-Responder Bot Using JavaScript and Gmail API

Build an Auto-Responder Bot Using JavaScript and Gmail API

Build an Auto-Responder Bot Using JavaScript and Gmail API

 

Automating your inbox can save countless hours, particularly if you’re drowning in support tickets, freelance inquiries, or client follow-ups. In this guide, we’ll show you how to build a Gmail auto-responder bot using JavaScript and the Gmail API. We’ll cover both Google Apps Script for lightweight automation and Node.js for more control and customization.

1. Understanding the Gmail API and Authentication

The Gmail API lets you programmatically read, send, and manage emails. Before doing anything, you’ll need to enable the Gmail API and set up authentication.

Using Google Apps Script (No OAuth setup required):

function autoResponder() {
  var threads = GmailApp.search('is:unread -from:me');

  for (var i = 0; i < threads.length; i++) {
    var messages = threads[i].getMessages();
    var lastMessage = messages[messages.length - 1];

    if (!lastMessage.isReplied()) {
      threads[i].reply("Thank you for your email. I’ll get back to you shortly.");
    }
  }
}

This script searches for unread messages not sent by you and replies if they haven’t been responded to. You can schedule it using a time-based trigger in the Apps Script UI.

Node.js Setup (Requires OAuth2):

First, install the required packages:

npm install googleapis @google-cloud/local-auth

Then, initialize your project and load the Gmail API:

const { google } = require('googleapis');
const path = require('path');
const fs = require('fs');

async function createGmailClient() {
  const auth = new google.auth.GoogleAuth({
    keyFile: 'credentials.json',
    scopes: ['https://www.googleapis.com/auth/gmail.modify'],
  });

  const gmail = google.gmail({ version: 'v1', auth });
  return gmail;
}

2. Fetching Unread Emails

Once authenticated, we need to fetch unread emails, skipping those we’ve already responded to.

async function getUnreadEmails(gmail) {
  const res = await gmail.users.messages.list({
    userId: 'me',
    labelIds: ['INBOX', 'UNREAD'],
    q: '-from:me',
  });

  return res.data.messages || [];
}

This function only returns IDs. You need to fetch full message details using gmail.users.messages.get() before you can read the snippet, headers, or body.

3. Sending Automated Replies

To respond to emails, craft a reply message and send it using gmail.users.messages.send.

async function sendAutoReply(gmail, message) {
  const threadId = message.threadId;

  const raw = Buffer.from(
    `To: ${getHeader(message.payload.headers, 'From')}
` +
    `Subject: Re: ${getHeader(message.payload.headers, 'Subject')}
` +
    `In-Reply-To: ${getHeader(message.payload.headers, 'Message-ID')}

` +
    `Thank you for reaching out. I’ll reply to your message soon.`
  ).toString('base64').replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '');

  await gmail.users.messages.send({
    userId: 'me',
    requestBody: {
      raw: raw,
      threadId: threadId,
    },
  });
}

Note: Email content must be base64url encoded. Also, ensure you include proper headers like In-Reply-To and Subject to keep conversation threads organized.

4. Putting It All Together with Node.js

Now let's tie it together with a function that loops through unread emails and responds accordingly.

async function autoRespond() {
  const gmail = await createGmailClient();
  const unreadMessages = await getUnreadEmails(gmail);

  for (const msg of unreadMessages) {
    const fullMessage = await gmail.users.messages.get({ userId: 'me', id: msg.id });

    if (!isAlreadyReplied(fullMessage.data)) {
      await sendAutoReply(gmail, fullMessage.data);

      // Mark as read
      await gmail.users.messages.modify({
        userId: 'me',
        id: msg.id,
        requestBody: { removeLabelIds: ['UNREAD'] },
      });
    }
  }
}
function getHeader(headers, name) {
  return headers.find(h => h.name.toLowerCase() === name.toLowerCase())?.value || '';
}

function isAlreadyReplied(message) {
  return message.payload.headers.some(h => h.name === 'In-Reply-To');
}

Use cron jobs or services like PM2 or GitHub Actions to schedule this script periodically to keep your inbox current.

5. Customization and Tips

Dynamic Filters:

Create smarter bots that only reply to specific labels, senders, or time ranges using advanced search queries:

labelIds: ['INBOX'],
q: 'is:unread older_than:1d subject:(Invoice OR Payment)',

Throttle Replies:

To avoid API limits or loops, maintain a log (in memory, spreadsheet, or DB) of message IDs you’ve already replied to.

Performance:

Use batch endpoints where possible (e.g., batchModify) and avoid unnecessary API calls by storing state.

Format HTML Emails:

`Content-Type: text/html; charset="UTF-8"\n\n<p>This is a formatted response</p>`

Conclusion

In this tutorial, you learned how to build an auto-responder with both Google Apps Script and Node.js using the Gmail API. While Apps Script is fast and serverless, Node.js gives you more flexibility and scalability. Adding filters, tracking replies intelligently, and formatting the message body can help build production-ready email bots. This solution is ideal for customer service, freelancers, and teams wanting to automate their inbox workflows.

 

Useful links: