node.js - 发送邮件()上的Nodemailer w Google Mail服务帐户错误
问题描述
我正在尝试从 Firebase 功能发送电子邮件,此时我可以获得 jwt 客户端、授权 iy、获取令牌并创建 nodemailer 传输器。但是尝试执行 transporter.sendmail(),我得到一个错误:
info: { Error: Invalid status code 401
at ClientRequest.req.on.res (/Users/yves/Developments/WIP/VUE.JS-vcli-3-beta/le-choro-des-charentes/functions/node_modules/nodemailer/lib/fetch/index.js:221:23)
at emitOne (events.js:116:13)
at ClientRequest.emit (events.js:211:7)
at HTTPParser.parserOnIncomingClient [as onIncoming] (_http_client.js:551:21)
at HTTPParser.parserOnHeadersComplete (_http_common.js:117:23)
at TLSSocket.socketOnData (_http_client.js:440:20)
at emitOne (events.js:116:13)
at TLSSocket.emit (events.js:211:7)
at addChunk (_stream_readable.js:263:12)
at readableAddChunk (_stream_readable.js:250:11)
type: 'FETCH',
sourceUrl: 'https://accounts.google.com/o/oauth2/token',
code: 'EAUTH',
command: 'AUTH XOAUTH2' }
在阅读了很多帖子(在许多不同情况下的问答)之后,我迷失了......我的感觉是这个错误可能与 refresk 令牌有关......但谁知道呢?
这是我的函数(我插入了一些 console.log 来观察它的进展......,所有的环境变量都设置为 w functions.config()):
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp();
const { google } = require('googleapis')
const nodemailer = require('nodemailer')
exports.sendContactEmailOAuth = functions.https.onRequest((req, res) => {
const sender_email = 'john.doe@acme.com';
const sender_msg = 'just a test to contact the site owner.'
const email = 'contact@example.com'
const jwtClient = new google.auth.JWT({
email: functions.config().service_key.client_email,
key: functions.config().service_key.private_key,
scopes: ['https://mail.google.com/']
}
)
console.log('JWT Client: ', jwtClient)
jwtClient.authorize((error, tokens) => {
if (error) {
console.log('NOT AUTHORIZE?: ', error)
res.json({ success: false, error: error });
return
}
console.log('AUTHORIZED tokens: ', tokens)
var transporter = nodemailer.createTransport({
host: "smtp.gmail.com",
port: 465,
secure: true,
auth: {
type: 'OAuth2',
user: email,
serviceClient: functions.config().service_key.client_id,
privateKey: functions.config().service_key.private_key,
accessToken: tokens.access_token,
refreshToken: tokens.refresh_token,
expires: tokens.expiry_date
}
});
console.log('nodemailer transporter set...');
const mailOptions = {
from: 'An Example<' + sender_email + '>',
to: email,
subject: 'Apple and Banana',
text: sender_msg,
html: '<h1>Apple and Banana</h1><p>My html here</p>'
};
transporter.sendMail(mailOptions, (error, response) => {
if (error) {
console.log(error);
res.end('error');
} else {
console.log("Message sent: " + response.message);
res.end('sent');
}
transporter.close();
});
});
});
现在我可以看到控制台输出:
=====================
info: User function triggered, starting execution
info: JWT Client: JWT {
domain: null,
_events: {},
_eventsCount: 0,
_maxListeners: undefined,
transporter: DefaultTransporter {},
credentials: { refresh_token: 'jwt-placeholder', expiry_date: 1 },
certificateCache: null,
certificateExpiry: null,
refreshTokenPromises: Map {},
_clientId: undefined,
_clientSecret: undefined,
redirectUri: undefined,
authBaseUrl: undefined,
tokenUrl: undefined,
eagerRefreshThresholdMillis: 300000,
email: 'postman@example-209605.iam.gserviceaccount.com',
keyFile: undefined,
key: '-----BEGIN PRIVATE KEY-----\nMIIEvAI........IZFwQg==\n-----END PRIVATE KEY-----\n',
scopes: [ 'https://mail.google.com/' ],
subject: undefined,
additionalClaims: undefined }
info: AUTHORIZED tokens: { access_token: 'ya29.c.Elm6BYmTEQ6B82VWaAVx-9oXxX0ytUhgag-FJNPzFl1R9zEeeQQsGuMB5XnMrnbRRZBQuJkprvW1E_Sh8spyEmbd4iwAXbaj2Ou9vcww',
token_type: 'Bearer',
expiry_date: 1526217245000,
id_token: undefined,
refresh_token: 'jwt-placeholder' }
info: nodemailer transporter set...
info: { Error: Invalid status code 401
at ClientRequest.req.on.res (/Users/myself/Developments/myapp/functions/node_modules/nodemailer/lib/fetch/index.js:221:23)
at emitOne (events.js:116:13)
at ClientRequest.emit (events.js:211:7)
at HTTPParser.parserOnIncomingClient [as onIncoming] (_http_client.js:551:21)
at HTTPParser.parserOnHeadersComplete (_http_common.js:117:23)
at TLSSocket.socketOnData (_http_client.js:440:20)
at emitOne (events.js:116:13)
at TLSSocket.emit (events.js:211:7)
at addChunk (_stream_readable.js:263:12)
at readableAddChunk (_stream_readable.js:250:11)
type: 'FETCH',
sourceUrl: 'https://accounts.google.com/o/oauth2/token',
code: 'EAUTH',
command: 'AUTH XOAUTH2' }
- jwt 客户端好吗?我猜一个座位是授权的。
- 代币还好吗?id_token:未定义和 refresh_token:'jwt-placeholder'?
- 这个无效的状态码 401 是什么意思?
感谢您的反馈。我离启动和运行它不远了,但这是经过漫长的 GMail 服务帐户身份验证之后的最后一个问题。
解决方案
推荐阅读
- python - 如何在 Kivymd 列表中激活列表
- python - 如何使用 cv2 去除数字周围的噪音
- kubernetes - 删除期间的 Helm 钩子
- tensorflow - 具有多个前向通道的渐变胶带
- android - 我正在使用带有 expo 的 react native 构建一个应用程序,其中我需要 android 上的图片库的权限
- python - python 表达式 normalize('NFKD', txt)
- javascript - 将 Tooltip div 放置在 span 上方的可变高度(React)
- css - 防止块元素的高度在没有绝对定位的情况下推动其他块元素?
- reactjs - Chart.js 3.5:当同一图表中有多个条形时,线性渐变不正确应用
- r - 如何在 R 中保存 p = scatterplot(data1~data2]