Before starting the code you need an account in send grid which will send the notification to your mail. Generally we use email notifications for forget passwords in your applications. You can follow the below steps to get the task done and if you have any queries please leave a comment below.
We require a few modules from npm to send the notification through the mail.
- npm install formidable
- npm install crypto
- npm install async
- npm install nodemailer
In my router.js file the following code will be present
app.route('/forgotpasswordResponse')
.post(userCtrl.forgotpasswordResponse);
When I run my services and hit the above Url from postman it will take you to the forgotpasswordResponse method. We are using post method in postman where we need to pass Email id as parameter
In forgotpasswordResponse my code is somthing like this,
exports.forgotpasswordResponse = function(req, res, next) {
var input=req.body;
//console.log(input);
async.waterfall([
function(done) {
crypto.randomBytes(20, function(err, buf) {
var token = buf.toString('hex');
done(err, token);
});
},
function(token, done) {
MongoClient.connect(url, function(err, db){
var dbo = db.db("Here is your DB Name");
//console.log(req.body.Email);
var query = { Email : req.body.Email };
dbo.collection('CLC_User').find(query).toArray(function(err,result){
if(result.length == 0){
req.flash('error', 'No account with that email address exists.');
}
var myquery = { Email: result[0].Email };
var newvalues = { $set: {resetPasswordToken: token, resetPasswordExpires: Date.now() + 3600000 }};
dbo.collection("CLC_User").updateOne(myquery, newvalues, function(err, res) {
if (err) throw err;
console.log("1 document updated");
});
// console.log(result[0].Email);
done(err, token, result);
});
});
},
function(token, result, done,Username,password) {
var emailVal = result[0].Email;
console.log(emailVal);
var Username="";
var password="";
MongoClient.connect(url, function(err, db){
var dbo = db.db("Here willbe your db name");
dbo.collection('Accountsettings').find().toArray(function(err,result){
if (err) throw err;
Username=result[0].UserName;
password=result[0].Password;
// console.log(Username);
// console.log(password);
// res.json({status : 'success', message : 'Records found', result : result});
// console.log(Username);
var smtpTransport = nodemailer.createTransport({
service: 'SendGrid',
auth: {
user: Username,
pass: password
}
});
const mailOptions = {
to: emailVal,
from: '[email protected]',
subject: 'Node.js Password Reset',
text: 'You are receiving this because you (or someone else) have requested the reset of the password for your account.\n\n' +
'Please click on the following link, or paste this into your browser to complete the process:\n\n' +
'http://' + req.headers.host + '/reset/' + token + '\n\n' +
'If you did not request this, please ignore this email and your password will remain unchanged.\n'
};
smtpTransport.sendMail(mailOptions, function(err) {
console.log("HI:"+emailVal);
res.json({status : 'success', message : 'An e-mail has been sent to ' + emailVal + ' with further instructions.'});
done(err, 'done');
});
})
});
}
], function(err) {
if (err) return next(err);
});
}
In my case I am using waterfall methologie for this method with will execute acyn in method, In the above code initially I am updating the collection with resetPasswordToken and resetPasswordExpires using email id and getting my send grid credentials from db form Accountsettings collections. If you can observe in mailOptions text "req.headers.host" will be the link which will get in you mail with token.
When you click on Url which you got in the email it will redirect you to another page to set the password.
Again we need to go to route.js and the code will be some thing like this. It will take to html page which we can reset the password,
app.route('/reset/:token')
.get(Resetpassword.resetpasswordResponse);
This time I am passing the token which I stored in db as "resetPasswordToken". Now it will take you to resetpasswordResponse method and the code is below,
exports.resetpasswordResponse = function(req, res) {
console.log("welcome");
MongoClient.connect(url, function(err, db){
var dbo = db.db("Here is you db");
dbo.collection('CLC_User').findOne({resetPasswordToken: req.params.token, resetPasswordExpires: { $gt: Date.now() } }, function(err, user) {
if (!user) {
res.json({message: 'Password reset token is invalid or has expired.'});
}else{
console.log("coming");
fs.readFile("api/Controllers/resetpassword.html", function (error, data) {
console.log("its working");
if (error) {
console.log(error);
res.writeHead(404);
res.write('Contents you are looking are Not Found');
} else {
//res.writeHead(200, { 'Content-Type': 'text/html' });
res.write(data);
}
res.end();
});
}
});
});
}
Your html code in resetpassword.html will be like this,
<!DOCTYPE html>
<html>
<head>
<title>Reset Password</title>
<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
</head>
<body>
<h4 class="postdata" style="text-align:center;"></h4>
<div class="main-agileits">
<h2 class="sub-head">Reset Password</h2>
<div class="sub-main">
<form method="post">
<span class="senddata"></span><br><br>
<input placeholder="Enter Password" name="password" class="password" type="password" required=""><br><br>
<input placeholder="Confirm Password" name="confirmpassword" class="confirmpassword" type="password" required=""><br><br>
<input type="submit" name ="submit" value="RESET PASSWORD">
</form>
</div>
</div>
</body>
</html>
<script type="text/javascript">
$( document ).ready(function() {
$("input[name='submit']").on("click", function(){
$(".senddata").html("");
var url = window.location.href;
var password = $('.password').val();
var confirmpassword = $('.confirmpassword').val();
if( password == confirmpassword){
$.post(url,{Password : password},function(result,status){
var msg = result.status;
var msgdata = result.message;
if(msg == "success"){
$(".postdata").html(msgdata);
$(".main-agileits").css("display","none")
}else{
return false;
}
});
}else{
$(".senddata").html("Passwords did not match");
}
return false;
});
});
</script>
the next step is send the Email notification after changing the password.The code is
app.route('/reset/:token')
.post(setpassword.setpasswordResponsemail);
exports.setpasswordResponsemail = function(req, res) {
async.waterfall([
function(done) {
MongoClient.connect(url, function(err, db){
var dbo = db.db("Your Db name goes here");
dbo.collection('CLC_User').findOne({resetPasswordToken: req.params.token, resetPasswordExpires: { $gt: Date.now() } }, function(err, user) {
if (!user) {
res.json({message: 'Password reset token is invalid or has expired.'});
}
//console.log(user);
var myquery = { resetPasswordToken: req.params.token };
var newvalues = { $set: {Password: req.body.Password,resetPasswordToken: undefined, resetPasswordExpires: undefined, modifiedDate : Date(Date.now()) }};
dbo.collection("CLC_User").updateOne(myquery, newvalues, function(err, result) {
if (err) throw err;
//console.log("result ======" + result);
console.log("1 document updated");
});
done(err, user);
});
});
},
function(user, done) {
MongoClient.connect(url, function(err, db){
var dbo = db.db("Your db name goes here");
var Username="";
var password="";
dbo.collection('Accountsettings').find().toArray(function(err,result){
if (err) throw err;
Username=result[0].UserName;
password=result[0].Password;
})
})
var smtpTransport = nodemailer.createTransport({
service: 'SendGrid',
auth: {
user: Username,
pass: password
}
});
var mailOptions = {
to: user.Email,
from: '[email protected]',
subject: 'Your password has been changed',
text: 'Hello,\n\n' +
'This is a confirmation that the password for your account ' + user.Email + ' has just been changed.\n'
};
smtpTransport.sendMail(mailOptions, function(err) {
res.json({status : 'success', message : 'Success! Your password has been changed.'});
done(err);
});
}
], function(err) {
if (err) return err;
});
}
Hope this code will help someone who really needs it. Thank you.