gmail.users.labels.list()
functionality.When using Google's Node.js API I get a error trying to send a email. The error is:
{ "code": 403, "errors": [{ "domain": "global", "reason": "insufficientPermissions", "message": "Insufficient Permission" }] }
fs.readFile(secretlocation, function processClientSecrets(err, content) { if (err) { console.log('Error loading client secret file: ' + err); return; } authorize(JSON.parse(content), sendMessage); }); function sendMessage(auth) { var raw = makeBody('[email protected]', '[email protected]', 'subject', 'message test'); gmail.users.messages.send({ auth: auth, userId: 'me', message: { raw: raw } }, function(err, response) { res.send(err || response) }); }
The function processClientSecrets
is from the Google guide i mentioned above. It reads my .json
file that has my access_token
and refresh_token
. The makeBody
function is a to make a encoded body message.
In the config variabels I have also:
var SCOPES = [ 'https://mail.google.com/', 'https://www.googleapis.com/auth/gmail.modify', 'https://www.googleapis.com/auth/gmail.compose', 'https://www.googleapis.com/auth/gmail.send' ];
gmail.users.labels.list()
method.Is my setup wrong? Have there been changes in the API? What am I missing?
Ok, so I found the problem(s).
Problem #1 While following the Node.js quickstart guide the example in that tutorial has
var SCOPES = ['https://www.googleapis.com/auth/gmail.readonly'];
And when I got the .json
that looks like:
{ "access_token": "xxx_a_long_secret_string_i_hided_xxx", "token_type": "Bearer", "refresh_token": "xxx_a_token_i_hided_xxx", "expiry_date": 1451721044161 }
those tokens where produced taking into account only the auth/gmail.readonly
scope in the tutorial code.
So I deleted the first .json
, added the scopes from my final scope array (i posted in the question) and ran the tutorial setup again, receiving a new token.
Problem #2
In the object passed to the API I was sending:
{ auth: auth, userId: 'me', message: { raw: raw } }
but that is wrong, message
key should be called resource
.
This is what I added to the tutorial's code:
function makeBody(to, from, subject, message) { var str = ["Content-Type: text/plain; charset=\"UTF-8\"\n", "MIME-Version: 1.0\n", "Content-Transfer-Encoding: 7bit\n", "to: ", to, "\n", "from: ", from, "\n", "subject: ", subject, "\n\n", message ].join(''); var encodedMail = new Buffer(str).toString("base64").replace(/\+/g, '-').replace(/\//g, '_'); return encodedMail; } function sendMessage(auth) { var raw = makeBody('[email protected]', '[email protected]', 'test subject', 'test message'); gmail.users.messages.send({ auth: auth, userId: 'me', resource: { raw: raw } }, function(err, response) { res.send(err || response) }); }
And call everything with:
fs.readFile(secretlocation, function processClientSecrets(err, content) { if (err) { console.log('Error loading client secret file: ' + err); return; } // Authorize a client with the loaded credentials, then call the // Gmail API. authorize(JSON.parse(content), sendMessage); });
So for anyone looking at this trying to get a test email sent from their API but cant get this work heres what you gotta do:
Step 1: Replace the
var SCOPES = ['https://www.googleapis.com/auth/gmail.readonly'];
with this:
var SCOPES = [ 'https://mail.google.com/', 'https://www.googleapis.com/auth/gmail.modify', 'https://www.googleapis.com/auth/gmail.compose', 'https://www.googleapis.com/auth/gmail.send' ];
Step 2: At the end of googles sample code add this:
function makeBody(to, from, subject, message) { var str = ["Content-Type: text/plain; charset=\"UTF-8\"\n", "MIME-Version: 1.0\n", "Content-Transfer-Encoding: 7bit\n", "to: ", to, "\n", "from: ", from, "\n", "subject: ", subject, "\n\n", message ].join(''); var encodedMail = new Buffer(str).toString("base64").replace(/\+/g, '-').replace(/\//g, '_'); return encodedMail; } function sendMessage(auth) { var raw = makeBody('[email protected]', '[email protected]', 'This is your subject', 'I got this working finally!!!'); const gmail = google.gmail({version: 'v1', auth}); gmail.users.messages.send({ auth: auth, userId: 'me', resource: { raw: raw } }, function(err, response) { return(err || response) }); } fs.readFile('credentials.json', function processClientSecrets(err, content) { if (err) { console.log('Error loading client secret file: ' + err); return; } // Authorize a client with the loaded credentials, then call the // Gmail API. authorize(JSON.parse(content), sendMessage); });
Step 3(Optional)
Delete this line:
authorize(JSON.parse(content), listLabels);
And these:
/** * 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.'); } }); }
(So you don't get the random labels in your console)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With