web-dev-qa-db-fra.com

Envoi d'e-mails à plusieurs destinataires via nodemailer

J'essaie d'envoyer un courrier électronique à plusieurs destinataires. Pour cela, j'ai créé un tableau de destinataires, mais avec mon code, je ne peux envoyer qu'un courrier électronique au dernier ID de courrier électronique du tableau trois fois. Qu'est ce qui ne va pas avec mon code?

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

Votre problème est de référencer le même objet msg à partir du code async ..... Le foreach est terminé avant que sendMail n'envoie les emails.

Ainsi, msg.to sera le dernier élément de l'objet maiiliste.

Essayez de cloner/copier des msg dans maillist foreach, ou déplacez simplement la définition du msg à cet endroit: 

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) {
7
eenagy

nodemailer (v2.4.2) docs say:

to - Liste séparée par des virgules ou un tableau d'adresses de messagerie de destinataires qui figureront dans le champ À:

alors vous pouvez juste faire:

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
}
24
pkyeck

Autant que je sache, vous pourrez avoir plusieurs destinataires comme celui-ci.

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

Alors pourquoi tu ne fais pas quelque chose comme 

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
}

J'ai déjà essayé et ça marche. En outre, de mon point de vue, pourquoi vous devez vous soucier de manière "asynchrone" ou envoyer des courriels 1K fois si vous avez la possibilité d’envoyer Tous en une seule fois sans complication?

Quoi qu'il en soit, espérons que cette aide, répondez à votre question ou il peut aider quelqu'un d'autre

Ma réponse peut sûrement être améliorée.

19
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

Un bon moyen de le faire de manière asynchrone serait d'utiliser la fonction each dans le module async: 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

Vous envoyez les e-mails de manière asynchrone, vous avez donc besoin d'une fonction d'attente qui attend tous les e-mails jusqu'à ce qu'ils aient été envoyés. Sinon, vous programmez des exits et certaines demandes ne sont pas satisfaites. Donc, vous devez faire une sorte de fonction de délai qui vérifie si les emails ont été envoyés.

0
satchcoder

La méthode sendMail est effectivement résolue une fois la boucle forEach terminée, mais le problème est que la méthode sendMail ne renvoie pas un type de promesse. Par conséquent, si vous essayez d'attendre cela, cela ne fonctionnera toujours pas.

vous devez donc créer une fonction distincte pour sendmail, ce qui en fait une promesse comme celle-ci.

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

ceci permet donc d'attendre cela et donc l'itérateur attendra que le processus se termine avant de passer à la boucle suivante.

Le code complet devrait ressembler à ceci

    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();
      }
    });
});
};
0
Klexzi