1

I am trying to send an email based on the entries inside a database using nodemailer. I have tried practically anything I can think of (manually creating an array of Promises and using that in a call of Promise.all(), doing that using a map, etc.), but I always keep getting the same error: UnhandledPromiseRejectionWarning: Error: Message failed: 450 SQLITE_ERROR: cannot start a transaction within a transaction. The nodemailer-documentation clearly states that -- when not passing a callback-fn, the transporter.sendMail()-function is wrapped as a promise. However, when I am manually defining an array of those promises like so...

const transporter = nodemailer.createTransport(serverData);
const mailData = ...;

const arr = [transporter.sendMail(mailData), transporter.sendMail(mailData)];

... the same error already fires even though I have not even 'ran' through that array using Promise.all(); is it a misconception that the functions in the array will only run when I manually specify?

Anyhow, this is my complete code for the database; I am using sequelize to retrieve the data from the database. I have verified that there are no problems on the retrieving-data-from-the-db-side of this task.

class Mail extends Model {
...

  static resendUndeliveredMails(){
    this.findAll()
        .then((mails) => {
          return Promise.all(mails.map(async mail => {
             transporter.sendMail(mail.dataValues);
          }));
        })
        .catch((e) => {
          console.log(e);
        });
  }
}

Any help would be greatly appreciated! Thank you in advance :).

ovda96
  • 61
  • 1
  • 8

1 Answers1

1

I have tested nodeMailer API with promise.all and I did not found any problem with it this is the code I used below, and another thing the error you are getting is I think related to equalizer or SQL cause the error you are getting is being thrown by SQLITE_ERROR UnhandledPromiseRejectionWarning: Error: Message failed: 450 SQLITE_ERROR: cannot start a transaction within a transaction, and another thing the way you are writing async inside the promise all I think is wrong I will share with you here the way you should write the function, but about your fist question about the promises firing before you run promise.all that's all when you create an Array-like this [promise(arg)] you are calling the function at that moment so the promise will start and node will handle it even if you don't put it inside of promise.all

 static async resendUndeliveredMails() {
try {
  const mails = await findAll();
  const mailerPromises = mails.map((mail) => transporter.sendMail(mail.dataValues));
  const responses = await Promise.all(mailerPromises);
  console.log(responses, "All Mails Have Been Sent Successfully");
} catch (e) {
  console.log(e);
}

}

const nodemailer = require("nodemailer");

const transporter = nodemailer.createTransport({
  service: "gmail",
  auth: {
    user: "user",
    pass: "pass", // naturally, replace both with your real credentials or an application-specific password
  },
});

const mailOptions = {
  from: "user@gmail.com",
  to: "test@gmail.com",
  subject: "testing due",
  text: "Dudes, we really need your money.",
};

const mailOptions2 = {
  from: "user@gmail.com",
  to: "test1@gmail.com",
  subject: "LOL due",
  text: "Dudes, we really need your money.",
};

Promise.all([
  transporter.sendMail(mailOptions),
  transporter.sendMail(mailOptions2),
])
  .then((res) => console.log(res))
  .catch((err) => console.log(err));
Chamsddine Bouzaine
  • 1,299
  • 10
  • 17
  • Thank you for your answer! This clarifies on what I am (still) doing wrong with promises! I decided to take another approach using the `reduce`-function, see also https://stackoverflow.com/a/21372567/10964093 . Thank you again! – ovda96 Oct 18 '20 at 13:28