Getting 'unauthorized_client' error with Nodemailer and Google OAuth2 in Node.js when deployed as a netlify function

85 Views Asked by At

I have created a contact.js netlify function to handle mails which have to be sent to my gmail account. I am using nodemailer alongwith google api (oauth2.0) to send these mails, but netlify logs the following error :

ERROR MESSAGE

ERROR  Unhandled Promise Rejection  {"errorType":"Runtime.UnhandledPromiseRejection","errorMessage":"Error: unauthorized_client","reason":{"errorType":"Error","errorMessage":"unauthorized_client","config":{"method":"POST","url":"https://oauth2.googleapis.com/token","data":"<<REDACTED> - See `errorRedactor` option in `gaxios` for configuration>.","headers":{"Content-Type":"application/x-www-form-urlencoded","User-Agent":"google-api-nodejs-client/9.4.1","x-goog-api-client":"gl-node/18.18.0"},"body":"<<REDACTED> - See `errorRedactor` option in `gaxios` for configuration>.","responseType":"unknown"},"response":{"config":{"method":"POST","url":"https://oauth2.googleapis.com/token","data":"<<REDACTED> - See `errorRedactor` option in `gaxios` for configuration>.","headers":{"Content-Type":"application/x-www-form-urlencoded","User-Agent":"google-api-nodejs-client/9.4.1","x-goog-api-client":"gl-node/18.18.0"},"body":"<<REDACTED> - See `errorRedactor` option in `gaxios` for configuration>.","responseType":"unknown"},"data":{"error":"unauthorized_client","error_description":"Unauthorized"},"headers":{"alt-svc":"h3=\":443\"; ma=2592000,h3-29=\":443\"; ma=2592000","cache-control":"no-cache, no-store, max-age=0, must-revalidate","connection":"close","content-encoding":"gzip","content-type":"application/json; charset=utf-8","date":"Wed, 20 Dec 2023 09:14:55 GMT","expires":"Mon, 01 Jan 1990 00:00:00 GMT","pragma":"no-cache","server":"scaffolding on HTTPServer2","transfer-encoding":"chunked","vary":"Origin, X-Origin, Referer","x-content-type-options":"nosniff","x-frame-options":"SAMEORIGIN","x-xss-protection":"0"},"status":401,"statusText":"Unauthorized","request":{"responseURL":"https://oauth2.googleapis.com/token"}},"status":401,"stack":["Error: unauthorized_client","    at Gaxios._request (/var/task/node_modules/gaxios/build/src/gaxios.js:141:23)","    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)","    at async OAuth2Client.refreshTokenNoCache (/var/task/node_modules/google-auth-library/build/src/auth/oauth2client.js:175:19)","    at async OAuth2Client.refreshAccessTokenAsync (/var/task/node_modules/google-auth-library/build/src/auth/oauth2client.js:209:19)","    at async OAuth2Client.getAccessTokenAsync (/var/task/node_modules/google-auth-library/build/src/auth/oauth2client.js:238:23)"]},"promise":{},"stack":["Runtime.UnhandledPromiseRejection: Error: unauthorized_client","    at process.<anonymous> (file:///var/runtime/index.mjs:1276:17)","    at process.emit (node:events:517:28)","    at emit (node:internal/process/promises:149:20)","    at processPromiseRejections (node:internal/process/promises:283:27)","    at process.processTicksAndRejections (node:internal/process/task_queues:96:32)"]}

This code runs fine on localhost but displays this error when I deployed it on netlify. Note: All the credentials(env) are correct and properly stored. I created the client id, secret and refresh token by making a google cloud project and generating the Oauth credentials from there. And obtained the refresh token from the OauthPlayground2.0 website. This is the REDIRECT_URI: https://developers.google.com/oauthplayground

CODE

const nodemailer = require("nodemailer");
const { google } = require("googleapis");
const dotenv = require("dotenv").config();

exports.handler = async function (event, context) {
  try {

    const { name, email, _subject, message } = JSON.parse(event.body);

    const oAuth2Client = new google.auth.OAuth2(
      process.env.CLIENT_ID,
      process.env.CLIENT_SECRET,
      process.env.REDIRECT_URI
    );

    oAuth2Client.setCredentials({
      refresh_token: process.env.REFRESH_TOKEN,
    });

    const transporter = nodemailer.createTransport({
      service: "gmail",
      auth: {
        type: "OAuth2",
        user: process.env.EMAIL_ADDRESS,
        clientId: process.env.CLIENT_ID,
        clientSecret: process.env.CLIENT_SECRET,
        refreshToken: process.env.REFRESH_TOKEN,
        accessToken: oAuth2Client.getAccessToken(),
      },
    });

    const mailOptions = {
      from: email,
      to: process.env.EMAIL_ADDRESS,
      subject: _subject,
      text: `Name: ${name}\nEmail: ${email}\nSubject: ${_subject}\nMessage: ${message}`,
    };

    await transporter.sendMail(mailOptions);

    return {
      statusCode: 200,
      body: JSON.stringify({ message: "Email sent successfully" }),
    };
  } catch (error) {
    console.error(error);

    return {
      statusCode: 500,
      body: JSON.stringify({ error: "Error sending email" }),
    };
  }
};

Please help me solve this issue.

0

There are 0 best solutions below