I am sending mails using nodemailer. I need to know if the mail is sent or not and then update my database but the mail is sent in the transporter(which I do not think returns promises) which takes time and hence the return is always false, even if the mail is sent.
This is my mail sending file which I call from other routes
// mail_file.js
// imports
sendmail = async (req) => {
let transporter = nodemailer.createTransport({
// settings
});
var mailOptions = {
// mailoptions
};
let resp = false;
await transporter.sendMail(mailOptions, function (error, info) {
if (error) {
console.log('error is ' + error);
resp = false;
} else {
console.log('Email sent: ' + info.response);
resp = true;
}
});
return resp;
};
module.exports = sendmail;
When I log the info of the mail, it is after the logging of the response of the sendmail function in the somepath.js
As per the Nodemailer documentation:
All public Nodemailer methods support both callbacks and Promises (if callback is omitted). You need to have at least Node v8.0.0 if you want to use async..await with Nodemailer
An example can be found here: https://nodemailer.com/about/#example
Nodemailer v6.4.8 supports both synchronous version and asynchronous version of sendMail.sendMail(mailOptions: Mail.Options, callback: (err: Error | null, info: SentMessageInfo) => void): void; sendMail(mailOptions: Mail.Options): Promise;
This answer still helps someone who needs to understand how to promisify a function that uses callbacks. Linking an article that explains the same thing https://letsdqode.blogspot.com/2022/01/using-callbacks-with-async-await-or.html
Original Answer: transporter.sendMail does not return a promise, it uses a callback function. change your code
return new Promise((resolve,reject)=>{
let transporter = nodemailer.createTransport({
//settings
});
var mailOptions = {
//mailoptions
};
let resp=false;
transporter.sendMail(mailOptions, function(error, info){
if (error) {
console.log("error is "+error);
resolve(false); // or use rejcet(false) but then you will have to handle errors
}
else {
console.log('Email sent: ' + info.response);
resolve(true);
}
});
})
}
as I said earlier, transport.sendMail() function uses call back that's why you can not use await there.But you can write a wrapper function around it so that you can use await in your functions where you need more readble and clean code. just consider the following example
async function wrapedSendMail(mailOptions){
return new Promise((resolve,reject)=>{
let transporter = nodemailer.createTransport({//settings});
transporter.sendMail(mailOptions, function(error, info){
if (error) {
console.log("error is "+error);
resolve(false); // or use rejcet(false) but then you will have to handle errors
}
else {
console.log('Email sent: ' + info.response);
resolve(true);
}
});
}
})
Now you can use this wrappedSendMail function in your other functions like below,
sendmail= async(req)=>{
var mailOptions = {
//mailoptions
};
let resp= await wrapedSendMail(mailOptions);
// log or process resp;
return resp;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With