複数の受信者にメールを送信しようとしています。このために、受信者の配列を作成しましたが、私のコードでは、配列の最後の電子メール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(); }
});
});
問題は、非同期コードから同じ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) {
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
}
私の知る限り、あなたはこのような複数の受信者を取得することができます
"[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回メールを送信することを心配する必要があるのはなぜですか。
とにかく、この助けを願って、あなたの質問に答えるか、誰かの助けになるかもしれません
確かに、私の答えは改善できます。
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
}
非同期に行う良い方法は、非同期モジュールの各関数を使用することです: 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
});
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();
}
});
});
};
電子メールを非同期で送信するため、送信されるまですべてのメールを待機する待機機能が必要です。送信されない場合は、プログラムが終了し、リクエストの一部が満たされないためです。そのため、電子メールが送信されたかどうかを確認するタイムアウト機能を実行する必要があります。