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!
Prerequisites
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>
<html>
<head>
<title>Gmail API Quickstart - Send Email</title>
<meta charset="utf-8" />
</head>
<body>
<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>
<script async defer src="https://apis.google.com/js/api.js" onload="gapiLoaded()"></script>
<script async defer src="https://accounts.google.com/gsi/client" onload="gisLoaded()"></script>
</body>
</html>
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="https://apis.google.com/js/api.js" onload="gapiLoaded()"></script>
<script async defer src="https://accounts.google.com/gsi/client" 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
const CLIENT_ID = 'REDACTED';
const API_KEY = 'REDACTED';
const TO_EMAIL = "REDACTED"
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;
maybeEnableButtons();
}
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;
maybeEnableButtons();
}
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) {
google.accounts.oauth2.revoke(token.access_token);
gapi.client.setToken('');
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: test@test.com\r\n" +
"To: test@test.com\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 gapi.client.gmail.users.messages.send({
userId: 'me',
resource: {
raw: encodedMessage
}
});
} catch (err) {
document.getElementById('content').innerText = err.message;
return;
}
const messageId = response.id;
if (!messageId) {
document.getElementById('content').innerText = 'Message not sent.';
return;
}
document.getElementById('content').innerText = 'Message sent: ' + messageId + "\n";
}
Conclusion
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.