loading...
Cover image for Setting up a site mailer with node mailer, express and Gmail
ITNEXT

Setting up a site mailer with node mailer, express and Gmail

tallangroberg profile image Tallan Groberg Updated on 惻7 min read

photo from https://stories.wf.com/pony-express-riders-young-fast-fearless/

In this tutorial, we are going to be setting up a site mailer.

I think where a lot of devs go wrong with site mailers is trying to make one for an application instead of making a mailing service that thier application can use.

That's why in this tutorial we are going to set up a site mailer that can be used by any application.

This means that the contact form for your portfolio can also be used as the feedback form for your projects.

Once you have one of these set up you can do amazing things with your website, such as sending payment receipts to a user's email and informing a blogger of new followers.

What does this tutorial teach?

We are going to set up a contact form that sends what users enter into a form to a specific email using express, node mailer, react as a basic front end.

Why use react?

You can do the major functionality of this app without a front end framework. React is only going to be the form handling portion but it does provide the ability to scale if you want to do something more complex with a site mailer.

prerequisite software

1.node.js this is a must for every javascript related thing that happens outside a browser.

2.create-react-app you can only do the back end functionality without this but because this is going to help you to do more robust things with this tutorial, we are using it.

3.vscode you can use any text editor you want but I will be using vscode, this means it will be easiest to follow if you are too.

4.git cli for keeping versions and changes.

Prerequisite knowledge

  1. basic javascript.

  2. curiosity about express and node.js

  3. how to install npm packages on the command line.

(optional) bash commandline

getting started

go to the directory where you keep your projects and begin by making a new folder, called mail-service

mkdir mail-service

cd into the directory

cd mail-service

make a new npm project by initializing a package.json

npm init -y

the -y means we want to create this without asking questions.

Open the project.

code .

In the package.json we have the basic setup. Let's install the npm packages.

npm i express morgan dotenv nodemailer

express is a minimal framework for setting up server-side applications.

morgan is an http request logger, this will allow us to see the status of our request without making a function

dotenv is a package to save environment wide variables keeping sensitive information off of github. we will use it to hide emails and passwords.

node-mailer this is all the helper methods to make our service send emails.

Make a server.js file to house our server

touch server.js

at the top add the back-end imports.

const express = require('express')
const app = express()
require('dotenv').config()
const morgan = require('morgan')
const nodemailer = require('nodemailer')
const port = 4444

at the bottom add the app.listen to give our back end a definite port.

app.listen(port, () => {
  console.log(`app is live on ${port}`)
})

in the middle of those, make our app use morgan so that we get a better idea of how our app is behaving.

app.use(morgan('dev'))

Now have our app use express.json() to make sure everything gets to our backend in proper type.

app.use(express.json())

Start the app on the commandline.

nodemon server

If everything went right and you have all the packages installed, you should have a file and terminal looking like this.

Alt Text

Now we want to add git, for brevity I won't do this in writing.

The outline of this app goes like this.

Make one working route to send an email, make a frontend to use that route with a form.

Let's start by making a folder.

mkdir routes

Right click the routes folder we will make a sendToMe.js

Alt Text

Alt Text

Add express and nodemailer to this file like so.

const express = require('express')
const sendToMeRouter = express.Router()
const nodemailer = require('nodemailer')

Add a console.log to that file so that we can make sure we are reaching the file from the server.js

console.log("from sendToMe")

sendToMe.js

export the Router() at the bottom of the file.

module.exports = sendToMeRouter

in the server.js have the app use that route file like this.

app.use('/sendtome', require('./routes/sendToMe'))

turn the server back on and see if the console.log shows up.

nodemon server

Now we can build out the mailer's functionality.

To do this we need to make an email address that this will use.

With Gmail, you have to use the turn on less secure apps to do this.

You can use an email you already have but please be careful not to publish your password.

Now, in your google account home, in the top left corner, go to security.

Alt Text

Scroll down until you reach less secure apps.

Alt Text

The alternative to this is figuring out how to enable your site to use Oauth in your app, that will just be another thing.

Alt Text

You should receive an email shortly from google saying that you enabled less secure apps.

Make a .env file

touch .env

Now we need to add the email and password to the .env file and app wide variable.

THE_EMAIL="super secret dont show anyone!!!"

THE_PASSWORD="super secret dont show anyone!!!"

.env

We are set up to make the transport object and the mailing functions in the sendToMe.js file.

const transport = {
  //all of the configuration for making a site send an email.

  host: 'smtp.gmail.com',
  port: 587,
  secure: false,
  auth: {
    user: process.env.THE_EMAIL,
    pass: process.env.THE_PASSWORD
  }
};

Now make the transporter function

const transporter = nodemailer.createTransport(transport);
  transporter.verify((error, success) => {
    if(error) {
      //if error happened code ends here
      console.error(error)
    } else {
      //this means success
      console.log('users ready to mail myself')
    }
  });

Let's add another function to make this work on a post request.

sendToMeRouter.post('/', (req,res, next) => {
    //make mailable object
    const mail = {
      from: process.env.THE_EMAIL,
      to: 'tallan.taven@gmail.com',
      subject: req.body.subject,
      text: `
      from:
      ${req.body.name} 

      contact: ${req.body.email}

      message: 

      ${req.body.text}`
    }
// error handling goes here. 
  });

finish with some error handling.

transporter.sendMail(mail, (err,data) => {
      if(err) {
        res.json({
          status: 'fail'
        })
      } else {
        res.json({
          status: 'success'
        })
      }
    })

//still inside the .post request the next line should be });

You can test this in post man but remember that you have to have text, email, name, and subject defined in order to get this to work and enable cors app wide.

Ok now we get to my favorite part, the react app.

While still inside the project directory on the command line create-react-app

create-react-app client

Go to the package.json and connect the express app to the react app with a proxy like so.

//dont forget to add the comma after the curly bracket because it's json.
},
  "proxy": "http://localhost:4444/"

You will need to run the back and the front end at the same time.

on the back end

nodemon server

On in the client folder.

cd client && npm start

This should take you to the ordinary boiler-plate react.

Let's add axios to the client folder.

in client directory on the command-line

cd client && npm i axios

Remove all the code between the div tags.

Your app function should look like this.

function App() {
  return (
    <div className="App">

    </div>
  );
}

Now make a form with 3 inputs and a textarea

<form>
        <input type="text" placeholder="" name="" value={} onChange={} />
        <input type="text" placeholder="" name="" value={} onChange={} />
        <input type="text" placeholder="" name="" value={} onChange={} />
        <textarea name="" id="" cols="30" rows="10"></textarea>
      </form>

Dont panic! Our app will run again when we fill in the value and onChange attributes

We will have the useState hooks keep the string for us.

We need to import axios.

At the top.

import React, {useState} from 'react';
import axios from 'axios'

Inside the app function.

 const [inputs, setInputs] = useState({email: '', name: '', subject: '', description: ''})

Now to make the handleChange and the handleSubmit's

const handleChange = e => {
    const {name, value} = e.target
    setInputs(prev => ({...prev, [name]: value }))
  }
  const handleSubmit = e => {
    e.preventDefault()
    // post request goes here. 
  }

Add the place holders, name, value and onChange attributes so that our app isn't crashed anymore, add the onSubmit action to the form and a button. I've also added br tags.

<h1>feed back form. </h1>
      <form onSubmit={handleSubmit}>
        <input type="text" placeholder="email" name="email" value={inputs.email} onChange={handleChange} />
        <br />
        <input type="text" placeholder="name" name="name" value={inputs.name} onChange={handleChange} />
        <br />
        <input type="text" placeholder="subject" name="subject" value={inputs.subject} onChange={handleChange} />
        <br />
        <textarea name="description" placeholder="tell us about your experience" value={inputs.description} onChange={handleChange} cols="30" rows="10"></textarea>
<br />
        <button>submit</button>
      </form>

It's time for us to add the axios post request to /sendtome route inside the handleSubmit and configure the object so that everything is received properly.

The new handleSubmit will look like this.

const handleSubmit = e => {
    e.preventDefault()
    //destructure from inputs 
    const {email,name,subject,description} = inputs
    axios.post('/sendtome', {
      //make an object to be handled from req.body on the backend. 
      email,
      name,
      subject,
      //change the name to represent text on the backend.
      text: description
    }) 
  }

Let's give it a try.

If you copied and pasted all the code snippets it will work.

There you have it.

I'll be doing one on how to set up mailschimp to start your own news letter which gives much more beautiful emails than the plain text one you see here.

If you know anyone that this could help or just want to support me as a fellow tech enthusiast, please share and follow my posts.

Posted on by:

tallangroberg profile

Tallan Groberg

@tallangroberg

I love to write, I love all things tech I recently published a novel.

ITNEXT

ITNEXT is a platform for software developers, engineers, IT architects, system engineers and IT enthousiasts to share knowledge, connect and connect.

Discussion

markdown guide
 
 

Thanks!!

Iā€™m glad you got it working without any problems!!!

 
 

You are welcome not a problem, I love sharing what I do.