Nodemailer 3LO OAuth给予GaxiosError:未授权客户端

c3frrgcw  于 2023-05-28  发布在  iOS
关注(0)|答案(2)|浏览(114)

在emailTransporter.js我的代码如下。

const nodemailer = require('nodemailer');
const { google } = require("googleapis");
const path = require('path');
const OAuth2 = google.auth.OAuth2;

require('dotenv').config({path: path.join(__dirname, '.env')});

const oauth2Client = new OAuth2(
    process.env.CLIENT_ID, // ClientID
    process.env.CLIENT_SECRET, // Client Secret
    "https://developers.google.com/oauthplayground" // Redirect URL
);

oauth2Client.setCredentials({
    refresh_token: process.env.REFRESH_TOKEN
});
const accessToken = oauth2Client.getAccessToken();

let transporter = nodemailer.createTransport({
    host: 'smtp.gmail.com',
    port: 465,
    secure: true,
    auth: {
        type: "OAuth2",
        user: process.env.USER_EMAIL, 
        clientId: process.env.CLIENT_ID,
        clientSecret: process.env.CLIENT_SECRET,
        refreshToken: process.env.REFRESH_TOKEN,
        accessToken: accessToken
    },
    tls: {
        rejectUnauthorized: false
    }
});

module.exports = transporter;

在auth.js中,我使用emailTransporter.js中的emailTransporter导出来发送一些电子邮件选项。但是node给我的错误是这样的:
D:\nodejs\node_modules\gaxios\build\src\gaxios. js:129 throw new common_1.GaxiosError(Request failed with status code ${translatedResponse.status},opts,translatedResponse);^
GaxiosError:unauthorized_client在Gaxios。_request(D:\nodejs\node_modules\gaxios\build\src\gaxios。js:一百二十九:23)在processTicksAndRejections(节点:internal/process/task_queues:九十六:5)at async OAuth2Client.refreshTokenNoCache(D:\nodejs\node_modules\google-auth-library\build\src\auth\oauth2client.js:一百七十四:21)at async OAuth2Client.refreshAccessTokenAsync(D:\nodejs\node_modules\google-auth-library\build\src\auth\oauth2client.js:一百九十八:19)at async OAuth2Client.getAccessTokenAsync(D:\nodejs\node_modules\google-auth-library\build\src\auth\oauth2client.js:二百二十七:23){响应:{配置:{方法:'POST',url:'https://oauth2.googleapis.com/token',data:'refresh_token = 1%2F%2F04PvTQnD4_www.example.com & client_secret = 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 & grant_type = refresh_token',header:86nCgYIARAAGAQSNwF-L9IrTdRMaV9mdIMhyEhFeJeKGSvqYnbgkCw-18aF7ZFmRgpWoWiQM3EXozwMiXzvfYwmAwc&client_id=543495663437-d59lg6u1a77o9a2uinf83idb0md991l9.apps.googleusercontent.com'application/x-www-form-urlencoded',' User-Agent':'google-api-nodejs-client/7.11.0',' x-goog-api-client':'gl-node/16.13.2 auth/7.11.0',接受:'application/json '},paramsSerializer:[函数:paramsSerializer],函数体:2019 - 01 - 22 00:00:00:00 Copyright © 2018 - 2019 www.d59lg6u1a.com版权所有77o9a2uinf83idb0md991l9.apps.googleusercontent.com&client_secret = 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 & grant_type = refresh_token',validateStatus:[Function:validateStatus],responseType:'json '},数据:{error:'unauthorized_client',error_description:'Unauthorized '},标头:{'alt-svc':'h3 =":443"; ma = 2592000,h3 - 29 =":443"; ma = 2592000,h3-Q050 =":443"; ma = 2592000,h3-Q046 =":443"; ma = 2592000,h3-Q043 =":443"; ma = 2592000,quic =":443"; ma = 2592000 v ="46,43"',' cache-control':'no-cache,no-store,max-age = 0,must-revalidate',连接:'close','content-encoding':'gzip','content-type':'application/json; charset = utf-8',日期:'Wed,19 Jan 2022 03:47:31 GMT',过期时间:'Mon,01 Jan 1990 00:00:00 GMT',pragma:'no-cache',服务器:'HTTPServer2上的脚手架','transfer-encoding':'chunked',vary:'Origin,X-Origin,Refererer',' x-content-type-options':'nosniff',' x-frame-options':'SAMEORIGIN',' x-xss-protection':“0”},状态:401,状态文本:“未经授权”,请求:{responseURL:'https://oauth2.googleapis.com/token '}},配置:{method:'POST',url:'https://oauth2.googleapis.com/token',data:'refresh_token = 1%2F%2F04PvTQnD4_www.example.com & client_secret = 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 & grant_type = refresh_token',header:{'Content-Type ':'application/x-www-form-urlencoded',' User-Agent':86nCgYIARAAGAQSNwF-L9IrTdRMaV9mdIMhyEhFeJeKGSvqYnbgkCw-18aF7ZFmRgpWoWiQM3EXozwMiXzvfYwmAwc&client_id=543495663437-d59lg6u1a77o9a2uinf83idb0md991l9.apps.googleusercontent.com'gl-node/16.13.2 auth/7.11.0',接受:'application/json '},paramsSerializer:[函数:paramsSerializer],函数体:2019 - 01 - 22 00:00:00:00 Copyright © 2018 - 2019 www.d59lg6u1a.com版权所有77o9a2uinf83idb0md991l9.apps.googleusercontent.com&client_secret = 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 & grant_type = refresh_token',validateStatus:[Function:validateStatus],responseType:'json '},代码:'401 '} 'refresh_token=1%2F%2F04PvTQnD4_86nCgYIARAAGAQSNwF-L9IrTdRMaV9mdIMhyEhFeJeKGSvqYnbgkCw-18aF7ZFmRgpWoWiQM3EXozwMiXzvfYwmAwc&client_id=543495663437-d59lg6u1a77o9a2uinf83idb0md991l9.apps.googleusercontent.com&client_secret=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&grant_type=refresh_token', validateStatus: [Function: validateStatus], responseType: 'json' }, code: '401' }

acruukt9

acruukt91#

https://developers.google.com/oauthplayground/中,我必须选择右上方的“使用您自己的凭据”选项。填写cliendId和clientSecret,它已经工作了。

mfuanj7w

mfuanj7w2#

// I was able to go around this issue by using the clientId and secret 
// directly in the file. I realized it wasn't 
// picking up the id and secret values from the .env file.
// My test only works with Node.js at the moment. not sure if it works for  
// other program/language.

import nodemailer from "nodemailer";

import { google } from "googleapis";

const CLIENT_ID = "insert your client id from goodle cloud console";
const CLIENT_SECRET = "insert your client secret from goodle cloud console";
const REDIRECT_URI = "https://developers.google.com/oauthplayground";
const REFRESH_TOKEN = "insert your refresh token from oauth playground";

const OAuth2Client = new google.auth.OAuth2(
  CLIENT_ID,
  CLIENT_SECRET,
  REDIRECT_URI
);

OAuth2Client.setCredentials({ refresh_token: REFRESH_TOKEN });

export default async function sendVerificationEmail(email, name, url) {
  try {
    const accessToken = await OAuth2Client.getAccessToken();
    const transport = nodemailer.createTransport({
      service: "gmail",
      auth: {
        type: "OAuth2",
        user: "sender@gmail.com",
        clientId: CLIENT_ID,
        clientSecret: CLIENT_SECRET,
        refreshToken: REFRESH_TOKEN,
        accessToken: accessToken,
      },
    });
    const mailOptions = {
      from: "Support 📧 <sender@gmail.com>",
      to: email,
      subject: "Facebook email verification",
      text: "Facebook email verification",
      html: `<div style="max-width:700px;margin-bottom:1rem;display:flex;align-items:center;gap:10px;font-family:Roboto;font-weight:600;color:#3b5998"><img src="https://res.cloudinary.com/dmhcnhtng/image/upload/v1645134414/logo_cs1si5.png" alt="" style="width:30px"><span>Action requise : Activate your facebook account</span></div><div style="padding:1rem 0;border-top:1px solid #e5e5e5;border-bottom:1px solid #e5e5e5;color:#141823;font-size:17px;font-family:Roboto"><span>Hello ${name}</span><div style="padding:20px 0"><span style="padding:1.5rem 0">You recently created an account on Facebook. To complete your registration, please confirm your account.</span></div><a href=${url} style="width:200px;padding:10px 15px;background:#4c649b;color:#fff;text-decoration:none;font-weight:600">Confirm your account</a><br><div style="padding-top:20px"><span style="margin:1.5rem 0;color:#898f9c">Facebook allows you to stay in touch with all your friends, once refistered on facebook,you can share photos,organize events and much more.</span></div></div>`,
    };
    const result = transport.sendMail(mailOptions, (err, res) => {
      if (err) return err;
      return res;
    });
    return result;
  } catch (error) {
    return error;
  }
}

相关问题