【问题标题】:Sending email to multiple recipients via nodemailer通过 nodemailer 向多个收件人发送电子邮件
【发布时间】:2015-02-15 15:16:49
【问题描述】:

我正在尝试向多个收件人发送电子邮件。为此,我创建了一个收件人数组,但使用我的代码,我只能将邮件发送到数组的最后一个电子邮件 ID 三次。我的代码有什么问题?

var nodemailer = require("nodemailer");

var smtpTransport = nodemailer.createTransport(
"SMTP",{
  host: '',
  //  secureConnection: true,         // use SSL
  port: 25
});

var maillist = [
  '****.sharma3@****.com',
  '****.bussa@****.com',
  '****.gawri@****.com',
];

var msg = {
    from: "******", // sender address
    subject: "Hello ✔", // Subject line
    text: "Hello This is an auto generated Email for testing  from node please ignore it  ✔", // plaintext body
    cc: "*******"    
    //  html: "<b>Hello world ✔</b>" // html body
}


maillist.forEach(function (to, i , array) {
  msg.to = to;

  smtpTransport.sendMail(msg, function (err) {
    if (err) { 
      console.log('Sending to ' + to + ' failed: ' + err);
      return;
    } else { 
      console.log('Sent to ' + to);
    }

    if (i === maillist.length - 1) { msg.transport.close(); }
  });
});

【问题讨论】:

    标签: javascript node.js nodemailer


    【解决方案1】:

    nodemailer (v2.4.2) docs 说:

    to - 将出现在“收件人:”字段中的逗号分隔列表或收件人电子邮件地址数组

    所以你可以这样做:

    var maillist = [
      '****.sharma3@****.com',
      '****.bussa@****.com',
      '****.gawri@****.com',
    ];
    
    var msg = {
        from: "******", // sender address
        subject: "Hello ✔", // Subject line
        text: "Hello This is an auto generated Email for testing  from node please ignore it  ✔", // plaintext body
        cc: "*******",
        to: maillist
    }
    

    【讨论】:

    • 这些是您正在寻找的机器人。
    【解决方案2】:

    据我所知,您将能够收到多个这样的收件人

    "mail1@mail.com,mail2@mail.com,mail3@mail.com,mail4@mail.com"
    

    那你为什么不做类似的事情

    var maillist = '****.sharma3@****.com, ****.bussa@****.com, ****.gawri@****.com';
    
    var msg = {
        from: "******", // sender address
        to: maillist,
        subject: "Hello ✔", // Subject line
        text: "Hello This is an auto generated Email for ...  ✔", // plaintext body
        cc: "*******"    
        //  html: "<b>Hello world ✔</b>" // html body
    }
    

    我已经尝试过了,它正在工作。此外,从我的角度来看,如果您有发送能力,为什么还要担心“异步”或发送电子邮件 1K 次 所有这些都只需一次,没有任何复杂性?

    无论如何希望这会有所帮助,回答您的问题,或者它可能对其他人有所帮助

    当然,我的答案可以改进..

    【讨论】:

    • 是的,这也是可能的,但是,我事先不知道收件人的TO列表,可以有任意数量的收件人。
    • 但是您从其他地方获取这些收件人...我的意思是您正在获取我认为的表单或变量...顺便说一句,我认为您可以添加某种预先在您发送任何电子邮件之前对电子邮件员进行处理,这样您就可以一次收到所有邮件……我提出了一个关于如何完全格式化变量邮件列表的想法和格式,并且只是在发送电子邮件之前放入“msg” plnkr.co/edit/giNSNHJTlrEi5nj8WmG5
    • 以及如何将变量从 js 传递到 Html 文件??
    • 请记住,这种方法(to 具有多个地址的字段)会将所有电子邮件收件人公开给所有收件人。隐私问题。
    【解决方案3】:

    您的问题是从异步代码中引用相同的 msg 对象。 foreach 在 sendMail 发送电子邮件之前完成。

    所以 msg.to 将是 maiilist 对象的最后一项。

    尝试在邮件列表 foreach 中克隆/复制 msg,或者只是将 msg 定义移动到那里:

    maillist.forEach(function (to, i , array) {
    
    
      var msg = {
            from: "******", // sender address
            subject: "Hello ✔", // Subject line
            text: "Hello This is an auto generated Email for testing  from node please ignore it  ✔", // plaintext body
            cc: "*******"    
            //  html: "<b>Hello world ✔</b>" // html body
        }
      msg.to = to;
    
      smtpTransport.sendMail(msg, function (err) {
    

    【讨论】:

      【解决方案4】:
      var maillist = [
        '****.sharma3@****.com',
        '****.bussa@****.com',
        '****.gawri@****.com',
      ];
      
      maillist.toString();
      
      var msg = {
          from: "******", // sender address
          to: maillist,
          subject: "Hello ✔", // Subject line
          text: "Hello This is an auto generated Email for testing  from node please ignore it  ✔", // plaintext body
          cc: "*******"    
          //  html: "<b>Hello world ✔</b>" // html body
      }
      

      【讨论】:

        【解决方案5】:

        异步执行此操作的一个好方法是使用 async 模块中的 each 函数:https://caolan.github.io/async/docs.html#each

        var async = require("async");
        
        async.each(maillist, function(to, callback){
        
            msg.to = to;
        
            smtpTransport.sendMail(msg, function (err) {
                if (err) { 
                    console.log('Sending to ' + to + ' failed: ' + err);
                    callback(err);
                } else { 
                    console.log('Sent to ' + to);
                    callback();
                }
            });
        }, function(err){
            if(err){
                console.log("Sending to all emails failed:" + err);
            }
        
            //Do other stuff or return appropriate value here
        });
        

        【讨论】:

          【解决方案6】:
          let info = await transporter.sendMail({
            from: [{ name: "sender Name", address: "sender@example.com" }], // sender address
            to: [
              { name: "Receiver Name 1", address: "receiver1@example.com" },
              { name: "Receiver Name 2", address: "receiver2@example.com" },
            ],
            subject: "Hey you, awesome!",
            html: "<b>This is bold text</b>",
            text: "This is text version!",
          });
          
          • 您可以将电子邮件发送给多个收件人,方法是将名称保留在对象数组中,其中名称是收件人姓名,地址是收件人电子邮件地址。
          • 通过上述方式,我可以向多个收件人发送电子邮件。

          【讨论】:

          • 你会考虑为这段代码sn-p添加一些解释吗?
          • 谢谢FilipVeličković 我已经添加了解释。
          【解决方案7】:

          sendMail 方法实际上是在 forEach 循环结束后得到解决,但问题是 sendMail 方法没有返回类型的 promise,所以如果你尝试等待它,它仍然无法工作。

          所以你需要做的是为 sendmail 创建一个单独的函数,从而使它成为这样的承诺

              const send = (transporter: any, mailOptions: any) => {
              return new Promise((resolve, reject) => {
                  transporter.sendMail(mailOptions, (error: any, info: any) => {
                    if (error) {
                      return reject(error);
                    } else {
                      return resolve();
                    }
                  });
              });
              };
          

          所以这可以等待这个,因此迭代器将在进入下一个循环之前等待进程完成。

          完整的代码应该是这样的

              let transporter = nodemailer.createTransport({
                host: "mail.smtp.com", // your server host address
                port: 587, // port
                secure: false, // use TLS // true for 465, false for other ports
                auth: {
                  user: EMAIL_USER, // your email address
                  pass: EMAIL_PSW, // your password
                },
                tls: {
                  rejectUnauthorized: false
                }
              });
          
              // store an array of errors if any
              let successful: any[] = [];
              let failed: any[] = [];
              await recipients.forEach(async (to, i) => {
                let mailOptions = {
                  from, // sender address
                  to, // list of receivers
                  subject, // Subject line
                  text // plain text body
                };
          
                if (html) {
                  (mailOptions as any).html = html;
                }
          
                // send mail with defined transport object
                // here we use the fuction we created which is now a promise
                await send(transporter, mailOptions)
                  .then(() => {
                    successful.push({ success: true, to });
                  })
                  .catch(reason => {
                    failed.push({ success: false, to, message: reason });
                  });
                if (i === recipients.length - 1) {
                  if (failed.length === recipients.length) {
                    return reject({ failed });
                  } else {
                    return resolve({ successful, failed });
                  }
                }
              });
            });
          
          
          const send = (transporter: any, mailOptions: any) => {
          return new Promise((resolve, reject) => {
              transporter.sendMail(mailOptions, (error: any, info: any) => {
                if (error) {
                  return reject(error);
                } else {
                  return resolve();
                }
              });
          });
          };
          

          【讨论】:

            【解决方案8】:

            您正在异步发送电子邮件,因此您需要一个等待功能来等待所有邮件,直到它们被发送,因为如果没有,您的程序将退出并且某些请求没有得到满足。因此,您必须执行某种超时功能来检查电子邮件是否已发送。

            【讨论】:

              【解决方案9】:
              maillist.forEach(function (to, i , array) {
                (function(i,to){
                   msg.to = to;
                smtpTransport.sendMail(msg, function (err) {
                  if (err) { 
                    console.log('Sending to ' + to + ' failed: ' + err);
                    return;
                  } else { 
                    console.log('Sent to ' + to);
                  }
              
                  if (i === maillist.length - 1) { msg.transport.close(); }
                });
              })(i,to)
              });
              

              【讨论】:

              • 点评来源: 您好,请不要只用源代码回答。尝试对您的解决方案如何工作提供一个很好的描述。请参阅:How do I write a good answer?。谢谢
              猜你喜欢
              • 2013-10-30
              • 2012-05-18
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2017-05-16
              • 2017-01-10
              相关资源
              最近更新 更多