I think the answer is that using a gcloud service account with GmailAPI requires domain wide delegation, but I haven't been able to find a definitive answer.
Basic code setup within node, called from my express server.
const { google } = require('googleapis');
const gmail = google.gmail('v1');
const GMAIL_SCOPE_SEND = 'https://www.googleapis.com/auth/gmail.send';
const setAuth = async (scopes) => {
const auth = new google.auth.GoogleAuth({
// Uses default credientials from the env variable GOOGLE_APPLICATION_CREDENTIALS
// Scopes can be specified either as an array or as a single, space-delimited string.
scopes: scopes,
});
const authClient = await auth.getClient();
google.options({ auth: authClient });
return authClient;
};
const sendEmail = async (address, code) => {
console.log('sendEmail', address, code);
const subject = "Hello";
const utf8Subject = `=?utf-8?B?${Buffer.from(subject).toString('base64')}?=`;
const messageParts = [
'From: ${SERVICE_ACCOUNT_EMAIL}',
`To: ${address}`,
'Content-Type: text/html; charset=utf-8',
'MIME-Version: 1.0',
`Subject: ${utf8Subject}`,
'',
'Test',
];
const message = messageParts.join('\n');
// The body needs to be base64url encoded.
const encodedMessage = Buffer.from(message)
.toString('base64')
.replace(/\+/g, '-')
.replace(/\//g, '_')
.replace(/=+$/, '');
const res = await gmail.users.messages.send({
userId: 'me',
requestBody: {
raw: encodedMessage,
},
});
console.log(res.data);
return res.data;
};
const init = () => {
setAuth([GMAIL_SCOPE_SEND]);
};
init();
module.exports = { sendEmail };
This results in the error:
code: 400,
errors: [
{
message: 'Precondition check failed.',
domain: 'global',
reason: 'failedPrecondition'
}
]
Is there a way to make this work? What does this error mean?