web-dev-qa-db-ja.com

nodemailerを介して複数の受信者にメールを送信する

複数の受信者にメールを送信しようとしています。このために、受信者の配列を作成しましたが、私のコードでは、配列の最後の電子メールIDに3回しかメールを送信できません。私のコードの何が問題になっていますか?

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(); }
  });
});
24
Atul Sharma

問題は、非同期コードから同じ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) {
13
eenagy

nodemailer(v2.4.2) docs say:

to-[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
}
33
pkyeck

私の知る限り、あなたはこのような複数の受信者を取得することができます

"[email protected],[email protected],[email protected],[email protected]"

なぜあなたは次のようなことをしないのですか

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回メールを送信することを心配する必要があるのはなぜですか。

とにかく、この助けを願って、あなたの質問に答えるか、誰かの助けになるかもしれません

確かに、私の答えは改善できます。

22
ackuser
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
}
4
Nitin Kumar

非同期に行う良い方法は、非同期モジュールの各関数を使用することです: 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
});
4
bmpickford

SendMailメソッドは、forEachループの終了後に実際に解決されますが、問題はsendMailメソッドがプロミスのタイプを返さないため、これを待機しようとしても機能しません。

あなたがする必要があるのは、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();
      }
    });
});
};
1
Klexzi

電子メールを非同期で送信するため、送信されるまですべてのメールを待機する待機機能が必要です。送信されない場合は、プログラムが終了し、リクエストの一部が満たされないためです。そのため、電子メールが送信されたかどうかを確認するタイムアウト機能を実行する必要があります。

0
satchcoder