Before diving into more details, let me explain my current situation. I am utilizing node's nodemailer to facilitate the process of sending emails based on the information submitted through a form. Initially, everything was functioning smoothly when there was only one recipient and one HTML body, which were sent together. However, I encountered an issue when I introduced mailOptions2
within a for
loop to enable sending emails with recipients and HTML bodies stored in separate arrays. Despite the emails and HTML content being sent, they were not aligned as intended. Additionally, upon form submission, the /send
state kept loading indefinitely, eventually displaying the raw HTML of the page without any CSS applied. The error message I received was as follows:
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)
Despite encountering similar posts about this error, I struggled to find a resolution that matched my specific scenario, mainly due to my limited experience as a beginner.
Node.js Configuration:
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', '<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="b3cbcac9f3d4ded2dadf9dd0dcde">[email protected]</a>'];
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: '<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="7d0504073d1a101c1411531e1210">[email protected]</a>', // 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" <<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="9ee6e7e4def7f0f8f1b0fdf1f3">[email protected]</a>>', // 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'});
});
}
});
Essentially, using a for
loop for mailOptions2
to assign distinct values to specific areas caused the aforementioned issues. If I had avoided this approach, the functionality would have operated without any complications.
Below is the structure of the relevant files for your reference:
server.js
services.html
public
css
styles.css