How to verify user email in node.js ?
CyberWolves
Posted on May 10, 2021
Email verification is crucial feature for every website. It will help us from spam users. It is my first blog, i will try my level best. So let's start coding.
App overview :
project structure
The following table shows overview of the Rest APIs that be exported:
Methods | Urls | Actions |
---|---|---|
POST | api/user/ | create user and send email |
GET | api/user/verify/:id/:token | verify link sent by email |
Create Node.js App
first, we create a folder :
$ mkdir node-mongo-email-verify
$ cd node-mongo-email-verify
Next, we initialize the Node.js App with a package.json file:
$ npm init --yes
We need to install necessary modules: express, mongoose, nodemailer, joi and dotenv.
$ npm install express mongoose nodemailer joi dotenv
Express : Express is minimal and flexible Node.js web applicaton framework.
Mongoose : Mongoose is an Object Data Modeling (ODM) library for MongoDB and Node.js.
Nodemailer : Nodemailer allow us to send email.
Joi : Joi is an object schema description language and validator for javascript objects.
dotenv : It loads environment variables from a .env file.
The package.json file should look like this :
{
"name": "node-mongo-email-verify",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"dependencies": {
"dotenv": "^9.0.0",
"express": "^4.17.1",
"joi": "^17.4.0",
"mongoose": "^5.12.7",
"nodemailer": "^6.6.0"
}
}
Setup Express Web Server
In the root folder, let's create new index.js file :
require("dotenv").config();
const express = require("express");
const app = express();
app.use(express.json());
const port = process.env.PORT || 8080;
app.listen(port, () => console.log(`Listening on port ${port}...`));
Now let's run the app with command: node index.js
Configure Environment Variables :
In the root folder, let's create new .env file :
DB = // mongodb url
HOST = // email host
USER = // email id
PASS = // email password
SERVICE = // email service
BASE_URL = 'http://localhost:8080/api'
Configure MongoDB database :
In the root folder, let's create new db.js file :
const mongoose = require("mongoose");
module.exports = async function connection() {
try {
const connectionParams = {
useNewUrlParser: true,
useCreateIndex: true,
useUnifiedTopology: true,
};
await mongoose.connect(process.env.DB, connectionParams);
console.log("connected to database.");
} catch (error) {
console.log(error, "could not connect to database.");
}
};
import db.js to index.js and call it :
//....
const connection = require("./db");
const express = require("express");
//.....
(async () => await connection())();
app.use(express.json());
//....
Define The Model :
In model folder, create user.js file like this :
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
const Joi = require("joi");
const userSchema = new Schema({
name: {
type: String,
min: 3,
max: 255,
required: true,
},
email: {
type: String,
required: true,
},
verified: {
type: Boolean,
default: false,
},
});
const User = mongoose.model("user", userSchema);
const validate = (user) => {
const schema = Joi.object({
name: Joi.string().min(3).max(255).required(),
email: Joi.string().email().required(),
});
return schema.validate(user);
};
module.exports = {
User,
validate,
};
In models folder create token.js file like this :
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
const tokenSchema = new Schema({
userId: {
type: Schema.Types.ObjectId,
ref: "user",
required: true,
},
token: {
type: String,
required: true,
},
});
const Token = mongoose.model("token", tokenSchema);
module.exports = Token;
Configure The Email Transporter :
In the utils folder, create email file like this :
const nodemailer = require("nodemailer");
const sendEmail = async (email, subject, text) => {
try {
const transporter = nodemailer.createTransport({
host: process.env.HOST,
service: process.env.SERVICE,
port: 587,
secure: true,
auth: {
user: process.env.USER,
pass: process.env.PASS,
},
});
await transporter.sendMail({
from: process.env.USER,
to: email,
subject: subject,
text: text,
});
console.log("email sent sucessfully");
} catch (error) {
console.log("email not sent");
console.log(error);
}
};
module.exports = sendEmail;
Define The Routes :
In the routes folder, create users.js file :
const sendEmail = require("../utils/email");
const Token = require("../models/token");
const { User, validate } = require("../models/user");
const crypto = import("crypto");
const express = require("express");
const router = express.Router();
router.post("/", async (req, res) => {
try {
const { error } = validate(req.body);
if (error) return res.status(400).send(error.details[0].message);
let user = await User.findOne({ email: req.body.email });
if (user)
return res.status(400).send("User with given email already exist!");
user = await new User({
name: req.body.name,
email: req.body.email,
}).save();
let token = await new Token({
userId: user._id,
token: crypto.randomBytes(32).toString("hex"),
}).save();
const message = `${process.env.BASE_URL}/user/verify/${user.id}/${token.token}`;
await sendEmail(user.email, "Verify Email", message);
res.send("An Email sent to your account please verify");
} catch (error) {
res.status(400).send("An error occured");
}
});
router.get("/verify/:id/:token", async (req, res) => {
try {
const user = await User.findOne({ _id: req.params.id });
if (!user) return res.status(400).send("Invalid link");
const token = await Token.findOne({
userId: user._id,
token: req.params.token,
});
if (!token) return res.status(400).send("Invalid link");
await User.updateOne({ _id: user._id, verified: true });
await Token.findByIdAndRemove(token._id);
res.send("email verified sucessfully");
} catch (error) {
res.status(400).send("An error occured");
}
});
module.exports = router;
import users route to index.js
//....
const user = require("./routes/users");
const connection = require("./db");
//.....
app.use(express.json());
app.use("/api/user", user);
//....
That's it check the APIs in postman :)
Posted on May 10, 2021
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.