Gmail API JavaScript – Send Email Tutorial for Beginners

Sending emails programmatically can be a powerful tool, especially for developers automating routine tasks. In this beginner-friendly tutorial, we’ll walk through the process of sending an email using the Gmail API using JavaScript. Let’s get started!


Before we dive into the tutorial, make sure you have the following:

  • Basic knowledge of HTML and JavaScript.
  • A Google Cloud Platform (GCP) account.
  • Create a new project in the Google Cloud Console.
  • Enable the Gmail API for your project.
  • Generate API credentials (Client ID and API Key) from the Developer Console.

HTML Structure

Let’s start by examining the basic HTML structure of our project. We have two buttons – one for authorization and another for signing out. These buttons will play a crucial role in interacting with the Gmail API.

<!DOCTYPE html>
<title>Gmail API Quickstart - Send Email</title>
<meta charset="utf-8" />
<p>Gmail API Quickstart</p>

<!--Add buttons to initiate auth sequence and sign out-->
<button id="authorize_button" onclick="handleAuthClick()">Authorize</button>
<button id="signout_button" onclick="handleSignoutClick()">Sign Out</button>

<pre id="content" style="white-space: pre-wrap;"></pre>

<script type="text/javascript">

/* Our code below will go here */

<script async defer src="" onload="gapiLoaded()"></script>
<script async defer src="" onload="gisLoaded()"></script>

Loading the Gmail API and Google Identity Services

We include two script tags to load the Gmail API and Google Identity Services asynchronously. This ensures that our page doesn’t freeze while waiting for these resources.

<script async defer src="" onload="gapiLoaded()"></script>
<script async defer src="" onload="gisLoaded()"></script>

Client Configuration

At the beginning of our script, we have some configuration variables. These include your CLIENT_ID, API_KEY, and email addresses for the sender and recipient.

// TODO(developer): Set to client ID and API key from the Developer Console

Initializing the Google API Client

We initialize the Google API client using the gapiLoaded and initializeGapiClient functions. The API key and discovery document are crucial for this step.

* Callback after api.js is loaded.
function gapiLoaded() {
    gapi.load('client', initializeGapiClient);

* Callback after the API client is loaded. Loads the
* discovery doc to initialize the API.
async function initializeGapiClient() {
    await gapi.client.init({
        apiKey: API_KEY,
        discoveryDocs: [DISCOVERY_DOC],
    gapiInited = true;

Initializing Google Identity Services

The gisLoaded function initializes the token client for Google Identity Services.

* Callback after Google Identity Services are loaded.
function gisLoaded() {
    tokenClient = google.accounts.oauth2.initTokenClient({
        client_id: CLIENT_ID,
        scope: SCOPES,
        callback: '', // defined later
    gisInited = true;

Enabling Buttons

The maybeEnableButtons function ensures that the authorization button is visible only when both libraries are loaded.

* Enables user interaction after all libraries are loaded.
function maybeEnableButtons() {
    if (gapiInited && gisInited) {
    document.getElementById('authorize_button').style.visibility = 'visible';

Handling Authorization

The handleAuthClick function initiates the authorization process, prompting the user to select a Google Account and granting consent to share data.

*  Sign in the user upon button click.
function handleAuthClick() {
    tokenClient.callback = async (resp) => {
        if (resp.error !== undefined) {
            throw (resp);
        document.getElementById('signout_button').style.visibility = 'visible';
        document.getElementById('authorize_button').innerText = 'Refresh';
        await send_email();

    if (gapi.client.getToken() === null) {
    // Prompt the user to select a Google Account and ask for consent to share their data
    // when establishing a new session.
    tokenClient.requestAccessToken({prompt: 'consent'});
} else {
    // Skip display of account chooser and consent dialog for an existing session.
    tokenClient.requestAccessToken({prompt: ''});

Handling Sign Out

The handleSignoutClick function allows users to sign out, revoking access and clearing the content area.

*  Sign out the user upon button click.
function handleSignoutClick() {
    const token = gapi.client.getToken();
    if (token !== null) {
    document.getElementById('content').innerText = '';
    document.getElementById('authorize_button').innerText = 'Authorize';
    document.getElementById('signout_button').style.visibility = 'hidden';

Sending an Email

Finally, the send_email function constructs a basic email and sends it using the Gmail API. Note the base64url encoding of the email message.

* Sends an email
async function send_email() {
    let response;
    // Note the from email must be the email address of the user who has authorized this code.
    const message =
        "From:\r\n" +
        "To:\r\n" +
        "Subject: As basic as it gets\r\n\r\n" +
        "This is the plain text body of the message.  Note the blank line between the header information and the body of the message.";

    // The body needs to be base64url encoded.
    const encodedMessage = btoa(message)
    const reallyEncodedMessage = encodedMessage.replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '')

    try {
        const response = await{
            userId: 'me',
            resource: {
                raw: encodedMessage
    } catch (err) {
        document.getElementById('content').innerText = err.message;
        const messageId =;
        if (!messageId) {
        document.getElementById('content').innerText = 'Message not sent.';
        document.getElementById('content').innerText = 'Message sent: ' + messageId + "\n";


Congratulations! You’ve successfully set up a basic web page to send emails using the Gmail API. This is just the beginning – there’s a lot more you can explore and customize based on your needs. Feel free to check out the Gmail API documentation for more advanced features and functionalities.

Final word

Remember this is client side JavaScript so the user will need to login in each time they run the app, there is no way to store the existing authorization. Also remember that the from email must be the email of the user who logged in so i would use getProfile to find that users email.

Additional Resources

About Linda Lawton

My name is Linda Lawton I have more than 20 years experience working as an application developer and a database expert. I have also been working with Google APIs since 2012 and I have been contributing to the Google .Net client library since 2013. In 2013 I became a a Google Developer Experts for Google Analytics.

Leave a comment

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.