Ninja Space Content Tech Blog

Working with Nodemailer and Express to create a Contact Us form

Posted by Ninja Space Content on Thursday, December 31, 2020 Under: nodemailer
For the last 24 hours, I have been working on my Contact Us form and I have it up and running now. However, no surprise here, I didn't do it without some errors at the beginning. I found some sources that I want to document here to look back on for the future for the next Nodemailer implementation.

Here are the three resources on Nodemailer that I looked at:

I used Express and Node for my server, and React for my front end. If you're like me, I like to take a good amount of time to research and then when I feel comfortable enough with the big picture of everything, I'll start typing code.

I found that the three resources at the top were very helpful. The first two links use gmail as an example, which is what I am using for my Contact Us form that I've been working on, and the same tech stack: Express, Node and React. The last link listed above is Nodemailer's official doc, which I highly recommend reading first. 

The main problem I ran into on the server side involved my gmail credentials. This was the error message that I received in my terminal: "Error: Invalid login: 535-5.7.8 Username and Password not accepted."

There were two main issues that I needed to fix at this point. First, I mistyped my password and finally, I needed to go into my Google account settings to turn on the following: Allow less secure apps

(More info on Allow less secure apps access from Google directly: "Some apps and devices use less secure sign-in technology, which makes your account vulnerable. You can turn off access for these apps, which we recommend, or turn it on if you want to use them despite the risks. Google will automatically turn this setting OFF if it’s not being used.")

So, you'll want to go to your Google account, then Settings, then turn ON the Allow less secure apps part. This will allow the Contact Us form to work and send information from the form to the particular gmail account.

After correcting my password and turning on the Allow less secure apps toggle, I was finally able to receive messages from my Contact Us form locally while developing.

Also, I want to note that I put my email username and password in a .env file and used a dotenv library via Node to hide my personal information so make sure we all do that to all of our important proprietary information before we push anything to our Github repository! 

The first place that I deployed the app was on Heroku for this new project as I've used the hidden variables for JWT token and API Keys with Heroku in the past during my coding bootcamp cohort program and feel comfortable with it. Then, I started getting curious about getting a domain for it and purchased the domain: and to my surprise, the company gave me a free shared hosting plan for a year so I decided to utilize it. It's live on the domain now and here's the Contact Us form where I utilized Nodemailer: Since my shared hosting plan does not support Node.js, I had to improvise a bit and edit my code so that it calls to my Heroku URL for the Contact form part. I'm using a free Heroku plan so it does go to sleep and to wake up, it takes 30 seconds and most likely it will take you that long to send the form but I'm satisfied with it for now.

After everything was up and running, I git init and pushed my code to GitHub, but then when I deployed to Heroku, the Contact Us form doesn't work, saying there was an error connection. Exact message was: POST http://localhost:4000/send net::ERR_CONNECTION_REFUSED in my console. Things I had to add to get my Contact Us form to work on Heroku:
  • Add "proxy": "http://localhost:4000", to my package json
  • Make sure I have all of the following scripts. I was missing "node index.js". Example: "scripts": { "start:client": "react-scripts start", "start": "node index.js", "start:dev": "nodemon index.js", "build": "react-scripts build" }
  • Add path join like so: const path = require('path'); server.use(express.static(path.join(__dirname, 'build'))); server.use((req, res, next) => { res.sendFile(path.join(__dirname, 'build', 'index.html')) });
And then it fixed my problem.

I kept having Nodemailer problems on Heroku using my google gmail account so after googling, I discovered that you'll need to double check to make sure you have Allow less secure apps accessing turned ON again for your Google gmail account that you listed for your Nodemailer because it goes back to turning it off again if it's not used after awhile! If that doesn't work, additionally, click on this link: and check to see if it'll help. I also noticed that if I leave my computer for 30 minutes and come back to try the form again, I'd have to do the Unlock Captcha link again for my google account for it to work on deployment again. It was pretty frustrating. I felt like I needed to find a more permanent solution so I tried to use one of my Godaddy hosting email accounts but I keep getting this error: 

code: 'EMESSAGE',
response: '550 <> Sender Rejected - MAILFROM must be a valid domain. Ensure the mailfrom domain: ""  has a valid MX or A record.',
responseCode: 550,

My code looked like the following: 
service: 'Godaddy',
host: "",  
secureConnection: true,
port: 465,
auth: { user: EMAIL, pass: PASSWORD, },

Another Attempted Solution: 
My CNAME for smpt originally was: CNAME   smtp

I thought that I needed to set the CNAME to point to so I changed that and checked back in an hour. It still wasn't working so I created an MX file with these values:

Points to
Priority 1
TTL 1/2 Hour

It still didn't get my Nodemailer to send so I decided to throw in the towel and just use gmail. I'd just always have to make sure the Allow less secured apps is turned ON via my Google account every once in awhile and check the captcha if I wanted to use it or demo it to someone. 

Then, after hours on StackOverflow, I found a more permanent solution. I reverted my Google account back to 2-Step Verification and when it did this, the account allowed me to create app passwords! All I had to do was create an app password and use this app password as the password for the Nodemailer, instead of my main password. This was a win-win situation! Now, I don't have to do the annoying captcha link anymore for my Google account to use the Contact Us form. Here's how my code looks: 

const contactEmail = nodemailer.createTransport({ host: '', port: 587, secure: false, auth: { user: EMAIL, pass: PASSWORD, }, });

And in my .env, the PASSWORD is the app password I generated. Now, it works like a charm. 

So after a couple of months, I wanted to dabble into AWS and get something deployed on there. I've successfully gotten this PrettyScouts app to deploy on AWS Amplify. It was so easy. Read the steps that I took to get this React App deployed on AWS Amplify in this blog entry.

I originally had a Nodemailer issue on AWS Amplify but found that I had to do the same tweak that I did for my Godaddy shared hosting account because AWS Amplify is server-less and I just simply had to change the code to do an API call to my Heroku link. This was a really great way for me to do a comparison on deployment to test between deploying on Godaddy's shared hosting account and AWS Amplify. I'm definitely gravitating towards AWS Amplify.

Here are the two deployed links of the same React app, utilizing Godaddy Shared Hosting and AWS Amplify:
Deployed on Godaddy Shared Hosting using custom domain:
Deployed on AWS Amplify:

In : nodemailer 

Tags: nodemailer  using gmail account  errors  documentation  express  react 

About Ninja Space Content

Ninja Space Content I have been building simple websites on my own since 2008 and currently run several websites at the moment, including this one. I used to be an account manager for an affiliate/e-commerce company, helping affiliates grow their sales so I have some knowledge on the business side and client side of affiliate marketing. Most recently, I decided to complete a JavaScript coding bootcamp and graduated in Dec 2020.
Note: links to resources and promoting special deals may allow me to earn a small commission from each sale.