Nodemailer not working in production

Hello all!

I was working on a personal project for the past week and have been testing it locally using Netlify Dev. Now that it was all working, I started testing it in production, but seems like it’s not working as expected for one thing.

To provide some context, I was trying to develop my own static comments solution powered by Netlify Functions. I have added a feature where we could reply to existing comments and the creator of the original comment would be notified by email (if they had provided one while submitting the comment). I’m storing the database on FaunaDB and sending out the emails using Nodemailer and Sendinblue SMTP.

As I have said before, the local tests worked fine, I was receiving emails, the production one however, doesn’t seem to work. What’s strange to me that, it seems as if the Nodemailer is not even trying to send e-mail because in my Sendinblue dashboard, I don’t see any email being sent out (as opposed to my local tests in which I could not only see the email being sent, but also delivered and email opens were tracked too).

My Functions log returns no error, so I’m not sure what’s happening.

Here’s my repo if someone wants to test: https://github.com/Hrishikesh-K/Comments

You’d need some environment variables to test and since I can’t expect anyone to have or create accounts on FaunaDB and Sendinblue to help me, I’m giving out access to test keys which I will delete once the thread is solved.

FAUNADB = fnAEHKkAkmACBfKxAaCfhuNxH8UJg-2OI_NUIJe_
SENDINBLUE_USER = netlify.test@hrishikeshk.ml
SENDINBLUE_PASS = xsmtpsib-42e7ae48396b5f44d1637ea22ef603690a800a62f5b0d0972530f6e1d795c6cb-ND8tXMpsCHxyOKq1
SENDINBLUE_SENDER = "Foo Bar <foo@bar.com>"

Save the above text in a .env file in the root of the project folder (while testing locally), or save it as environment variables in Netlify UI.

Here’s the link to the website: https://comments-test.netlify.app/#296298668511724039

In case it’s needed, the function responsible for sending comments is here: https://github.com/Hrishikesh-K/Comments/blob/main/functions/addComment.js#L93-L105. The code above that is fetching the database entry with the required ID and getting the email address from that.

Any help will be appreciated.

Hey there, @hrishikesh :wave:

Thanks so much for your patience here, and my apologies for the delay. I assure you we haven’t forgotten about this question! I’ve looped in some Support Engineers who will be able to give you some more guidance :slight_smile:

Hey @hrishikesh!
Finally got a chance to dive into this. I forked your repo and added a bunch of logs: GitHub - kaganjd/Comments. I think I may have found, if not THE culprit, then A culprit. Here’s some output from the function logs (with my email changed):

submittedData: [
  'name=howdy+v3',
  'email=hello%40randomemail.com',
  'parent=null', <------ this seems incorrect/unexpected
  'comment=test'
]
...
commentData: {
  ref: Ref(Collection("commentsTest"), "298340475185660422"),
  ts: 1620778498810000,
  data: {
    comment: '<p>test</p>',
    email: 'hello@randomemail.com',
    parent: 'null', <------ this seems incorrect/unexpected
    name: 'howdy v3'
  }
}

Because parent is null, I believe this code path is never taken: Comments/addComment.js at main · kaganjd/Comments · GitHub

What do you think?

Thank you very much for looking at this, but I believe it’s not the cause. E-mail notifications would be triggered when someone has replied to a previous existing comment, which would mean, the value of parent is not null. The value of parent is the ref of the ‘parent comment’. For testing purposes, you can try keeping it not null, any random +ve integer would do. Basically, my code is checking if the parent could be parsed an an integer. If yes, it means that the comment has a parent. So, I go ahead and check if the email contains @ which is a requirement for any valid email address and if yes, I send the notification.

Gotcha, thanks! Digging back into this and being sure to reply to an existing comment instead of create a fresh comment, I’m seeing that I can log within the if statement, but not after the then statement:

...
        if (parseInt(commentData.data.parent)) {
          // Get the document with parent's ID
          console.log("inside parseInt"); <--- this is logged in the function logs
          commentsDB
            .query(
              faunaDB.query.Get(
                faunaDB.query.Ref(
                  faunaDB.query.Collection(title),
                  commentData.data.parent
                )
              )
            )
            .then((parentData) => {
              // Save the name
              const receiverName = parentData.data.name;
              console.log("receiverName:", receiverName); <---- this is not

You might try putting that initial query within a try/catch statement to see if you can surface the error.

It’s done! Finally fixed! :netliconfetti:

TL;DR: I gave up on nodemailer and used emailjs instead.


@jen, when you pointed out the part in your reply, I kind of felt stupid. I had just recently fixed the same error in another part of my code, basically I had to add return before the code for it to be executed correctly. For example: commentsDB.query(faunaDB.query...) would become return commentsDB.query(faunaDB.query...). So, I was kinda optimistic and hurriedly published this commit only to find out that it still didn’t work only on production. I was getting the statement in the functions log that you mentioned you were not getting. I added another debug statement inside the condition which checks for the presence of @ and that worked too. However, the next log statement that was supposed to be logged after the mail was sent, never logged in production. No matter what I did. Everything was smooth as butter in local even now.

I was going to give up on that, but then I searched more articles and stuff, none really helped. I’m still not sure if it was me or nodemailer (or Netlify :stuck_out_tongue_winking_eye:), but the emails were not being sent. So, I finally decided to try using another tool to send the mails. After searching and reading about a few, I landed on emailjs. On the surface it seemed the same, and after some trial and error I could finally get it to work.

Here’s my updated code:

// ... previous code with nodemailer swapped for emailjs

// Store the sender as a constant
const sender = process.env.SENDINBLUE_SENDER

// Send the email
return new SMTPClient({
  port: 587,
  tls: true,
  host: 'smtp-relay.sendinblue.com',
  user: process.env.SENDINBLUE_USER,
  password: process.env.SENDINBLUE_PASS
}).sendAsync({
  from: sender,
  subject: 'New reply to your comment',
  to: receiverName + ' <' + receiverEmail + '>',
  text: 'email body',
}).then(() => {

  // Return the data of the comment for client-side processing
  return {
    statusCode: 200,
    body: JSON.stringify(commentData),
    headers: {
      'cache-control': 'public, max-age=0, must-revalidate'
    }
  }
  
})

Check in the repo here: OpinionJS/addComment.js at main · Hrishikesh-K/OpinionJS · GitHub. This is a different repo than the one I used in my opening post because I made many changes in these 20 days and merging them back to the old repo would have been a problem.

I really appreciate for taking the time @jen. Because, I had almost given up on this 20 days ago itself when I had posted the question here and more when I didn’t receive any response. After your reply, I got some optimism to give this another try and I’m happy it’s finally working. Hope this helps someone else too.

3 Likes

So glad you kept working on this fantastic project and that it’s working now :partying_face::partying_face::partying_face:Was a huge help that you created the test keys.

To others reading: please note that we generally do not and cannot provide this level of support in the forum- adding logs to custom code is well beyond the scope of our support. Hrishikesh is an exception to this rule because he’s a tremendous contributor who has helped tons of people here, so we are happy to fork, clone, log, whatever!

2 Likes

Also! If you decide to open source the repo and/or write a blog post about this, let us know and I’ll see if we can promote it somehow.

Yes, it’s indeed an open source project. I am publishing it as a Node Module too and also creating a Netlify Build Plugin to easily copy and deploy the functions. I’ve got promising results in most of the tests and was just able to overcome another limitation (discussed here).

I’m currently writing the documentation. The repo is here: https://www.github.com/Hrishikesh-K/OpinionJS/ and the documentation is here: https://opinionjs.netlify.app/. If someone does come across this as of now, don’t use it just yet. I’m constantly changing something, and more importantly, even the name is not finalized. So, a lot of breaking changes are expected. But if someone is willing to test and suggest changes, go ahead. I’d love to improve this thing as I think it might help many people solve a major problem on their static websites.

1 Like