node.jsgmail-apigoogle-workspaceservice-accountsgoogle-api-nodejs-client

Can't send an email from service account, get 400 Precondition check failed error


Trying to send an email using a service account with role owner within my project. I keep getting a 400 error that says Precondition check failed.

const sendEmail = async () => {

const auth = new google.auth.GoogleAuth({
    keyFile: "gmail.json", //the key file
    scopes: "https://www.googleapis.com/auth/gmail.send",
});

const authClientObject = await auth.getClient();
const gmail = google.gmail({version:"v1", auth: authClientObject})
  // Compose the email
  const email = 'To: someone@jybe.ca\r\n' +
                `Cc: someoneelse@jybe.ca\r\n` +
                'Subject: CUSTOM DONATION ALERT\r\n\r\n' +
                'blablabla\r\n';
  
  // Encode the email in base64 format
  const base64EncodedEmail = Buffer.from(email).toString('base64');
  
  // Send the email
  gmail.users.messages.send({
    userId: serviceAccountEmail,
    resource: {
      raw: base64EncodedEmail,
    },
  }, (err, res) => {
    if (err) {
      console.error('Error sending email:', err);
      return;
    }
  
    console.log('Email sent:', res.data);
  });

}


Solution

  • Precondition check failed.

    Normally occurs when you are using a service account and have not properly configured domain wide delegation within your google workspace account.

    I can also see you have not denoted which user in your workspace account the service account should delignate as.

    const {google} = require('googleapis');
    const path = require('path');
    
    async function runSample(impersonate) {
        // acquire an authentication client using a service account
        const auth = await google.auth.getClient({
            keyFile: path.join('C:\\Development\\FreeLance\\GoogleSamples\\Credentials\\workspaceserviceaccount.json'),
            scopes: ['https://www.googleapis.com/auth/gmail.readonly' ],
            clientOptions: { subject: impersonate },
        });
    
        // obtain the gmail client
        const gmail = google.gmail({version: 'v1', auth});
    
    
         // Lists the messages in the user's account.
    
        console.log(auth)
        const res = await gmail.users.messages.list({
            userId: 'me',
        });
        const messages = res.data.messages;
        if (!messages || messages.length === 0) {
            console.log('No messages found.');
            return;
        }
        console.log('messages:');
        messages.forEach((message) => {
            console.log(`- ${message.id} - ${message.subject}`);
        });
    }
    
    runSample('user@yourdomain.com').catch(console.error);