基本上,我试图向用户发送一个url来重置他的密码。我已经正确地从mailer.js
导入了所有的东西,并且在得到响应之前一切都很好。这是说
it can not read property response of undefined.
routes/users.js
router.post("/reset-password/:email", emailController.createResetPasswordToken)
utils/mailer.js
const nodemailer = require("nodemailer")
let transporter = nodemailer.createTransport({
service: "gmail",
auth: {
user: process.env.EMAIL,
pass: process.env.PASSWORD
}
})
getPasswordResetURL = (user, token) => {
return `http://localhost:3000/reset-password/${user._id}/${token}`
}
const resetPasswordTemplate = (user, url) => {
const from = process.env.EMAIL
const to = user.email
const subject = "Password Reset"
const html = `
<p>Hey ${user.name || user.email},</p>
<p>We heard that you forgot your password. Sorry about that!</p>
<p>But don’t worry! You can use the following link to reset your password:</p>
<a href=${url}>${url}</a>
<p>If you don’t use this link within 1 hour, it will expire.</p>
`
}
module.exports = { transporter, getPasswordResetURL, resetPasswordTemplate }
emailController.js
const User = require("../models/User")
const bcrypt = require("bcrypt")
const jwt = require("jsonwebtoken")
const validator = require("validator")
const { transporter, getPasswordResetURL, resetPasswordTemplate } = require("../utils/mailer")
module.exports = {
createResetPasswordTokenAndSendMail: (req, res) => {
const email = req.params.email
User.findOne({ email }, (err, user) => {
if (err) console.log(err)
// res.json({user})
const hashedPassword = user.password
const createdAt = user.createdAt
const userId = user._id
// console.log(user.password, user.createdAt, userId )
const secret = hashedPassword + "-" + createdAt
const token = jwt.sign({ userId }, secret, {
expiresIn: 3600
})
// console.log(token)
// console.log(user)
const url = getPasswordResetURL(user, token)
// console.log(url)
const emailTemplate = resetPasswordTemplate(user, url)
// console.log(emailTemplate, "l26")
const sendEmail = () => {
transporter.sendMail(emailTemplate, (err, info) => {
if (err) console.log(err)
// console.log(info, "L31")
console.log("email sent successfully", info.response)
})
}
sendEmail()
})
}
}
当我在Postman中测试这个API时,我在控制台中得到了以下错误:
{ Error: Missing credentials for "PLAIN"
at SMTPConnection._formatError (/home/voidrealm/Desktop/myApp/node_modules/nodemailer/lib/smtp-connection/index.js:784:19)
at SMTPConnection.login (/home/voidrealm/Desktop/myApp/node_modules/nodemailer/lib/smtp-connection/index.js:448:38)
at connection.connect (/home/voidrealm/Desktop/myApp/node_modules/nodemailer/lib/smtp-transport/index.js:271:32)
at SMTPConnection.once (/home/voidrealm/Desktop/myApp/node_modules/nodemailer/lib/smtp-connection/index.js:215:17)
at Object.onceWrapper (events.js:313:30)
at emitNone (events.js:106:13)
at SMTPConnection.emit (events.js:208:7)
at SMTPConnection._actionEHLO (/home/voidrealm/Desktop/myApp/node_modules/nodemailer/lib/smtp-connection/index.js:1313:14)
at SMTPConnection._processResponse (/home/voidrealm/Desktop/myApp/node_modules/nodemailer/lib/smtp-connection/index.js:942:20)
at SMTPConnection._onData (/home/voidrealm/Desktop/myApp/node_modules/nodemailer/lib/smtp-connection/index.js:749:14)
at TLSSocket.SMTPConnection._onSocketData.chunk (/home/voidrealm/Desktop/myApp/node_modules/nodemailer/lib/smtp-connection/index.js:195:44)
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)
at TLSSocket.Readable.push (_stream_readable.js:208:10) code: 'EAUTH', command: 'API' }
/home/voidrealm/Desktop/myApp/controllers/emailController.js:32
console.log("email sent successfully", info.response)
^
TypeError: Cannot read property 'response' of undefined
at transporter.sendMail (/home/voidrealm/Desktop/myApp/controllers/emailController.js:32:69)
at transporter.send.args (/home/voidrealm/Desktop/myApp/node_modules/nodemailer/lib/mailer/index.js:226:21)
at connection.login.err (/home/voidrealm/Desktop/myApp/node_modules/nodemailer/lib/smtp-transport/index.js:282:36)
at SMTPConnection.login (/home/voidrealm/Desktop/myApp/node_modules/nodemailer/lib/smtp-connection/index.js:448:24)
at connection.connect (/home/voidrealm/Desktop/myApp/node_modules/nodemailer/lib/smtp-transport/index.js:271:32)
at SMTPConnection.once (/home/voidrealm/Desktop/myApp/node_modules/nodemailer/lib/smtp-connection/index.js:215:17)
at Object.onceWrapper (events.js:313:30)
at emitNone (events.js:106:13)
at SMTPConnection.emit (events.js:208:7)
at SMTPConnection._actionEHLO (/home/voidrealm/Desktop/myApp/node_modules/nodemailer/lib/smtp-connection/index.js:1313:14)
at SMTPConnection._processResponse (/home/voidrealm/Desktop/myApp/node_modules/nodemailer/lib/smtp-connection/index.js:942:20)
at SMTPConnection._onData (/home/voidrealm/Desktop/myApp/node_modules/nodemailer/lib/smtp-connection/index.js:749:14)
at TLSSocket.SMTPConnection._onSocketData.chunk (/home/voidrealm/Desktop/myApp/node_modules/nodemailer/lib/smtp-connection/index.js:195:44)
at emitOne (events.js:116:13)
at TLSSocket.emit (events.js:211:7)
at addChunk (_stream_readable.js:263:12)
更新
配置OAuth之后,我将得到相同的错误:
这是我更新的代码。
mailer.js
const nodemailer = require("nodemailer")
let transporter = nodemailer.createTransport({
service: "gmail",
auth: {
type: "OAuth2",
user: process.env.EMAIL,
clientId: process.env.clientId,
clientSecret: process.env.clientSecret,
refreshToken: process.env.refreshToken,
accessToken: process.env.accessToken,
expiresIn: process.env.expiresIn
}
})
getPasswordResetURL = (user, token) => {
return `http://localhost:3000/reset-password/${user._id}/${token}`
}
const resetPasswordTemplate = (user, url) => {
from = process.env.EMAIL,
to = user.email,
subject = "Password Reset",
auth = {
user: user.email,
refreshToken: process.env.refreshToken,
accessToken: process.env.accessToken,
expiresIn: process.env.expiresIn
},
html = `
<p>We heard that you forgot your password. Sorry about that!</p>
<p>But don’t worry! You can use the following link to reset your password:</p>
<a href=${url}>${url}</a>
<p>If you don’t use this link within 1 hour, it will expire.</p>
`
return {from, to, subject, html, auth}
}
module.exports = { transporter, getPasswordResetURL, resetPasswordTemplate }
emailController.js
const User = require("../models/User")
const bcrypt = require("bcrypt")
const jwt = require("jsonwebtoken")
const validator = require("validator")
const { transporter, getPasswordResetURL, resetPasswordTemplate } = require("../utils/mailer")
module.exports = {
createResetPasswordTokenAndSendMail: (req, res) => {
const email = req.params.email
User.findOne({ email }, (err, user) => {
if (err) console.log(err)
// res.json({user})
const hashedPassword = user.password
const createdAt = user.createdAt
const userId = user._id
// console.log(user.password, user.createdAt, userId )
const secret = hashedPassword + "-" + createdAt
const token = jwt.sign({ userId }, secret, {
expiresIn: 3600
})
// console.log(token)
// console.log(user)
const url = getPasswordResetURL(user, token)
// console.log(url)
const emailTemplate = resetPasswordTemplate(user, url)
console.log(emailTemplate, "l26")
const sendEmail = () => {
transporter.sendMail(emailTemplate, (err, info) => {
if (err) console.log(err)
// console.log(info, "L31")
console.log("email sent successfully", info.response)
})
}
sendEmail()
})
}
}
控制台
{ Error: invalid_request
at postRequest (/home/voidrealm/Desktop/myApp/node_modules/nodemailer/lib/xoauth2/index.js:259:33)
at PassThrough.req.once (/home/voidrealm/Desktop/myApp/node_modules/nodemailer/lib/xoauth2/index.js:328:20)
at Object.onceWrapper (events.js:313:30)
at emitNone (events.js:111:20)
at PassThrough.emit (events.js:208:7)
at endReadableNT (_stream_readable.js:1064:12)
at _combinedTickCallback (internal/process/next_tick.js:138:11)
at process._tickCallback (internal/process/next_tick.js:180:9) code: 'EAUTH', command: 'AUTH XOAUTH2' }
/home/voidrealm/Desktop/myApp/controllers/emailController.js:33
console.log("email sent successfully", info.response)
^
TypeError: Cannot read property 'response' of undefined
at transporter.sendMail (/home/voidrealm/Desktop/myApp/controllers/emailController.js:33:69)
at transporter.send.args (/home/voidrealm/Desktop/myApp/node_modules/nodemailer/lib/mailer/index.js:226:21)
at connection.login.err (/home/voidrealm/Desktop/myApp/node_modules/nodemailer/lib/smtp-transport/index.js:282:36)
at _auth.oauth2.getToken (/home/voidrealm/Desktop/myApp/node_modules/nodemailer/lib/smtp-connection/index.js:1709:24)
at generateCallback (/home/voidrealm/Desktop/myApp/node_modules/nodemailer/lib/xoauth2/index.js:111:13)
at postRequest (/home/voidrealm/Desktop/myApp/node_modules/nodemailer/lib/xoauth2/index.js:259:24)
at PassThrough.req.once (/home/voidrealm/Desktop/myApp/node_modules/nodemailer/lib/xoauth2/index.js:328:20)
at Object.onceWrapper (events.js:313:30)
at emitNone (events.js:111:20)
at PassThrough.emit (events.js:208:7)
at endReadableNT (_stream_readable.js:1064:12)
at _combinedTickCallback (internal/process/next_tick.js:138:11)
at process._tickCallback (internal/process/next_tick.js:180:9)
Note:我正在获取auth所需的所有凭据值,并将其保存在我的.env文件中。
发布于 2020-02-22 10:38:23
根据this answer的说法,Gmail / Google电子邮件服务需要OAuth2来进行认证。纯文本密码需要在google帐户上手动禁用安全功能。
因此,请确保您从您的帐户禁用安全功能或使用oAuth2。
另外,我不确定您使用的是哪个版本的Nodemail,但是info参数不包含response
支柱。它有一个envelope
和一个messageId
属性。
发布于 2020-02-22 14:02:28
你什么地方都没有宣布运输机。
试着执行下面的代码,
var transporter = nodemailer.createTransport({
service: 'gmail',
auth: {
user: process.env.EMAIL,
pass: process.env.PASSWORD
}
});
var mailOptions = {
const from = process.env.EMAIL
const to = user.email
const subject = "Password Reset"
const html = `
<p>Hey` + user.name user.email+`,</p>
<p>We heard that you forgot your password. Sorry about that!</p>
<p>But don’t worry! You can use the following link to reset your password:</p>
<a href=`url`>`url</a>
<p>If you don’t use this link within 1 hour, it will expire.</p>
`
};
transporter.sendMail(mailOptions, function(error, info){
if (error) {
console.log(error);
} else {
console.log('Email sent: ' + info.response);
}
});
编辑的
更改html格式,就像我在上面的代码中所做的那样。
https://stackoverflow.com/questions/60351160
复制相似问题