首先让我详细介绍一下。我使用节点的nodemailer从表单上提交的信息发送电子邮件。当我有一个收件人和一个html主体,它立即发送它,工作正常。但是当我将mailOptions2
放在for
循环中时,我就可以发送包含不同数组中的收件人和html主体的电子邮件。然后它仍然以不同的方式发送电子邮件和html内容。但是当提交表单时,在/send
状态下它会继续加载,最终只加载页面的原始html,没有css。我收到这个错误:
Error: Can't set headers after they are sent.
at validateHeader (_http_outgoing.js:489:11)
at ServerResponse.setHeader (_http_outgoing.js:496:3)
at ServerResponse.header (C:\Users\Ahmet Ömer\Desktop\Repairtechnician\node_modules\express\lib\response.js:767:10)
at ServerResponse.send (C:\Users\Ahmet Ömer\Desktop\Repairtechnician\node_modules\express\lib\response.js:170:12)
at done (C:\Users\Ahmet Ömer\Desktop\Repairtechnician\node_modules\express\lib\response.js:1004:10)
at Immediate._onImmediate (C:\Users\Ahmet Ömer\Desktop\Repairtechnician\node_modules\express-handlebars\lib\utils.js:26:13)
at runCallback (timers.js:781:20)
at tryOnImmediate (timers.js:743:5)
at processImmediate [as _immediateCallback] (timers.js:714:5)
我知道有关于此错误的帖子,但在我的情况下无法知道如何解决它,因为我还是初学者。
的NodeJS:
app2.engine('handlebars', exphbs2());
app2.set('view engine', 'handlebars');
// Static folder
app2.use('/public', express2.static(path2.join(__dirname, 'public')));
app2.use('/', express2.static(path2.join(__dirname, '')));
// Body Parser Middleware
app2.use(bodyParser2.urlencoded({ extended: false }));
app2.use(bodyParser2.json());
app2.get('/', (req, res) => {
res.render('services');
});
app2.post('/send', (req, res) => {
let mailList = ['xyz', 'xyz@gmail.com'];
let outputs = [
`
<div>
</div>
`,
`
<div>
</div>
`];
// create reusable transporter object using the default SMTP transport
let transporter2 = nodemailer2.createTransport({
service: 'gmail',
port: 25,
secure: false,
auth: {
user: 'xyz@gmail.com', // senders email
pass: 'xyz' // senders password
},
tls:{
rejectUnauthorized:false
}
});
for ( var i = 0; i < mailList.length; i++) {
// setup email data with raw html
let mailOptions2 = {
from: '"xyz" <xyz@info.com>', // sender address
to: mailList[i], // receiver or receivers
subject: 'xyz', // Subject line
html: outputs[i] // html body
};
// send mail with defined transport object
transporter2.sendMail(mailOptions2, (error, info) => {
if (error) {
return console.log(error);
}
console.log('Message sent: %s', info.messageId);
console.log('Preview URL: %s', nodemailer2.getTestMessageUrl(info));
res.render('services', {msg2:'xyz'});
});
}
});
正如我所说,如果我没有使用for
mailOptions2
循环将不同的值传递给指定区域,那么它就可以正常工作。
如果可能有帮助,这是我提到的文件的结构:
server.js
services.html
public
css
styles.css
答案 0 :(得分:3)
您无法多次调用res.render()
,因为res.render
会将已编译的html发送给客户端。因此,只有在您希望向客户发送最终回复时,才需要致电res.render
。
对于这种情况,您可以使用Promise来管理sendMail回调:
// init this array outside the for loop
let sendMailPromises = [];
// this is inside the for loop
let promise = new Promise((resolve, reject) => {
transporter2.sendMail(mailOptions2, (err, infos) => {
if(err) reject(err)
console.log('Mail sent %s', info.messageId);
console.info('Preview URL: %s', nodeMailer2.getTest(info));
resolve(infos)
});
});
sendMailPromises.push(promise);
// this is after (and outside) the for loop.
Promise.all(sendMailPromises)
.then(() => {
res.render(mailOptions, {msg2: '...'})
}).catch((err) => {
console.error(err);
})