javascript - 使用 Nodemailer 发布 JSON 来发送电子邮件要么发送邮件,但挂起或引发错误

标签 javascript node.js express email nodemailer

我正在开发带有基本联系表单的 MERN 应用程序,该表单使用 Nodemailer 发送电子邮件。我想要来自服务器的某种响应可以显示在前端,例如“邮件已发送”或“邮件未发送”等...

这是我的第一次尝试(来自 server.js 的代码),基于示例 here :

myRoutes.route('/send-mail').post(async function(req, res) {
  let testAccount = await nodemailer.createTestAccount();

  // create reusable transporter object using the default SMTP transport
  let transporter = nodemailer.createTransport({
      host: 'smtp.ethereal.email',
      port: 587,
      secure: false, // true for 465, false for other ports
      auth: {
          user: testAccount.user, // generated ethereal user
          pass: testAccount.pass // generated ethereal password
      }
  });

  let senderName = req.body.senderName;
  let senderEmail = req.body.senderEmail;
  let subject = req.body.subject;
  let message = req.body.message;
  let toEmail = req.body.toEmail;

  // send mail with defined transport object
  let info = await transporter.sendMail({
      from: `"${senderName}" <${senderEmail}>`, // sender address
      to: toEmail, // receiver address
      subject: subject, // Subject line
      text: message, // plain text body
      html: message
  });

  console.log('Message sent: %s', info.messageId);
  // Message sent: <b658f8ca-6296-ccf4-8306-87d57a0b4321@example.com>

  // Preview only available when sending through an Ethereal account
  console.log('Preview URL: %s', nodemailer.getTestMessageUrl(info));
  // Preview URL: https://ethereal.email/message/WaQKMgKddxQDoou...
});

这可行(邮件已发送,预览 URL 已记录到控制台),但对服务器的 post 请求只是挂起,直到最终超时。因此,由于无论如何我都需要这样做,为了从服务器获取响应并通知前端用户,我想我应该在 sendMail 函数之后添加一个回调。

带回调的代码:

myRoutes.route('/send-mail').post(async function(req, res) {
  let testAccount = await nodemailer.createTestAccount();

  // create reusable transporter object using the default SMTP transport
  let transporter = nodemailer.createTransport({
      host: 'smtp.ethereal.email',
      port: 587,
      secure: false, // true for 465, false for other ports
      auth: {
          user: testAccount.user, // generated ethereal user
          pass: testAccount.pass // generated ethereal password
      }
  });

  let senderName = req.body.senderName;
  let senderEmail = req.body.senderEmail;
  let subject = req.body.subject;
  let message = req.body.message;
  let toEmail = req.body.toEmail;

  // send mail with defined transport object
  let info = await transporter.sendMail({
      from: `"${senderName}" <${senderEmail}>`, // sender address
      to: toEmail, // receiver address
      subject: subject, // Subject line
      text: message, // plain text body
      html: message
  },function(){
    res.json('Mail sent!');
  }).catch(err => {
    res.json("Couldn't send the mail for some reason");
  });

  console.log('Message sent: %s', info.messageId);
  // Message sent: <b658f8ca-6296-ccf4-8306-87d57a0b4321@example.com>

  // Preview only available when sending through an Ethereal account
  console.log('Preview URL: %s', nodemailer.getTestMessageUrl(info));
  // Preview URL: https://ethereal.email/message/WaQKMgKddxQDoou...
});

这会收到“邮件已发送!”来自服务器的响应,但服务器抛出此错误:UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'catch' of undefined,并且它不记录 messageID 或预览 url,所以我不确定是否确实发送了邮件。

我尝试在 catch 之前将 err 作为参数传递给函数,但这没有帮助。

我还尝试完全删除捕获(见下文):

myRoutes.route('/send-mail').post(async function(req, res) {
  let testAccount = await nodemailer.createTestAccount();

  // create reusable transporter object using the default SMTP transport
  let transporter = nodemailer.createTransport({
      host: 'smtp.ethereal.email',
      port: 587,
      secure: false, // true for 465, false for other ports
      auth: {
          user: testAccount.user, // generated ethereal user
          pass: testAccount.pass // generated ethereal password
      }
  });

  let senderName = req.body.senderName;
  let senderEmail = req.body.senderEmail;
  let subject = req.body.subject;
  let message = req.body.message;
  let toEmail = req.body.toEmail;

  // send mail with defined transport object
  let info = await transporter.sendMail({
      from: `"${senderName}" <${senderEmail}>`, // sender address
      to: toEmail, // receiver address
      subject: subject, // Subject line
      text: message, // plain text body
      html: message
  },function(){
    res.json('Mail sent!');
  });

  console.log('Message sent: %s', info.messageId);
  // Message sent: <b658f8ca-6296-ccf4-8306-87d57a0b4321@example.com>

  // Preview only available when sending through an Ethereal account
  console.log('Preview URL: %s', nodemailer.getTestMessageUrl(info));
  // Preview URL: https://ethereal.email/message/WaQKMgKddxQDoou...
});

这会得到“邮件已发送!”再次响应,但服务器现在抛出此错误:UnhandledPromiseRejectionWarning:TypeError:无法读取未定义的属性“messageId”

知道我怎样才能让它工作吗?我只想要一个简单的联系表单,提交后,它会从服务器发回响应,并显示状态告诉我们邮件是否已发送。

最佳答案

你忘记添加 return ,试试这个方法:

let info = await transporter.sendMail({
      from: `"${senderName}" <${senderEmail}>`, // sender address
      to: toEmail, // receiver address
      subject: subject, // Subject line
      text: message, // plain text body
      html: message
  }).then((data)=>{return data}).catch((error)=> {return error});

if(info.messageId){
   console.log('Message sent: %s', info.messageId);
   res.json({message:'Mail sent!'});
}else{
   console.log('Message Not sent');
   res.json({message:'Mail not sent!'});
}

关于javascript - 使用 Nodemailer 发布 JSON 来发送电子邮件要么发送邮件,但挂起或引发错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58248612/

相关文章:

javascript - 如何监听 HTML 页面中按下提交按钮的声音

javascript - 如何在发布新消息之前删除rabbitmq中的特定消息?

node.js - Nodejs 中所有路由之后的中间件

javascript - 用于从许多具有 "for"循环的 url 获取 html 信息的 x 射线使 objs 未定义

javascript - 当我选择一个选项值时,如何让 Javascript 知道?

javascript - 为什么输入框不在背景图片之上?

javascript - 无法将 JSON 结果绑定(bind)到组件变量

javascript - 在 express 中将路由设置为静态文件

javascript - NestJS : transform responses

node.js - 我无法获取/users json