Sending emails from a Node.js Application (and deploy it to Apache)

Sending emails from a Node.js Application (and deploy it to Apache)

This article assumes you have Node.js up and running in your development computer. If not report to Installing Node.js via package manager as this is the easiest way to do it for various platforms.

In a terminal create your project folder by

mkdir myproject && cd myproject

Then create your package.json by

npm init -y

(the above flag -y skips all the questions)

For the purpose of sending emails we'll be using Express and NodeMailer which you can install by entering the following command in the terminal of your project folder. We'll also have to deal with parsing the request's body and further along the way with cors so we'll install four packages at once.

npm i express nodemailer body-parser cors

Fire up your favorite IDE/Text editor and create a app.js file in the project folder.

A barebone's express application would resemble the following:

var express = require('express');
var app = express();

const port = 3000;

app.get('/', function (req, res) {
  res.send('Hello World!');
});

app.listen(port, function () {
  console.log(`🚀 Server ready at http://localhost:${port}`);
});

You can check if it's running by issuing the following command at the terminal:

node app.js

Time to create the route and the transport for dealing with sending emails (in this case we're using the default SMTP transport for Gmail) so app.js becomes the following:

import express from "express";
import nodeMailer from 'nodemailer';
import bodyParser from 'body-parser';

const app = express();

const port = 3000;

app.use(bodyParser.urlencoded({extended: true}));
app.use(bodyParser.json());
app.post('/send-email', function (req, res) {
  let transporter = nodeMailer.createTransport({
      host: 'smtp.gmail.com',
      port: 465,
      secure: true,
      auth: {
          user: 'YOUR_USER@gmail.com',
          pass: 'YOUR_PASSWORD'
      }
  });
  let mailOptions = {
      from: '"YOU" <YOUR_USER@gmail.com>', // sender address
      to: req.body.to, // list of receivers
      subject: req.body.subject, // Subject line
      text: req.body.body, // plain text body
      html: req.body.html // html body
  };


  transporter.sendMail(mailOptions, (error, info) => {
      if (error) {
        res.sendStatus(500);
        return console.log(error);
      }
      console.log('Message %s sent: %s', info.messageId, info.response);
      res.sendStatus(200);
      });
  });


app.listen(port, function () {
  console.log(`🚀 Server ready at http://localhost:${port}`);

});

At this point we can use Postman - Download Postman - to test the implementation (just replace _RECIPIENT_ with a valid account).

Sending a POST request from Postman

At this juncture you can either send the email successfully or fall victim to one of two scenarios:

  • Gmail blocking it. You need to enable 'less secure apps" in your gmail account - Less Secure Apps
  • CORS. That's what we'll be dealing with next
Note that the following is a very insecure configuration and should only be used for development purposes!
import express from "express";
import nodeMailer from 'nodemailer';
import bodyParser from 'body-parser';
import cors from 'cors';

const app = express();

const port = 3000;

// FIXME in production!
app.use(cors({
  origin: '*',
  credentials: true,
  allowedHeaders: ['Content-Type', 'Authorization', 'Content-Length', 'X-Requested-With', 'Accept'],
  methods: ['GET', 'PUT', 'POST', 'DELETE', 'OPTIONS'],
  optionsSuccessStatus: 200 // some legacy browsers (IE11, various SmartTVs) choke on 204 
}));

app.use(bodyParser.urlencoded({extended: true}));
app.use(bodyParser.json());
app.post('/send-email', function (req, res) {
  let transporter = nodeMailer.createTransport({
      host: 'smtp.gmail.com',
      port: 465,
      secure: true,
      auth: {
          user: 'YOUR_USER@gmail.com',
          pass: 'YOUR_PASSWORD'
      }
  });
  let mailOptions = {
      from: '"YOU" <YOUR_USER@gmail.com>', // sender address
      to: req.body.to, // list of receivers
      subject: req.body.subject, // Subject line
      text: req.body.body, // plain text body
      html: req.body.html // html body
  };


  transporter.sendMail(mailOptions, (error, info) => {
      if (error) {
        res.sendStatus(500);
        return console.log(error);
      }
      console.log('Message %s sent: %s', info.messageId, info.response);
      res.sendStatus(200);
      });

  });

app.listen(port, function () {
  console.log(`🚀 Server ready at http://localhost:${port}`);

});

That should take care of it! ;)

Client side methods for sending emails:

  • via html FORM
  • via axios (you need to npm install and import it to your app)
<form action="/send-email">
...
</form>



// Axios post example


axios.post('http://localhost:3000/send-email', {
            to: _RECIPIENT_,
            subject: "My exciting subject",
            html: `<p>Hello World!</p>`
        })
        .then(res => {
            console.log('Email sent.',res);
        })
        .catch(err => {
            console.log('Failure to send email.', err);
        })

Deployment on a Apache web server

(again this assumes you've installed and configured Apache on your computer)

In this scenario we have a client companion, say, React, application, also being served by express and we wish to deploy both to Apache.

// Example on how to serve the client application under express
app.use(express.static(__dirname +'./../client/')); //serves the index.html

Our app current runs on port 3000 and we'd very much like to simply enter the URL without having to specify the port number, right? That's where Proxy comes into play:

You simply have to edit httpd.conf (check you platform's specific instructions for the location of this file) and in the <VirtualHost *:80> section write something like this:

<VirtualHost *:80>
    ServerAdmin admin@site.com
    ServerName site.com
    ServerAlias www.site.com 

    ProxyRequests off

    <Proxy *>
        Order deny,allow
        Allow from all
    </Proxy>

    <Location />
        ProxyPass http://localhost:3000/
        ProxyPassReverse http://localhost:3000/
    </Location>

  
</VirtualHost>

WARNING: Do not enable proxying with ProxyRequests until you have secured your server. Open proxy servers are dangerous both to your network and to the Internet at large. Setting ProxyRequests to Off does not disable use of the ProxyPass directive.

We'll also need to enable proxy modules on Apache (example terminal command under Ubuntu) :

sudo a2enmod proxy proxy_http

Now restart apache server and test.

Lastly we'd also like to run our app after server reboots; We can achieve that with PM2 - Installation and usage

This concludes this article. Happy coding!

Feedback from my readers is what motivates me to keep working in public. Feel free to reach out, if you'd like to stay up to date with what I'm working on or simply present your own ideas! ;)

Mine doesn't work in production, even after adding cors

To view or add a comment, sign in

More articles by Pedro Doria Meunier

Others also viewed

Explore content categories