Search code examples
node.jsexpressnodemailer

Error handling not working for Nodemailer in Express


I have a function to read mails using nodemailer:MailRead.js

exports.sendMailService = async (mailOptions) => {
    return new Promise((resolve, reject) => {
        mailOptions.from = 'someemail@some.com'
        const transporter = nodemailer.createTransport({
            service: some,
            auth: {
                user: 'somemail@some.com',
                pass: 'password'
            }
        });
        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);
            }
        });
    })
}

When I'm calling this function in a controller :sendController.js

exports.sendMail = async (req, res, next) => {
    const mailBody = req.body
    try{
        await sendMailService(mailOptions)
        //if I do this:
        //const mailSent = await sendMailService(mailOptions)
        //if every credential is correct it mailSent displays true if not credentials false it gives 
        //false
        //but I want to handle error not just check for condition.
    }catch (err){ //not coming to catch part
        next(ApiError.badClientError('Bad Credentials')); //some function to handle error
            return;
    }
};

When an api is call : above function is triggered :

Apisample:

api.post('sendmail',sendMail);

Also I tried this SO: but I don't think its working for me.

So is there any suggestion on false credentials it should go to catch statement?


Solution

  • Your sendMail() function is assuming that a failed call to sendMailService() will reject the promise it returns. But, upon error, your sendMailService() function calls resolve(false), not reject(someError). Thus, your await sendMailService() never throws and you never get to your catch block.

    If instead, you reject upon error, it will then get to your catch block:

    exports.sendMailService = async (mailOptions) => {
        return new Promise((resolve, reject) => {
            mailOptions.from = 'someemail@some.com'
            const transporter = nodemailer.createTransport({
                service: some,
                auth: {
                    user: 'somemail@some.com',
                    pass: 'password'
                }
            });
            transporter.sendMail(mailOptions, function (error, info) {
                if (error) {
                    console.log("error is ", error);
                    // reject the returned promise with the error
                    reject(error);
                } else {
                    console.log('Email sent: ' + info.response);
                    resolve(true);
                }
            });
        })
    }