Skip to content

Instantly share code, notes, and snippets.

@cmundi
Last active August 10, 2019 20:13
Show Gist options
  • Save cmundi/6c7d3578ff36d13cff84438b8c39bffc to your computer and use it in GitHub Desktop.
Save cmundi/6c7d3578ff36d13cff84438b8c39bffc to your computer and use it in GitHub Desktop.
Google API Service Account Demo for Gmail and Drive
//
// Using Google Drive and Google Mail with a Service Account.
//
// Amswer to http://stackoverflow.com/questions/37902022/gmail-api-with-nodejs-send-gives-400-bad-request?answertab=active#tab-top
//
// A service account is pretty much like a normal Google account, except that yo can't get get a "shell" like
// the Gmail webapp or Drive webapp into it. To manage email with a Service Account, the administrator for the
// domain which owns the email addresses must enable API access for the Service Account. That's described in my
// SO post and the links therein. Assuming you've set all that up, it's time to have some fun!
//
// This gist was significantly inspired by examples distributed by Google under the Apache License 2 and is returned to
// the community also under the Apache License 2.
var fs = require('fs');
var base64 = require('base64-url'); // for encoding our email
// service account key - keep it safe
var key = require('./serviceaccount_key.json');
// google apis
var google = require('googleapis');
var drive = google.drive('v3');
var mail = google.gmail('v1');
// new up a client - include whatever scopes you need
var jwtClient = new google.auth.JWT(
key.client_email,
null,
key.private_key,
['https://www.googleapis.com/auth/drive', // drive scope
'https://www.googleapis.com/auth/gmail.readonly', // for labels
'https://www.googleapis.com/auth/gmail.send'], // mail scope
"maria@our_google_apps_domain.com"); // the user which wil be impersonated by our service account
// grab some tokens; we won't have to get our hands dirty because its's all nicely encapsulated in the jwtClient
jwtClient.authorize(function(err, tokens) {
if (err) {
console.log('JWT Auth Error: ' + err);
return;
}
// Let's have a look just for funsies!
console.log('Got tokens:' + JSON.stringify(tokens));
// Find out what our friend Maria has in her Google Drive
listFiles();
// Leave a present for her!
console.log('pushing file...');
var request = putFile('test.png'); // not much of a present...
console.log(JSON.stringify(request)); // hey check out that HTTPS request!
// What labels is Maria using in Gmail?
request = mail.users.labels.list({auth: jwtClient, userId: 'me'},
(err,res) => {
if (err) console.log('Labels Error:\n' + JSON.stringify(err));
if (res) console.log('Labels:\n' + JSON.stringify(res));
}
);
// now we're going to send an email from Maria to Manny.
var msg = [
'Content-Type: text/plain; charset=utf-8\n',
'MIME-Version: 1.0\n',
'Content-Transfer-Encoding: 7bit\n',
'To: manny@example.com\n', // who's this Danny guy, and why is Maria sending him email?
'From: maria@our_google_apps_domain.com\n', // better match the impersonated account
'Subject: Happy Hour\n\n',
'See you at happy hour!'
].join('');
console.log(msg);
safe = base64.escape(base64.encode(msg));
console.log(safe);
request = mail.users.messages.send(
{
auth: jwtClient,
userId: 'me', // this refers to the service avvount
resource:
{
raw: safe
}
},
(err,resp)=>{
console.log('error:\n' + JSON.stringify(err));
console.log('response:\n' + JSON.stringify(resp));
}
);
console.log(JSON.stringify(request));
});
// Make an authorized request to list Drive files.
function listFiles() {
drive.files.list({ auth: jwtClient, pageSize: 10, fields: "nextPageToken, files(id, name)" },
function(err, resp) {
// handle err and response
if (err) {
console.log('FAIL: ', err);
} else {
var files = resp.files;
if (files.length == 0)
console.log('no files found');
else {
console.log('Files:');
for (var i=0; i<files.length;i++) {
var file = files[i];
console.log('%s (%s)', file.name, file.id);
}
}
}
});
};
function putFile(filename) {
var req = drive.files.create({
auth: jwtClient,
resource: {
name: 'testimage.png',
mimeType: 'image/png'
},
media: {
mimeType: 'image/png',
body: fs.createReadStream(filename)
}
}, ()=> {
console.log('drive.files.create callback here!');
listFiles();
} );
return req;
};
@cmundi
Copy link
Author

cmundi commented Jun 19, 2016

This answers how to get a Service Account to work with Gmail plus some fun with Google Drive.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment