【问题标题】:Promisify Nodemailer with bluebird?用蓝鸟承诺 Nodemailer?
【发布时间】:2015-09-06 02:54:52
【问题描述】:

nodemailer author 明确表示他不支持承诺。我以为我会尝试使用 bluebird,但我的尝试似乎没有发现 Nodemailer 抛出的任何错误:

var nodemailer = require('nodemailer');
var Promise = require('bluebird');

// build the transport with promises
var transport = Promise.promisifyAll( nodemailer.createTransport({...}) );

module.exports = {
    doit = function() {
        // Use bluebird Async
        return transport.sendMailAsync({...});
    }
}

然后我通过这样做来调用它:

doit().then(function() {
    console.log("success!");
}).catch(function(err) {
    console.log("There has been an error");
});

但是,当提供无效的电子邮件时,我会看到:

Unhandled rejection Error: Can't send mail - all recipients were rejected

所以,我的 bluebird 承诺没有捕获 nodemailer 错误。我做错了什么?

【问题讨论】:

  • 您没有向我们展示您的整个代码 - 请制作一个重现它的版本 - 另外 - 在哪一行出现未处理的拒绝错误? (您收到此消息的事实表明 bluebird 确实看到了错误。
  • couchbase crud 方法也有同样的问题。

标签: javascript node.js promise bluebird nodemailer


【解决方案1】:

无法从我的脑海中说出代码有什么问题。我在承诺方面遇到了类似的问题,并决定手动承诺问题案例更容易。这不是最优雅的解决方案,但它是一个解决方案。

var transport = nodemailer.createTransport({...});

module.exports = {
    doit: function() {
        return new Promise(function (res, rej) {
           transport.sendMail({...}, function cb(err, data) {
                if(err) rej(err)
                else res(data)
            });
        });
    }
}

【讨论】:

    【解决方案2】:

    您可以尝试使用 .fromNode() 即时创建 Promise?

    var nodemailer = require('nodemailer');
    var Promise = require('bluebird');
    
    module.exports = {
        doit = function() {            
            return Promise.fromNode(function(callback) {
                transport.sendMail({...}), callback);
            }
        }
    }
    

    doit() 将返回一个蓝鸟承诺。您可以找到.fromNode() here 的文档。

    【讨论】:

      【解决方案3】:

      这就是我的工作方式(打字稿、bluebird's Promise、nodemailer-smtp-transport):

      export const SendEmail = (from:string,
                                to:string[],
                                subject:string,
                                text:string,
                                html:string) => {
      
          const transportOptions = smtpConfiguration; // Defined elsewhere
      
          const transporter = nodemailer.createTransport(smtpTransport(transportOptions));
      
          const emailOptions = {
              from: from,
              to: to.join(','),
              subject: subject,
              text: text,
              html: html
          };
      
          return new Promise((resolve, reject) => {
              transporter.sendMail(emailOptions, (err, data) => {
                  if (err) {
                      return reject(err);
                  } else {
                      return resolve(data);
                  }
              });
          });
      };
      

      【讨论】:

        【解决方案4】:

        如果你只想要Promisify .sendMail 方法,你可以这样做:

        const transport = nodemailer.createTransport({
          host: mailConfig.host,
          port: mailConfig.port,
          secure: true,
          auth: {
            user: mailConfig.username,
            pass: mailConfig.password,
          },
        });
        
        const sendMail = Promise.promisify(transport.sendMail, { context: transport });
        

        并像这样使用它:

        const mailOptions = {
          from: ...,
          to: ...,
          subject: ...,
          html: ...,
          text: ...,
        };
        
        sendMail(mailOptions)
          .then(..)
          .catch(..);
        

        或者如果你使用 async/await 包裹在异步函数中:

        ./mail.js
        
        const send = async (options) => {
          ...
        
          return sendMail(options);
        };
        
        export default { send };
        

        当你使用它时await

        ./testing.js
        
        import mail from './mail';
        
        await mail.sendMail(options);
        

        你明白了。

        【讨论】:

          【解决方案5】:

          现在如果你忽略回调,它会返回一个承诺。

          示例

          const nodemailer = require('nodemailer')
          
          const transport = nodemailer.createTransport({
              host: 'smtp_host',
              port: 'smpt_port',
              auth: {
                  user: 'smpt_auth_user',
                  pass: 'smpt_auth_password',
              },
          })
          
          const promise = transport.sendMail({
              from: '1@test.com',
              to: '2@test.com',
              text: 'Hello world!',
              subject: 'Test'
          })
          
          console.log(promise)
          

          上面的这个日志将返回Promise { <pending> }

          【讨论】:

          • 您的意思是“退货”吗?你能显示一些代码吗?
          • 您好@tomas,我已经更改了答案并添加了一个示例。
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-02-13
          • 2014-11-06
          • 2015-02-13
          • 1970-01-01
          • 2017-01-19
          • 2017-10-10
          相关资源
          最近更新 更多