Nodemailer send email with information from MySQL Database - mysql

I'm trying to do password recovery with Nodemailer. Basically, the user will input an email address to an HTML form and an email will be sent using Nodemailer. That email will contain the password from the MySQL database. My problem is, the password shows as "undefined".
app.post('/Forgot_Password_V1', function(request, response) {
var connection = request.app.get('pool');
connection.query('SELECT password FROM accounts WHERE email = ?', [request.body.email], function(error, results, fields) {
https://myaccount.google.com/lesssecureapps?pli=1
{ account: results[0] };
var transporter = nodemailer.createTransport({
service: 'Gmail',
auth: {
user: 'user',
pass: 'password'
}
});
//send to the email entered in the form input
var mailOptions = {
from: 'email',
to: request.body.email,
subject: 'Password Request',
text: 'You have requested to recover the password of your account.\n\n' +
request.password + // I tried this
account.password + // I also tried this
'\n End.\n'
};
The output for the password in the email shows "undefined". I've been trying different things to no avail. Can somebody please help what I'm doing wrong?

Related

Mysql JWT reporting fails always

i am trying to simulate login using Node.Js , JWT and mysql
i am always getting invalid user and pass, i started to wonder what i was not doing correctly.
My code:
app.post('/api/v1/user/login', async function(req,res){
var email = req.body.email;
var password = req.body.password;
var hashPass = await bcrypt.hashSync(password,12);
const bycryptPass = bcrypt.compareSync(password,hashPass);
dbConn.query('select * from xxxx_users where email =? and password =?',[email,bycryptPass],function(error,results,fields){
if(results.length > 0){
const token = jwt.sign({id:row[0].id},'the-super-strong-secrect',{ expiresIn: '1h' });
res.send({error: false, message: 'OK', token: token})
}else{
res.send({error: true, message: 'Invalid User or Pass'})
}
})
})
what am i not doing correctly? Why does it report that the login user and pass is always failed?
Compare hash would give you a boolean result based on the 2 values that you passed into it.
First, you have to get the user record based on the username and then check the password or pass hashed password to the query itself.
const hashPass = await bcrypt.hashSync(password,12);
//const bycryptPass = bcrypt.compareSync(password,hashPass);
dbConn.query('select * from xxxx_users where email =? and password =?',[email,hashPass],function(error,results,fields){
if(results.length > 0){
const token = jwt.sign({id:row[0].id},'the-super-strong-secrect',{ expiresIn: '1h' });
res.send({error: false, message: 'OK', token: token})
}else{
res.send({error: true, message: 'Invalid User or Pass'})
}
})
I prefer the following
const user = await getUserByUsername(loginRequest.userName);
if (user && compareHash(user.password, loginRequest.password)) {
//login success access
}
bcrypt will never produce the same hash for the same password. It's one of its design features.
Your general flow would work for older ways to hash passwords, like md5, sha256, but these are no longer recommended.
The general correct flow for implementing login works roughly like this:
Given that you have a username and password
Pull out the user record from the database based on the username alone (not the password)
Then use the compare function to see if the password the user supplied is comparable to the hash in the database.
It's impossible to select on the password hash, it will always be wrong.

Send email with nodemailer, and insert form data into mysql db

Trying to setup a form that receives user input for a beta testing email list, which will send me an email with the user's information, and store the same form data into a mysql database.
I have the mysql connection and query inside the same route as the nodemailer objects, but when the form is submitted I get an error saying that "admin is not defined". This is the admin inside the transporter object. I thought it might cause problems if two different objects (tranporter and connection) have the same property name, so I changed the conventional nodemailer 'user' inside the transporter to 'admin'.
const express = require("express");
const app = express();
const nodemailer = require("nodemailer");
const bodyParser = require("body-parser");
const mysql = require("mysql");
app.use(bodyParser.urlencoded({extended: true}));
// send "Beta" email when user signs up to the email list using the "Beta" form
app.post("/register", function(req, res){
// connect to database
const connection = mysql.createConnection({
host: "localhost",
user: "root",
password: "PASSWORD",
database: "DATABASE_NAME"
});
// insert statement
let insert = "INSERT INTO Beta_Testers(First_Name, Last_Name, Beta_Email) VALUES ('" + req.body.First_Name + "', '" + req.body.Last_Name + "', '" + req.body.Beta_Email + "')";
// execute the insert statement
connection.query(insert);
// disconnect from database
connection.end();
// nodemailer objects
let mailOpts, transporter;
// email transporter
transporter = nodemailer.createTransport({
host: 'smtp.gmail.com',
port: 3000, // changed from 465
secure: true,
auth: {
admin: "GMAIL_USER",
pass: "PASSWORD"
}
});
// email credentials
mailOpts = {
from: req.body.First_Name + " " + req.body.Last_Name + " <" + req.body.Beta_Email + ">",
to: admin,
subject: "You have a new BETA tester!",
text: `${req.body.Beta_Email} has signed up to be a BETA tester for WEBAPP_NAME. Please confirm sucessful registration into DATABASE_NAME.`
};
// send email and verify contact
transporter.sendMail(mailOpts, function(err, res) {
if (err) {
res.render("contact-failure");
} else {
res.render("contact-success");
}
});
});
ReferenceError: admin is not defined
The Error is in : "to: admin"
It should contain an email to which email will be sent. These are the mail_options and the option "to" need to be set with an email like "abc#xyz.com".
You can set :-
to: req.body.email

Error function not returning JSON format

I'm trying to pass a JSON error object into my code using the error function in two cases. Once in the email and password check statement and again in the if existingUser statement. I think it's just that time of the night.
const User = require('../models/user');
exports.signup = function(req, res, next) {
const email = req.body.email;
const password = req.body.password;
if (!email || !password) {
return res.err("Please enter in email and password");
}
//See if a user with the given email exists
User.findOne({ email: email }, function(err, existingUser) {
if (err) { return next(err); }
//If a user with email does exist, return an Error
if (existingUser) {
//the status sets the status of the http code 422 means couldn't process this
return res.err( 'Email is in use' );
}
//If a user with email does NOT exist, create and save user record
const user = new User({
email: email,
password: password
});
user.save(function(err) {
if (err) { return next(err); }
//Respond to request indicating the user was created
res.json({ success: true });
});
});
}
At the moment you are not returning the right status code in your response, you could try this:
Replace:
return res.err("Please enter in email and password");
With
return res.status(422).send({error: "Please enter in email and password"})
And replace:
return res.err( 'Email is in use' );
With:
return res.status(422).send({ error: "Email is in use" });
This will send back the required status code in the http response.
Also consider only using single or double quotes in your code for consistency.

passport-local with mysql not working

I am using node.js and passport and mysql for a userlogin.
I the main source is from https://github.com/manjeshpv/node-express-passport-mysql/issues
I want to add more columns in the table. I started with emailfield and change the code like below. I simply added the email variable at the needed places I think. I cannot find the bug where its crashing. without modifying anything, the code does work.
passport.js:
passport.use(
'local-signup',
new LocalStrategy({
// by default, local strategy uses username and password, we will override with email
usernameField : 'username',
passwordField : 'password',
//emailField : 'email',
passReqToCallback : true // allows us to pass back the entire request to the callback
},
function(req, username, password, email, done) {
// find a user whose email is the same as the forms email
// we are checking to see if the user trying to login already exists
connection.query("SELECT * FROM users WHERE username = ?",[username], function(err, rows) {
if (err)
log.info(err);
//return done(err);
if (rows.length) {
return done(null, false, req.flash('signupMessage', 'That username is already taken.'));
} else {
// if there is no user with that username
// create the user
var newUserMysql = {
username: username,
email: email,
password: bcrypt.hashSync(password, null, null) // use the generateHash function in our user model
};
var insertQuery = "INSERT INTO users ( username, password, email ) values (?,?,?)";
connection.query(insertQuery,[newUserMysql.username, newUserMysql.password, newUserMysql.email],function(err, rows) {
newUserMysql.id = rows.insertId;
return done(null, newUserMysql);
});
}
});
})
);
and here the log:
The magic happens on port 8080
GET /signup 200 20ms - 1.21kb
D:\node-express-passport-mysql\node_modules\mysql\lib\protocol\Parser.js:82
throw err;
^
TypeError: undefined is not a function
at Object.SqlString.escape (D:\node-express-passport-mysql\node_modules\mysq
l\lib\protocol\SqlString.js:46:13)
at D:\node-express-passport-mysql\node_modules\mysql\lib\protocol\SqlString.
js:80:19
at String.replace (native)
at Object.SqlString.format (D:\node-express-passport-mysql\node_modules\mysq
l\lib\protocol\SqlString.js:71:14)
at Connection.format (D:\node-express-passport-mysql\node_modules\mysql\lib\
Connection.js:263:20)
at Connection.query (D:\node-express-passport-mysql\node_modules\mysql\lib\C
onnection.js:196:22)
at Query._callback (D:\node-express-passport-mysql\config\passport.js:71:32)
at Query.Sequence.end (D:\node-express-passport-mysql\node_modules\mysql\lib
\protocol\sequences\Sequence.js:96:24)
at Query._handleFinalResultPacket (D:\node-express-passport-mysql\node_modul
es\mysql\lib\protocol\sequences\Query.js:144:8)
at Query.EofPacket (D:\node-express-passport-mysql\node_modules\mysql\lib\pr
otocol\sequences\Query.js:128:8)
28 Jun 21:03:58 - [nodemon] app crashed - waiting for file changes before starti
ng...
This looks to be the problem:
function(req, username, password, email, done) {
You added an extra argument email which shouldn't be there. Since it clobbers the done callback, when your code tries to call it it will cause an "undefined is not a function" error.
If you're passing an extra email property, you can access it through req.body.email (assuming that you're using a POST route to log in).

Sailsjs not getting email when using node mailer smtp transport

I am using node mailer to send emails in my sailsjs application.But unable to get emails when using smtp transport to send emails. It is showing the correct response with meesage id in callback method but am not getting email in my mailbox. Here is some configuration I made for smtp transport:
var nodemailer = require('nodemailer');
var smtpTransport = require('nodemailer-smtp-transport');
var transport = nodemailer.createTransport(smtpTransport({
host: 'smtp.hostname.com',
port: 587,
debug: true,
auth: {
user: 'XXXXXX',
pass: 'XXXXXX'
}
}));
And am using following method to send email:
var mailOptions = {
from: 'Sendername <sender#noreply.com>', // sender address
to: reciever#domain.com, // list of receivers
subject: Email Subject, // Subject line
text: 'Hello world ', // plaintext body
};
transport.sendMail(mailOptions, function(error, info){
if(error){
console.log(error);
}else{
console.log('Message sent: ' , info);
}
});
And the following response am getting after send email:
Message sent:
{ accepted: [ 'reciever#domain.com' ],
rejected: [],
response: '250 OK id=1XeiXV-00005O-6x',
envelope: { from: 'sender#noreply.com', to: [ 'reciever#domain.com' ] },
messageId: '1413456251972-47ace346-09f25dad-5616cfdb#noreply.com' }
Is your app deployed to a host or are you running it locally? Host's like Modulus often block SMTP ports because of spammers.