In this article, we will discuss how to send email in node and express applications using Nodemailer. Nodemailer is a module for NodeJS that eases the process of sending mail from your node application.
You can learn more about nodemailer here.
We will follow these steps:
Setting up the project
Configuring server.js and nodemailer
Creating ejs form for mail
Sending mail with nodemailer
Open the terminal window and create a project directory.
mkdir sendmail
Then, navigate to the directory.
cd sendmail
Now, initialize npm in it.
npm init -y
Let’s install the npm modules we will need to build the application.
We are installing:
Express (framework to design server)
ejs (template engine to serve static files)
nodemailer (module used to send mail)
npm i -S express ejs nodemailer
Let’s install another npm module named nodemon which automatically restarts our node application whenever we make changes to it, so we don’t need to do it manually again. It will make our work easier to save. (–save-dev flag is passed to install it only as a dev dependency).
npm i nodemon --save-dev
Now, we will set up server.js (our main server file).
Create server.js file, open it in your editor and write down the following code (explanation given below).
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
const express = require('express');
const app = express();
const nodemailer = require("nodemailer");
/*------------------SMTP Section Start-----------------------------*/
const smtp = nodemailer.createTransport({
service: "gmail",
host: "smtp.gmail.com",
auth: {
user: "Your gmail",
pass: `app password`
}
});
/*------------------SMTP Section Over-----------------------------*/
// setting server to use ejs template view engine
app.set("view engine", "ejs");
// parse requests of content-type - application/json
app.use(express.json());
// parse requests of content-type - application/x-www-form-urlencoded
app.use(express.urlencoded({
extended: true
}));
/*------------------Routing Section ------------------------*/
app.get('/', function (req, res) {
res.render('index');
});
/*--------------------Routing Section Over----------------------------*/
// setting server to listen at port 8080
app.listen(8080, function () {
console.log(" Server is live on port 8080 !!!");
});
Here we are setting up nodemailer in the SMTP section; it consists of various fields.
Service (name of SMTP service we are using, in this case Gmail)
Host (your SMTP service host, for Gmail it is smtp.gmail.com)
Auth object which consists of your mail-address and Gmail app password
Note that Gmail app password is not the same as your Google account password, for details see how to acquire app password.
Then we have told our server to use ejs template engine with
app.set("view engine","ejs");
If you are not familiar with ejs, see this.
The next two lines are to make sure our server parses json and x-www-form-urlencoded data correctly.
Next we have set up our route so it renders index.ejs file in the views directory when we open http://localhost:8080/ in our browser.
Lastly, code app.listens sets up the server to listen at localhost:8080.
Open a new terminal window and run server.
nodemon server.js
Now we will create a mail form.
Create index.ejs in views directory, open it in your code editor, and write down the following code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
<html>
<head>
<title>Node.JS Email application</title>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<!-- CSS link (loading Semantic UI from a CDN) -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/semantic-ui/2.4.1/semantic.min.css" integrity="sha512-8bHTC73gkZ7rZ7vpqUQThUDhqcNFyYi2xgDgPDHc+GXVGHXq+xPjynxIopALmOPqzo9JZj0k6OqqewdGO3EsrQ==" crossorigin="anonymous" referrerpolicy="no-referrer" />
<script>
$(document).ready(function(){
var from,to,subject,text;
function isEmail(email) {
var regex = /^([a-zA-Z0-9_.+-])+\@(([a-zA-Z0-9-])+\.)+([a-zA-Z0-9]{2,4})+$/;
return regex.test(email);
};
$("#send_email").click(function(){
to=$("#to").val();
if(!isEmail(to)){
$("#message").empty().html("Invalid email");
}
else{
subject=$("#subject").val();
text=$("#content").val();
$("#message").text("Sending e-mail...Please wait");
$.post("http://localhost:8080/send",{to:to,subject:subject,text:text},function(data){
if(data=="sent")
{
$("#message").empty().html("Email has been sent at "+to+" . Please check inbox!");
}
});
}
});
});
</script>
</head>
<body>
<div id="ui segment">
<h1>
Node.JS Email application
</h1>
<div class="ui segment form">
<div class="field">
<label>To</label>
<input id="to" type="text" placeholder="Enter E-mail ID where you want to send" />
</div>
<div class="field">
<label>Subject</label>
<input id="subject" type="text" placeholder="Write Subject" />
</div>
<div class="field">
<label>Text</label>
<textarea id="content" placeholder="Write what you want to send"></textarea>
</div>
<button class="ui button" type="submit" id="send_email">Send Email</button>
<span id="message"></span>
</div>
</div>
</body>
</html>
In this file we have created a simple form using semantic UI. We are using jquery to send form data (email data) after validation of email with regex expression to localhost:8080/send, which we will define later, and will process our data and send our mail.
You can view the form in the browser by visiting localhost:8080. You will see this webpage:
Now let’s define our express route where we will receive data and process it to send mail.
Open server.js and modify it as
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
const express = require('express');
const app = express();
const nodemailer = require("nodemailer");
const smtp = nodemailer.createTransport({
service: "gmail",
host: "smtp.gmail.com",
auth: {
user: "421kamlendra@gmail.com",
pass: `plrremgjravkanvq`
}
});
/*------------------SMTP Over-----------------------------*/
app.set("view engine", "ejs");
// parse requests of content-type - application/json
app.use(express.json());
// parse requests of content-type - application/x-www-form-urlencoded
app.use(express.urlencoded({
extended: true
}));
/*------------------Routing Started ------------------------*/
app.get('/', function (req, res) {
res.render('index');
});
//function for email validation//
function isEmail(email) {
var regex = /^([a-zA-Z0-9_.+-])+\@(([a-zA-Z0-9-])+\.)+([a-zA-Z0-9]{2,4})+$/;
return regex.test(email);
};
app.post('/send', function (req, res) {
var mailOptions = {
to: req.body.to,
subject: req.body.subject,
text: req.body.text
}
if (!isEmail(mailOptions.to)) {
res.status(401)
.send({
message: "Invalid Email"
});
}
console.log(mailOptions);
smtp.sendMail(mailOptions, function (error, response) {
if (error) {
console.log(error);
res.end("error");
} else {
console.log("Email sent ");
res.end("sent");
}
});
});
/*--------------------Routing Over----------------------------*/
app.listen(8080, function () {
console.log("Express Started on Port 8080");
});
Here we have defined an email function to check for validation and then a /send route which listens to post requests. Then we are sending mail using nodemailer with body object acquired from request and then destructured as it is required. Validation is done for email and an error message is sent if it is not valid, otherwise the mail is sent.
You can check if the application is working or not by visiting localhost:8080 in the browser and sending mail. You must see sending mail…… followed by the message sent check your email message
Sending mail with nodemailer is that simple.
Gmail is the fastest way to get started but not preferable without Oauth because of the following reasons.
As mentioned in the article above if you have 2FA enabled then you need an application-specific password to work with nodemailer.
You might run into trouble if your server is in a separate location, the application may run fine on a local machine but won’t work in production.
Google has very strict security restrictions so it might block the login attempt with a simple string password thinking it was performed by a robot, not the actual user.
Gmail also has a concept of ‘Less Secure’ apps which is when one uses a plaintext password to login it will allow messages when less secure is enabled and will block where it is disabled, which also sometimes causes ruckus.
You can avoid these issues using Oauth for authentication instead of sending a password in plaintext.