发布 JSON 以使用 Nodemailer 发送电子邮件要么发送邮件但挂起或抛出错误

Posting JSON to send an email with Nodemailer either sends mail but hangs or throws an error

我正在开发 MERN 应用程序,它有一个使用 Nodemailer 发送电子邮件的基本联系表。我想要来自服务器的某种可以显示在前端的响应,例如 'Mail sent' 或 'Mail not sent' 等...

这是我的第一次尝试(代码来自 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...
});

这从服务器获得 'Mail sent!' 响应,但服务器抛出此错误:UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'catch' of undefined,并且它不记录消息 ID 或预览 url,所以我'我不确定它是否真的发送了邮件。

我尝试在捕获之前将 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...
});

这再次获得 'Mail sent!' 响应,但服务器现在抛出此错误:UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'messageId' of undefined

知道如何让它工作吗?我只想要一个简单的联系表单,当提交时,它会从服务器发回响应,并告诉我们邮件是否已发送。

你忘了加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!'});
}