I have written code for email verification on user registration using nodemailer in nodejs but it is working fine only when running on localhost,
once I put this on server it is not working.Instead of localhost:8080 I used the server IP address then also same problem.
The snippet is
var smtpTransport = nodemailer.createTransport("SMTP", {
service: "Gmail",
auth: {
user: "abc#gmail.com",
pass: "12345"
}
});
var rand, mailOptions, host, link;
app.get('/send', function (req, res) {
rand = Math.floor((Math.random() * 100) + 54);
hash = bcrypt.hashSync(rand, 8);
console.log("hash key " + hash);
host = req.get('host');
console.log("Host -" + host);
link = "http://" + req.get('host') + "/verify?id=" + hash;
mailOptions = {
to: req.query.to,
subject: "Verify your Email account",
html: "Hello,<br> Please Click on the link to verify your email.<br>Click here to verify"
}
global.recip = mailOptions.to;
console.log("recipt =" + recip)
console.log(mailOptions);
smtpTransport.sendMail(mailOptions, function (error, response) {
if (error) {
console.log(error);
res.end("error");
} else {
console.log("Message sent: " + response.message);
res.end("sent");
}
smtpTransport.close();
});
});
app.get('/verify', function (req, res) {
console.log(req.protocol + ":/" + req.get('host'));
console.log("rand " + hash);
console.log("id -" + req.query.id);
if ((req.protocol + "://" + req.get('host')) == ("http://" + host)) {
console.log("Domain is matched. Information is from Authentic email");
if (req.query.id == hash) {
console.log("email is verified");
res.end("<h1 style=margin-top:200px;margin-left:200px;>Email " + mailOptions.to + " is been Successfully verified <br><a href='/password'>Reset Password</a>");
} else {
console.log("email is not verified");
res.end("<h1 style=margin-top:200px;margin-left:200px;>Please enter your email again </h1>");
}
} else {
res.end("<h1>Request is from unknown source");
}
});
The page where user will enter the email id for verification.
$(document).ready(function () {
var from, to, subject, text;
$("#send_email").click(function () {
to = $("#to").val();
if (to == '') {
alert("Please enter a valid email");
} else {
$("#message").text("Sending E-mail...Please wait");
}
$.get("http://23.253.245.25/send", {
to: to
}, function (data) {
if (data == "sent") {
$("#message").empty().html("<h4><br> Email is been sent at " + to + " . Please check inbox !</h4>");
}
});
});
<div class="form-group">
<input type="text" id="to" placeholder="Enter E-mail which you want to verify" onblur="validateEmail(this);" required /><br>
<button id="send_email" style="margin-top:10px;">Send Email</button><br>
<span id="message"></span>
</div>
I had exactly the same issue before on my server. Here are steps to fix it:
Go to: https://www.google.com/settings/security/lesssecureapps to enable logging in from "Less secure apps" - What you've done
Ensure that your server was enabled if it's currently being blocked in the list: https://myaccount.google.com/security#activity
For me the error log was saying
534-5.7.14 <https-//accounts.google.com/ContinueSignIn ..... Please log in via your web browser and then try again....
I believed it told me to login to GMail from my server's browser! So I tried to use Lynx - a browser for terminal to login to GMail (You can also login from: https://accounts.google.com/login). Then... Woo Hoo!, it works!
Good luck!
You have to enable below settings of gmail account from which you want to send mails
https://www.google.com/settings/security/lesssecureapps
Hope it works :)
You can use APP PASSWORD, not required to enable less secure app at your security level.
App password can be created for your custom applications eg: My Custom App
Use the newly generated password as your Gmail Password in your password field.
Support Link: https://support.google.com/accounts/answer/185833?hl=en
Related
I created two test users from MESIBO API, to test messaging between them.
Created exact same script in two files, and add send function in one file, to send message to the second user.
I tried the second user's token, UID, and address but the message gets sent from the first user but 2nd user's script listener doesn't catch it. Both the user tokens, appid (app name) are valid, I tried even in HTTPS connection too, but still couldn't receive a message on another end.
Second User (two.html) : Sender
FIrst User (one.html) : Receiver
Script form first user: which supposed to get the message
<script type="text/javascript" src="https://api.mesibo.com/mesibo.js"></script>
<script>
var demo_user_token = 'XXXXXXXXXXXXXXXXXX';
var demo_appid = 'legal.web';
var api = new Mesibo();
api.setListener(new MesiboListener());
api.setAppName(demo_appid);
api.setCredentials(demo_user_token);
api.setAccessToken(demo_user_token);
//api.setDatabase("mesibo");
api.start();
console.log('First User');
function MesiboListener() {
}
MesiboListener.prototype.Mesibo_OnConnectionStatus = function(status, value) {
console.log("Mesibo_OnConnectionStatus: " + status);
}
MesiboListener.prototype.Mesibo_OnMessageStatus = function(m) {
console.log("Mesibo_OnMessageStatus: from "
+ m.peer + " status: " + m.status);
}
MesiboListener.prototype.Mesibo_OnMessage = function(m, data) {
console.log("Mesibo_OnMessage: from " + m.peer);
}
MesiboListener.prototype.Mesibo_OnCall = function(callid, from, video) {
console.log("Mesibo_onCall: " + (video?"Video":"Voice") + " call from: " + from);
}
</script>
Script from the second user, who send message to the first user using first user's token
<script type="text/javascript" src="https://api.mesibo.com/mesibo.js"></script>
<input type="button" value="Send" onclick="sendTextMessage()" >
<script>
var demo_user_token = 'XXXXXXXXXXXXXXXXXXX';
var demo_appid = 'legal.web';
var api = new Mesibo();
api.setListener(new MesiboListener());
api.setAppName(demo_appid);
api.setCredentials(demo_user_token);
api.setAccessToken(demo_user_token);
api.start();
console.log('Scond User User');
function MesiboListener() {
}
MesiboListener.prototype.Mesibo_OnConnectionStatus = function(status, value) {
console.log("Mesibo_OnConnectionStatus: " + status);
}
MesiboListener.prototype.Mesibo_OnMessageStatus = function(m) {
console.log("Mesibo_OnMessageStatus: from "
+ m.peer + " status: " + m.status);
}
MesiboListener.prototype.Mesibo_OnMessage = function(m, data) {
console.log("Mesibo_OnMessage: from " + m.peer);
}
function sendTextMessage() {
let to = "2757b980f05600c48d75f17f6cb0480ed3a91557655dc7d2ebb3f2dc5vaa1cbe86178"
var profile = api.getProfile(to, 0);
console.log(profile);
var id = parseInt(Math.random()*10000);
profile.sendMessage(id, "this is text message");
}
</script>
Why are you using a token in the "to" parameter? It should be the address "USER_2". Please do not share your tokens in a public forum.
function sendTextMessage() {
let to = "USER_2"
var profile = api.getProfile(to, 0);
console.log(profile);
var id = parseInt(Math.random()*10000);
profile.sendMessage(id, "this is text message");
}
Refer to the tutorial here https://mesibo.com/documentation/tutorials/get-started/javascript/
I'm using an app.post method in Express like so:
app.post('/race', function(req,res) {
let raceResponse = {
user_name: req.body.userName
}
console.log('Express has received race.');
//Socket.IO
let race = io.of('/race').on('connection', (socket) => {
console.log('A user has entered the race!');
socket.on('racePageReady', function() {
console.log('race page ready recieved');
socket.emit('racePageInfo', raceResponse);
});
socket.on('createRoom', function(roomName) {
socket.join(roomName);
let clients = io.sockets.adapter.rooms[roomName].sockets;
console.log("A room with the name " + roomName + "was created.");
console.log(clients);
socket.emit('roomCreated', clients);
});
socket.on('joinRoom', function(roomName) {
socket.join(roomName);
let clients = io.sockets.adapter.rooms[roomName].sockets;
console.log('A user joined the room with the name: ' + roomName + ". The user's name is " + raceResponse.user_name);
console.log(clients);
socket.emit('roomCreated', clients);
});
});
res.sendFile(path.join(__dirname, '/client/race/index.html'));
}
The page is being sent fine, but the console.log and all the other Socket.IO stuff just doesn't happen. I'm finding this peculiar, because I have a different app.post method that works just fine, all console.logging and Socket.IO business happens. Here's the code:
app.post('/city', function(req,res) {
let cityResponse = {
user_name: req.body.userName
}
console.log('Express has received city.');
//Socket.IO
let city = io.of('/city').on('connection', (socket) => {
socket.id = Math.random();
socket.name = cityResponse.user_name;
SOCKET_LIST[socket.id] = socket; //defined earlier
User.onConnect(socket); //defined earlier
socket.on('cityPageReady', function() {
socket.emit('cityPageInfo', cityResponse);
console.log('city page ready recieved');
});
console.log('A user has connected to the city!');
console.log("Socket: " + socket);
console.log("Socket ID: " + socket.id);
console.log("SOCKET_LIST: ");
console.log(SOCKET_LIST);
socket.on('chat message', function(msg, user) {
console.log('User ' + user + ' sent the message : ' + msg);
socket.emit('chat message', msg, user);
});
});
res.sendFile(path.join(__dirname, '/client/city/index.html'));
});
As far as I can tell, both methods look pretty much the same, except for the Socket.IO stuff in the middle. I'm fairly certain that the io.of method is correct, as it's working for the City page, but not the race.
The only other difference is the way that the two pages are accessed. The City page is accessed through a HTML form with an action attribute, whereas the Race page is accessed through a HTML link (on the City page) with a href attribute.
Both methods are shown below:
CITY
<form id="cityForm" action="http://localhost:4000/city" method="POST">
User name: <input type="text" name="userName">
button type="submit" id="formSubmit">Submit</button>
</form>
RACE
<div><a href="http://localhost:4000/race"></div>
Can anyone see why this peculiar behaviour is occuring? If any other information is needed please let me know so that I can include it.
When clicking an on HTML link, the browser does a GET HTML request. When you submit a Form (with method="POST"), the browser does a POST request.
When using app.post(), you tell express to listen for POST requests. If you want express to listen for GET requests, you should use app.get()
I'm using Node for the first time and am having trouble when a certain response is triggered. In this case, I'm checking if the username and pw matches what I have in DynamoDB. It redirects to my page when the username and pw don't match my db, but when it does, all of my console.log output prints twice (which apparently has something to do with the favicon in Chrome) like "online" and "[pw] + database.js," but it also freezes my IDE and terminal. I then see the "The page isn't working, localhost didn't send any data" error in my browser. Ignore the privacy problems :) Thoughts?
database.js:
var myDB_lookup = function(username, password, route_callbck){
console.log('Looking up: ' + username);
users.get(username, function (err, data) {
if (err) {
route_callbck(null, "Lookup error: "+err);
} else if (data == null) {
route_callbck(null, null);
} else {
// JSON object that stores password & fullname
var value = JSON.parse(data[0].value);
var pw = value.password;
if (pw.valueOf() == password.valueOf()){
route_callbck({ password : pw }, null);
console.log(pw + "database.js");
}else{
//console.log('wrong password');
route_callbck(null, null);
}
}
});
};
routes.js:
var checkLogin = function(req,res){
var user = req.body.username;
var pw = req.body.password;
console.log(user + pw + "routes");
db.lookup(user, pw, function(data, err) {
if (data!=null){
console.log("online");
//req.session.username = user;
//req.session.password = pw;
}else{
res.render('main.ejs',{error:"Fields incorrect"});
}
});
};
main.ejs:
<form method="post" action="/checklogin">
Enter username here: <br>
<input type="text" name="username" placeholder = "Your username"> <br>
Enter password here: <br>
<input type="password" name="password" placeholder = "Your password">
<input type="submit" value="Log In">
</form>
The functions are all linked up in routes.js when I do module.exports = ...
You probably forget to send the response, make sure
res.render() or res.json() or res.send() gets hit
you should put a try/catch around JSON.parse(), that's a best practice.
Looks like your culprit is here:
if (data!=null){
console.log("online");
//req.session.username = user;
//req.session.password = pw;
// you need to send the response here too! <<<<<
res.render('main.ejs'); //// !!!
}else{
res.render('main.ejs',{error:"Fields incorrect"});
}
Here is a server-side function that receives a POST request and handles its response. As you can see, when no error occurs, the status code of the response is 200.
app.post('/submit', function(req, res) {
var p = new Promise(function(resolve, reject) {
db.serialize(function() {
db.run("INSERT INTO users VALUES (?, ?, ?, ?)",
[req.query['email'], req.query['company'], req.query['subject'], req.query['text']],
function (err) {
if (err) {
console.error(err);
reject();
} else {
console.log("Transaction passed");
resolve();
}
});
});
});
p.then(function(){
res.status(200).end();
}).catch(function() {
res.status(400).end();
})
});
In the client side, I wrote a JS function that sends an AJAX POST request to the server and handles the response:
function addFormToDB(email, company, subject, text) {
var xhttp = new XMLHttpRequest();
var params = "email=" + email + "&company=" + company + "&subject=" + subject + "&text=" + text;
xhttp.open("POST", "http://127.0.0.1:3000/submit?" + params, true);
xhttp.onreadystatechange = function() {
console.log(xhttp.readyState + " " + xhttp.status);
if (xhttp.readyState == 4 && xhttp.status == 200) {
console.log("request " + params + " was sent to DB");
alert("Thank You!");
}
};
xhttp.send();
}
When I invoke the function 'addFormToDB' from the console window of the browser, it sends an AJAX request to the server and gets it back with an xhhr.status of 200.
However, 'addFormToDB' has to be invoked when the user fills a form and clicks the 'submit' button. When this happens, the xhhr.status sent back from the server to the browser is always 0. I don't know why.
Here is the HTML code that creates the form:
<form id="form">
<label for="email"> E-mail: </label>
<input id = "email"> <br>
<label for="company"> Company: </label>
<input id = "company"> <br>
<label for="subject"> Subject: </label>
<input id = "subject"> <br>
<label for="text"> Text: </label>
<input id = "text"> <br>
<input type="submit" value="Submit" id="button"><br><br>
</form>
...
<script>
$("#form").submit(function() {
addFormToDB($("#email").val(), $("#company").val(), $("#subject").val(), $("#text").val())
});
</script>
Can you help me find out the bug?
The immediate issue is that you don't prevent the default action of a form submit - which is to POST data to the server and reload the page. As a side-effect this cancels all running Ajax requests, which causes the effect you see.
To prevent the default event action, call preventDefault() on the event object.
function submitHandler(e) {
e.preventDefault();
// some processing, for example Ajax
// the browser will not issue a traditional POST request
}
Back in the day, return false; had the same effect, but nowadays.preventDefault() is the way to go.
Further comments on your code:
Client Side
Don't roll your own Ajax functions. Ajax libraries are plenty and convenient, well-tested and provide easy-to-read Ajax support that prevents common errors and does all kinds of heavy lifting transparently. Just use one of the many libraries.
With jQuery, which you seem to be using anyway, the function becomes as straight-forward as this:
function addFormToDB(email, company, subject, text) {
return $.post("http://127.0.0.1:3000/submit", {
email: email,
company: company,
subject: subject,
text: text
})
.done(function (data) {
console.log("received", data);
alert("Thank You!");
})
.fail(function (jqXhr, status, err) {
console.error(err);
});
}
Server Side
Don't do your own promisification. It might look easy enough, but just as with Ajax, there's enough stuff that can go wrong and is easily overlooked. Let a library do it for you, or use a wrapper library that did it for you. For node-sqlite3, one such wrapper library exists: co-sqlite3. I recommend you look at it.
Your code could look like this:
app.post('/submit', function(req, res) {
var q = req.query;
var params = [q.email, q.company, q.subject, q.text];
db.serialize()
.then(() => db.run("INSERT INTO users VALUES (?, ?, ?, ?)", params))
.then(() => res.status(200).end())
.catch((err) => {
console.error(err);
res.status(400).end();
});
});
});
Or use one of the async/yield variants shown in the library's samples.
I am trying to access the Appcelerator Titanium SDK for ACS after authenticating a user through Social Integrations. I am using the following code, which is copied line for line from the ACS Kitchen Sink example application, and I still cannot get it to work. The call to log the user in is successful, but the subsequent call to PhotoCollections API returns "404 - Failed to Authenticate user".
I am using oauth 3 legged authentication with the User Authentication Scheme set to Authorization Server. I have also tried other ACS APIs, without any luck. Please help! I've been stuck on this for 2 weeks now.
fb.addEventListener('login', function(e) {
if (e.success) {
Cloud.SocialIntegrations.externalAccountLogin({
type : 'facebook',
token : fb.accessToken
}, function(e) {
if (e.success) {
var user = e.users[0];
Cloud.PhotoCollections.create({
name : 'Party Pictures'
}, function(e) {
if (e.success) {
var collection = e.collections[0];
alert('Success:\n' + 'id: ' + collection.id + '\n' + 'name: ' + collection.name + '\n' + 'count: ' + collection.counts.total_photos + '\n' + 'updated_at: ' + collection.updated_at);
} else {
alert('Error:\n' + ((e.error && e.message) || JSON.stringify(e)));
}
});
} else {
alert('Error: ' + ((e.error && e.message) || JSON.stringify(e)));
}
});
}
});
Turns out that multiple posts online were wrong about the server configuration needed to do this. Make sure that your "User Authentication Scheme" is set to "API Server" and not "Authorization Server". It turned out to be that simple for me.