Send an otp to the desired mobile number using nodejs - node.js

I am using Plivo to send sms to the user for otp verification and i am unable to update mobile number and message parameters for different users, here is my code
global.params = {
'src': 'xx-xxxx', // Sender's phone number with country code
'dst' : '91'+'xxxxxxxxxx', // Receiver's phone Number with country code
'text' : "Hi, message from Plivo", // Your SMS Text Message - English
'url' : "https://intense-brook-8241.herokuapp.com/report/", // The URL to which with the status of the message is sent
'method' : "GET" // The method used to call the url
};
module.exports={
foo: function createOTPverify(mobile_number, id){
var motp = randomize('0',4);
console.log("motp "+motp);
global.params.dst = mobile_number;
global.params.text = "Hi, your verification one time password is "+motp;
p.send_message(global.params, function(status, response){
console.log('Status: ', status);
console.log('API Response:\n', response);
})
}
}
here everything is working fine but unable to update parameters, i tried it using global but still not able to do, please help

You're not updating your config array anywhere. Hence, the issue
Check the below gist, it should help you send OTP
https://runkit.com/isanjayachar/plivo-send-otp
const plivo = require('plivo').RestAPI({
authId: '<your AUTH ID>',
authToken: '<your AUTH TOKEN>',
})
function getParmas(phone, otp) {
return {
'src': 'xx-xxxx',
'dst' : '91'+ phone,
'text' : "Your OTP for verification is " + otp,
'url' : "https://intense-brook-8241.herokuapp.com/report/",
'method' : "GET"
}
}
function sendOTP(phone) {
var otp;
// Generate your OTP here
plivo.make_call(getParmas(phone, otp), function(status, response) {
console.log('Status:' + status)
console.log('Reponse:' + response)
})
}
sendOTP('9999999999');

Related

Where can i find client token ID on Firebase Cloud Messaging?

I try to find simple client-server app using Firebase Cloud Messaging.
I use Nodejs and this package, but I don't know how and where I can find the client token?
Here the example code:
var fcm = require('fcm-notification');
var FCM = new fcm('path/to/privatekey.json');
var token = 'token here';
var message = {
data: { //This is only optional, you can send any data
score: '850',
time: '2:45'
},
notification:{
title : 'Title of notification',
body : 'Body of notification'
},
token : token
};
FCM.send(message, function(err, response) {
if(err){
console.log('error found', err);
}else {
console.log('response here', response);
}
})
Usually, the person is on the website / app and the client code asks for permission to send notifications. If granted, the client then calls the FCM server to get a token that represents that person.
The client code then saves that token to a database with the person's id.
Then when sending the message your server side software reads the token from the database.
(I hope that is the answer to your question.)

Firebase : How to send a password reset email backend with NodeJs

I'm trying to impliment the code as found here: https://firebase.google.com/docs/auth/web/manage-users#send_a_password_reset_email
var auth = firebase.auth();
var emailAddress = "user#example.com";
auth.sendPasswordResetEmail(emailAddress).then(function() {
// Email sent.
}).catch(function(error) {
// An error happened.
});
But I can't find the sendPasswordResetEmail method in firebase admin.
Anyway I can do this on the backend?
ORIGINAL JULY 2018 ANSWER:
The sendPasswordResetEmail() method is a method from the client-side auth module, and you're right, the Admin-SDK doesn't have it - or anything comparable. Most folks call this function from the front-end...
With that said, it is possible to accomplish on the backend... but you'll have to create your own functionality. I've done this sort of thing before, I'll paste some of my code from my cloud functions to help you along... should you choose to go down this road. I create my own JWT, append it to a URL, and then use NodeMailer to send them an email with that link... when they visit that link (a password reset page) they enter their new password, and then when they click the submit button I pull the JWT out of the URL and pass it to my 2nd cloud function, which validates it and then resets their password.
const functions = require('firebase-functions');
const admin = require('firebase-admin');
var jwt = require('jsonwebtoken');
admin.initializeApp()
// Email functionality
const nodemailer = require('nodemailer');
// Pull the gmail login info out of the environment variables
const gmailEmail = functions.config().gmail.email;
const gmailPassword = functions.config().gmail.password;
// Configure the nodemailer with our gmail info
const mailTransport = nodemailer.createTransport({
service: 'gmail',
auth: {
user: gmailEmail,
pass: gmailPassword,
},
});
// Called from any login page, from the Forgot Password popup
// Accepts a user ID - finds that user in the database and gets the associated email
// Sends an email to that address containing a link to reset their password
exports.forgotPassword = functions.https.onRequest( (req, res) => {
// Make a query to the database to get the /userBasicInfo table...
admin.database().ref(`userBasicInfo`).once('value').then( dataSnapshot => {
let allUsers = dataSnapshot.val() ? dataSnapshot.val() : {};
let matchingUid = '';
let emailForUser = '';
// Loop over all of the users
Object.keys(allUsers).forEach( eachUid => {
// See if their email matches
allUsers[eachUid]['idFromSis'] = allUsers[eachUid]['idFromSis'] ? allUsers[eachUid]['idFromSis'] : '';
if (allUsers[eachUid]['idFromSis'].toUpperCase() === req.body.userIdToFind.toUpperCase()) {
// console.log(`Found matching user! Uid: ${eachUid} with idFromSis: ${allUsers[eachUid]['idFromSis']}... setting this as the matchingUid`);
matchingUid = eachUid;
emailForUser = allUsers[eachUid]['email'] ? allUsers[eachUid]['email'] : '';
}
})
// After loop, see if we found the matching user, and make sure they have an email address
if (matchingUid === '' || emailForUser == '') {
// Nothing found, send a failure response
res.send(false);
} else {
// Send an email to this email address containing the link to reset their password
// We need to generate a token for this user - expires in 1 hour = 60 minutes = 3600 seconds
jwt.sign({ uid: matchingUid }, functions.config().jwt.secret, { expiresIn: 60 * 60 }, (errorCreatingToken, tokenToSend) => {
if (errorCreatingToken) {
console.log('Error creating user token:');
console.log(errorCreatingToken);
let objToReplyWith = {
message: 'Error creating token for email. Please contact an adminstrator.'
}
res.json(objToReplyWith);
} else {
// Send token to user in email
// Initialize the mailOptions variable
const mailOptions = {
from: gmailEmail,
to: emailForUser,
};
// Building Email message.
mailOptions.subject = 'LMS Password Reset';
mailOptions.text = `
Dear ${req.body.userIdToFind.toUpperCase()},
The <system> at <company> has received a "Forgot Password" request for your account.
Please visit the following site to reset your password:
https://project.firebaseapp.com/home/reset-password-by-token/${tokenToSend}
If you have additional problems logging into LMS, please contact an adminstrator.
Sincerely,
<company>
`;
// Actually send the email, we need to reply with JSON
mailTransport.sendMail(mailOptions).then( () => {
// Successfully sent email
let objToReplyWith = {
message: 'An email has been sent to your email address containing a link to reset your password.'
}
res.json(objToReplyWith);
}).catch( err => {
// Failed to send email
console.log('There was an error while sending the email:');
console.log(err);
let objToReplyWith = {
message: 'Error sending password reset email. Please contact an adminstrator.'
}
res.json(objToReplyWith);
});
}
})
}
}).catch( err => {
console.log('Error finding all users in database:');
console.log(err);
res.send(false);
})
});
// Called when the unauthenticated user tries to reset their password from the reset-password-by-token page
// User received an email with a link to the reset-password-by-token/TOKEN-HERE page, with a valid token
// We need to validate that token, and if valid - reset the password
exports.forgotPasswordReset = functions.https.onRequest( (req, res) => {
// Look at the accessToken provided in the request, and have JWT verify whether it's valid or not
jwt.verify(req.body.accessToken, functions.config().jwt.secret, (errorDecodingToken, decodedToken) => {
if (errorDecodingToken) {
console.error('Error while verifying JWT token:');
console.log(error);
res.send(false);
}
// Token was valid, pull the UID out of the token for the user making this request
let requestorUid = decodedToken.uid;
admin.auth().updateUser(requestorUid, {
password: req.body.newPassword
}).then( userRecord => {
// Successfully updated password
let objToReplyWith = {
message: 'Successfully reset password'
}
res.json(objToReplyWith);
}).catch( error => {
console.log("Error updating password for user:");
console.log(error)
res.send(false);
});
});
});
JANUARY 2019 EDIT:
The Admin SDK now has some methods that allow you to generate a "password reset link" that will direct people to the built-in Firebase password reset page. This isn't exactly the solution OP was looking for, but it's close. You will still have to build and send the email, as my original answer shows, but you don't have to do everything else... i.e.: generate a JWT, build a page in your app to handle the JWT, and another backend function to actually reset the password.
Check out the docs on the email action links, specifically the "Generate password reset email link" section.
// Admin SDK API to generate the password reset link.
const email = 'user#example.com';
admin.auth().generatePasswordResetLink(email, actionCodeSettings)
.then((link) => {
// Do stuff with link here
// Construct password reset email template, embed the link and send
// using custom SMTP server
})
.catch((error) => {
// Some error occurred.
});
Full disclosure - I haven't actually used any of those functions, and I'm a little concerned that the page in question refers a lot to mobile apps - so you might have to pass it the mobile app config.
const actionCodeSettings = {
// URL you want to redirect back to. The domain (www.example.com) for
// this URL must be whitelisted in the Firebase Console.
url: 'https://www.example.com/checkout?cartId=1234',
// This must be true for email link sign-in.
handleCodeInApp: true,
iOS: {
bundleId: 'com.example.ios'
},
android: {
packageName: 'com.example.android',
installApp: true,
minimumVersion: '12'
},
// FDL custom domain.
dynamicLinkDomain: 'coolapp.page.link'
};
On the other hand, the page also says these features provide the ability to:
Ability to customize how the link is to be opened, through a mobile
app or a browser, and how to pass additional state information, etc.
Which sounds promising, allowing it to open in the browser... but if you are developing for web - and the function errors out when not provided iOS/Android information... then I'm afraid you'll have to do it the old fashioned approach and create your own implementation... but I'm leaning towards this .generatePasswordResetLink should work now.
Unlike other client features which work on the user object (e.g. sending a verification mail), sending a password reset email works on the auth module and doesn't require a logged-in user. Therefore, you can simply use the client library from the backend (provided you have the user's email address):
const firebase = require('firebase');
const test_email = "test#test.com";
const config = {} // TODO: fill
const app = firebase.initializeApp(config);
app.auth().sendPasswordResetEmail(test_email).then(() => {
console.log('email sent!');
}).catch(function(error) {
// An error happened.
});
public void resetpasswoord()
{
string emailaddress = resest_email.text;
FirebaseAuth.DefaultInstance.SendPasswordResetEmailAsync(emailaddress).ContinueWith((task =>
{
if (task.IsCompleted)
{
Debug.Log("Email sent.");
}
if (task.IsFaulted)
{
Firebase.FirebaseException e =
task.Exception.Flatten().InnerExceptions[0] as Firebase.FirebaseException;
GetErrorMessage((AuthError)e.ErrorCode);
errorpanal = true;
return;
}
}));
}
void GetErrorMessage(AuthError errorcode)
{
string msg = "";
msg = errorcode.ToString();
print(msg);
errorpanal = true;
ErrorText.text = msg;
}

How to confirm email address using express/node?

I'm trying to build verification of email address for users, to verify their email is real. What package should I use to confirm the email address of the user? So far Im using mongoose and express
Code Example
var UserSchema = new mongoose.Schema({
email: { type: String, unique: true, lowercase: true }
password: String
});
var User = mongoose.model('User', UserSchema);
app.post('/signup', function(req, res, next) {
// Create a new User
var user = new User();
user.email = req.body.email;
user.password = req.body.password;
user.save();
});
In the app.post codes, how do i confirm the email address of the user?
What you're looking for is called "account verification" or "email verification". There are plenty of Node modules that can perform this, but the principle goes like this:
Your User model should have an active attribute that is false by default
When the user submits a valid signup form, create a new User (who's active will be false initially)
Create a long random string (128 characters is usually good) with a crypto library and store it in your database with a reference to the User ID
Send an email to the supplied email address with the hash as part of a link pointing back to a route on your server
When a user clicks the link and hits your route, check for the hash passed in the URL
If the hash exists in the database, get the related user and set their active property to true
Delete the hash from the database, it is no longer needed
Your user is now verified.
var express=require('express');
var nodemailer = require("nodemailer");
var app=express();
/*
Here we are configuring our SMTP Server details.
STMP is mail server which is responsible for sending and recieving email.
*/
var smtpTransport = nodemailer.createTransport("SMTP",{
service: "Gmail",
auth: {
user: "Your Gmail ID",
pass: "Gmail Password"
}
});
var rand,mailOptions,host,link;
/*------------------SMTP Over-----------------------------*/
/*------------------Routing Started ------------------------*/
app.get('/',function(req,res){
res.sendfile('index.html');
});
app.get('/send',function(req,res){
rand=Math.floor((Math.random() * 100) + 54);
host=req.get('host');
link="http://"+req.get('host')+"/verify?id="+rand;
mailOptions={
to : req.query.to,
subject : "Please confirm your Email account",
html : "Hello,<br> Please Click on the link to verify your email.<br>Click here to verify"
}
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");
}
});
});
app.get('/verify',function(req,res){
console.log(req.protocol+":/"+req.get('host'));
if((req.protocol+"://"+req.get('host'))==("http://"+host))
{
console.log("Domain is matched. Information is from Authentic email");
if(req.query.id==rand)
{
console.log("email is verified");
res.end("<h1>Email "+mailOptions.to+" is been Successfully verified");
}
else
{
console.log("email is not verified");
res.end("<h1>Bad Request</h1>");
}
}
else
{
res.end("<h1>Request is from unknown source");
}
});
/*--------------------Routing Over----------------------------*/
app.listen(3000,function(){
console.log("Express Started on Port 3000");
});
Follow the code example, you can use nodemailer to send the link, and then verify it.
Here is a link: https://codeforgeek.com/2014/07/node-email-verification-script/
Step 1:
User Model
var userSchema = new mongoose.Schema({
email: { type: String, unique: true },
isVerified: { type: Boolean, default: false },
password: String,
});
Token Model
const tokenSchema = new mongoose.Schema({
_userId: { type: mongoose.Schema.Types.ObjectId, required: true, ref: 'User' },
token: { type: String, required: true },
expireAt: { type: Date, default: Date.now, index: { expires: 86400000 } }
});
Step 2: Login
exports.login = function(req, res, next) {
User.findOne({ email: req.body.email }, function(err, user) {
// error occur
if(err){
return res.status(500).send({msg: err.message});
}
// user is not found in database i.e. user is not registered yet.
else if (!user){
return res.status(401).send({ msg:'The email address ' + req.body.email + ' is not associated with any account. please check and try again!'});
}
// comapre user's password if user is find in above step
else if(!Bcrypt.compareSync(req.body.password, user.password)){
return res.status(401).send({msg:'Wrong Password!'});
}
// check user is verified or not
else if (!user.isVerified){
return res.status(401).send({msg:'Your Email has not been verified. Please click on resend'});
}
// user successfully logged in
else{
return res.status(200).send('User successfully logged in.');
}
});
});
Step 3: Sign Up
exports.signup = function(req, res, next) {
User.findOne({ email: req.body.email }, function (err, user) {
// error occur
if(err){
return res.status(500).send({msg: err.message});
}
// if email is exist into database i.e. email is associated with another user.
else if (user) {
return res.status(400).send({msg:'This email address is already associated with another account.'});
}
// if user is not exist into database then save the user into database for register account
else{
// password hashing for save into databse
req.body.password = Bcrypt.hashSync(req.body.password, 10);
// create and save user
user = new User({ name: req.body.name, email: req.body.email, password: req.body.password });
user.save(function (err) {
if (err) {
return res.status(500).send({msg:err.message});
}
// generate token and save
var token = new Token({ _userId: user._id, token: crypto.randomBytes(16).toString('hex') });
token.save(function (err) {
if(err){
return res.status(500).send({msg:err.message});
}
// Send email (use credintials of SendGrid)
var transporter = nodemailer.createTransport({ service: 'Sendgrid', auth: { user: process.env.SENDGRID_USERNAME, pass: process.env.SENDGRID_PASSWORD } });
var mailOptions = { from: 'no-reply#example.com', to: user.email, subject: 'Account Verification Link', text: 'Hello '+ req.body.name +',\n\n' + 'Please verify your account by clicking the link: \nhttp:\/\/' + req.headers.host + '\/confirmation\/' + user.email + '\/' + token.token + '\n\nThank You!\n' };
transporter.sendMail(mailOptions, function (err) {
if (err) {
return res.status(500).send({msg:'Technical Issue!, Please click on resend for verify your Email.'});
}
return res.status(200).send('A verification email has been sent to ' + user.email + '. It will be expire after one day. If you not get verification Email click on resend token.');
});
});
});
}
});
});
Step 4: Verify Account
// It is GET method, you have to write like that
// app.get('/confirmation/:email/:token',confirmEmail)
exports.confirmEmail = function (req, res, next) {
Token.findOne({ token: req.params.token }, function (err, token) {
// token is not found into database i.e. token may have expired
if (!token){
return res.status(400).send({msg:'Your verification link may have expired. Please click on resend for verify your Email.'});
}
// if token is found then check valid user
else{
User.findOne({ _id: token._userId, email: req.params.email }, function (err, user) {
// not valid user
if (!user){
return res.status(401).send({msg:'We were unable to find a user for this verification. Please SignUp!'});
}
// user is already verified
else if (user.isVerified){
return res.status(200).send('User has been already verified. Please Login');
}
// verify user
else{
// change isVerified to true
user.isVerified = true;
user.save(function (err) {
// error occur
if(err){
return res.status(500).send({msg: err.message});
}
// account successfully verified
else{
return res.status(200).send('Your account has been successfully verified');
}
});
}
});
}
});
});
Step 5: Resend Link
exports.resendLink = function (req, res, next) {
User.findOne({ email: req.body.email }, function (err, user) {
// user is not found into database
if (!user){
return res.status(400).send({msg:'We were unable to find a user with that email. Make sure your Email is correct!'});
}
// user has been already verified
else if (user.isVerified){
return res.status(200).send('This account has been already verified. Please log in.');
}
// send verification link
else{
// generate token and save
var token = new Token({ _userId: user._id, token: crypto.randomBytes(16).toString('hex') });
token.save(function (err) {
if (err) {
return res.status(500).send({msg:err.message});
}
// Send email (use credintials of SendGrid)
var transporter = nodemailer.createTransport({ service: 'Sendgrid', auth: { user: process.env.SENDGRID_USERNAME, pass: process.env.SENDGRID_PASSWORD } });
var mailOptions = { from: 'no-reply#example.com', to: user.email, subject: 'Account Verification Link', text: 'Hello '+ user.name +',\n\n' + 'Please verify your account by clicking the link: \nhttp:\/\/' + req.headers.host + '\/confirmation\/' + user.email + '\/' + token.token + '\n\nThank You!\n' };
transporter.sendMail(mailOptions, function (err) {
if (err) {
return res.status(500).send({msg:'Technical Issue!, Please click on resend for verify your Email.'});
}
return res.status(200).send('A verification email has been sent to ' + user.email + '. It will be expire after one day. If you not get verification Email click on resend token.');
});
});
}
});
});
You can take help from this link:https://medium.com/#slgupta022/email-verification-using-sendgrid-in-node-js-express-js-mongodb-c5803f643e09
I would like to present a slightly different approach from the ones proposed.
This method does not put the hash into the database (therefore less interaction with it)
You don't need to register the hash in the database. Here's an overview after receiving a registration request:
You encode the user id + registration time
You send the token to the user
When the user triggers his registration request, you decode the token.
Because The decoded token contains the user id + the time, you can
mark the user as registered by increasing their role
(registered, subscriber, admin, etc.) for instance
Translated into code, you would have something like this:
1- Encode the token
function encodeRegistrationToken()
{
// jsonweb automatically adds a key that determines the time, but you can use any module
const jwt = require('jsonwebtoken');
// The information we need to find our user in the database (not sensible info)
let info = {id: yourUserId};
// The hash we will be sending to the user
const token = jwt.sign(info, "yoursecretkey");
return token;
}
// ...
let token = encodeRegistrationToken();
2- Send token to the user via any appropriate way
// Your implementation of sending the token
sendTokenToUser(token);
3- Decode the token
function decodeRegistrationToken(token)
{
const jwt = require('jsonwebtoken');
let decoded = jwt.verify(token, "yoursecretkey");
let userId = decoded.id;
// Check that the user didn't take too long
let dateNow = new Date();
let tokenTime = decoded.iat * 1000;
// Two hours
let hours = 2;
let tokenLife = hours * 60 * 1000;
// User took too long to enter the code
if (tokenTime + tokenLife < dateNow.getTime())
{
return {
expired: true
};
}
// User registered in time
return {
userID
};
}
4 - Update your database
Upgrade the user role to subscriber
or
Set their "register" key to true
Quick note: You can further encode the user id when encoding your token if you want (it's easily accessible).
I spent a lot of time figuring out the perfect way to send confirmation mail. Here is the method I used.
Libraries
const jwt = require('jsonwebtoken');
const nodemailer = require("nodemailer");
Step 1
Encode the user id in a jwt token with an expiration date
var date = new Date();
var mail = {
"id": user.id,
"created": date.toString()
}
const token_mail_verification = jwt.sign(mail, config.jwt_secret_mail, { expiresIn: '1d' });
var url = config.baseUrl + "verify?id=" + token_mail_verification;
Step 2
Send the token to the user email address using nodemailer library
let transporter = nodemailer.createTransport({
name: "www.domain.com",
host: "smtp.domain.com",
port: 323,
secure: false, // use SSL
auth: {
user: "user#domain.com", // username for your mail server
pass: "Password", // password
},
});
// send mail with defined transport object
let info = await transporter.sendMail({
from: '"NAME" <user#domain.com>', // sender address
to: user.email, // list of receivers seperated by comma
subject: "Account Verification", // Subject line
text: "Click on the link below to veriy your account " + url, // plain text body
}, (error, info) => {
if (error) {
console.log(error)
return;
}
console.log('Message sent successfully!');
console.log(info);
transporter.close();
});
Step 3
Accept the verification link
app.get('/verify', function(req, res) {
token = req.query.id;
if (token) {
try {
jwt.verify(token, config.jwt_secret_mail, (e, decoded) => {
if (e) {
console.log(e)
return res.sendStatus(403)
} else {
id = decoded.id;
//Update your database here with whatever the verification flag you are using
}
});
} catch (err) {
console.log(err)
return res.sendStatus(403)
}
} else {
return res.sendStatus(403)
}
})
Step 4
Have a coffee and THANK ME for saving your so much time
PS: This nodemailer SMTP method will even work with your hosting. So no need to go for third party. You can also find ways to use gmail with nodemailer.
if you are just testing on your local machine, one simple way of understanding how to do it can be :
Assuming you already know sending mails through nodemailer..
Once user signs up, after storing sign-up data in your database, on your server side take user email from sign-up data received and a random generated number and build a custom url with the address of page where user will be directed after he/she clicks on the link given in mail.
var customUrl = "http://"+ your host + "/" + your verification web-page + "?email=" + userEmail + "&id=" + randomNumber;
An example can be:
var userEmail = someone#example.com
var host = localhost:8080
var directWebPage = verifyUserEmail.html
var randomNumber = // generate with math.random() // lets say 111
Putting in above format of customUrl it looks something like this
customUrl:http://localhost:8080/verifyUserEmail.htmlemail=someone#example.com&id=111
Save this customUrl somewhere (probably in your database)
Now, send an email to user with email body containing this cutomUrl link.
Click to verify your email
When user clicks on the link he/she will be directed to verifyUserEmail.html page and when that happens you can extract the page url containing email and id information
For example in angular I go like this-
var urlVerifyData = $location.url(); or $location.absUrl();
Now extract email form urlVerifyData string using javascript string methods
Request your server with this email and urlVerifyData
Now query your database for this email and verify previously stored customUrl with user's urlVerifyData
If they match, hola ! You got yourself a genuine user !!!
I came across a Reddit post where one explained that one click on the link is not sufficient and might lead to errors and a failure of the verification. The logic is simple and legit, when the email containing the link is received, there might be link scanners (bots) on the SMTP server (Outlook, Gmail etc). Just like when you past a link on major social platforms, there is always a bot that hits the link. I did not try it myself but I believe Outlook scans some links (when you copy past a link it is converted to a thumbnail with page's content).
So this process oblige you to do a verification by two steps, maybe when the user clicks, he needs to past his own password used for signup (looks fine). Or provide a one time password with the email so that the user along with the verification link (maybe split then re-concat) the same token you send for verification and ask the user to enter that second part (this seems easier).
function generateLink() {
var chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
var token = '';
for (var i = 16; i > 0; --i) {
var rand = Math.round(Math.random() * (chars.length - 1))
token += chars[rand];
}
var link = "http://localhost" + "/verify?id=" + token;
return link;
}
// npm install #sendGrid/mail --save
//library for generating link using SendGrid
const sgMail = require('#sendgrid/mail');
sgMail.setApiKey("SENDGRID_API_KEY"); //create an account on sendgrid and get an API key
// generated link is send to the user's email for email verification
let sendVerifyEmailLink = (req, res) => {
var link = generateLink();
const msg = {
to: 'test#gmail.com',
from: 'test#gmail.com',
subject: 'Account Verifictaion',
text: 'Hello,\n\n' + 'Please verify your account by clicking the link:\/\/\n',
html: 'Hello,\n\n <br> Please verify your account by clicking the link: \n <br> <strong><a href = ' + link + '>http:\/\/ Click here to verify the given Link </a></strong>.\n .<br>Thanks<br>',
};
sgMail.send(msg).then(() => { }, error => {
console.error(error);
if (error.response) {
console.error(error.response.body)
}
});
console.log(msg)
}

Posting to group using facebook nodejs sdk : OAuthException

I am trying to post to facebook group wall using nodejs sdk ( https://github.com/node-facebook/facebook-node-sdk )
This is a piece of code I am using :
Access token ( works fine ) :
FB.api('oauth/access_token', {
client_id: appId,
client_secret: appSecret,
grant_type: 'client_credentials'
}, function (res) {
if (!res || res.error) {
var errorMessage = !res ? 'Unkown error' : res.error;
log.error(site + " Failed to get fb access token " + errorMessage);
}
var accessToken = res.access_token;
FB.setAccessToken(accessToken);
});
Attempt to post :
var message = 'Hi from facebook-node-js';
FB.api( facebookGroupId + '/feed', 'POST', {
// access_token: appToken,
message: message
}, function (res) {
if (!res || res.error) {
console.error(!res ? 'error occurred' : res.error);
return;
}
console.log('Post Id: ' + res.id);
});
Which fails with :
{ message: '(#200) The user hasn\'t authorized the application to perform this action',
type: 'OAuthException',
code: 200,
fbtrace_id: 'xxxxx' }
Now , this being a server side app, I can not pop something up to request the permission . Can someone point me where I can assign the needed permission to the app ?
You have to have access-token to get this done, It is obvious no user would like any app to save her facebook credentials. So right approach is to first pop-up that yields access token and make use of it for posting.
You need the user to grant user_managed_groups and publish_actions permission to do so. Keep in mind that both permissions need to be reviewed by Facebook.

Use the Mailchimp API

I'd like to use the Mailchimp Node.js API in my Parse Cloud Hosting app to subscribe a user to a mailing list. Parse doesn't support NPM but, given that the Mailchimp API has no dependencies, I thought I'd be able to copy the code into my project. However, the Mailchimp API uses the "https" module which Parse doesn't support.
Does anyone know of a way around this?
I've been unable to use the Mailchimp API directly but the REST API is pretty easy to use.
In main.js, create a Cloud Function. Enter your API key and update the REST URL to point at the correct Mailchimp data center (http://apidocs.mailchimp.com/api/2.0/)
var mailchimpApiKey = "<<REPLACE_WITH_YOUR_KEY>>";
Parse.Cloud.define("SubscribeUserToMailingList", function(request, response) {
if (!request.params ||
!request.params.email){
response.error("Must supply email address, firstname and lastname to Mailchimp signup");
return;
}
var mailchimpData = {
apikey : mailchimpApiKey,
id : request.params.listid,
email : {
email : request.params.email
},
merge_vars : request.params.mergevars
}
var url = "https://<<REPLACE_WITH_DATA_CENTRE>>.api.mailchimp.com/2.0/lists/subscribe.json";
Parse.Cloud.httpRequest({
method: 'POST',
url: url,
body: JSON.stringify(mailchimpData),
success: function(httpResponse) {
console.log(httpResponse.text);
response.success("Successfully subscribed");
},
error: function(httpResponse) {
console.error('Request failed with response code ' + httpResponse.status);
console.error(httpResponse.text);
response.error('Mailchimp subscribe failed with response code ' + httpResponse.status);
}
});
});
Then, in the code which calls this function... (replace your list ID)
Parse.Cloud.run("SubscribeUserToMailingList", {
listid : "<<REPLACE_WITH_LIST_ID>>",
email : email,
mergevars : {
FNAME : firstName,
LNAME : lastName
}
})
.then(function(success){
console.log("Successfully subscribed");
// ...
},
function(error){
console.log("Unable to subscribe");
// ...
});
Install mailchimp in your project
npm install mailchimp-api
From client controller call the server-controller with required data
Don't forget to add $http to the top of controller
$http({
method : 'POST',
url : '/mailchimp-users/subscribe',
data : {user:this.name}}).
success(function(response) {
console.log("hai this is basic test" + response);
$scope.send = response.message;
}).error(function(response) {
$scope.error = response.message;
});
In server controller
Add this to the beginning of page
var MailchimpUser = mongoose.model('MailchimpUser'),
_ = require('lodash'),
mcapi = require('mailchimp-api');
var apiKey = '4bf6fb8820c333da4179216c3c2ef8fb-us10';
// Change this to your Key
var listID = 'ebbf193760';
var mc = new mcapi.Mailchimp(apiKey, {version: '2.0'});
Add this function
exports.subscribe = function(req, res) {
var entry = req.body.user;
var mcReq = {
apikey: '4bf6fb8820c333da4179216c3c2ef8fb-us10',
id: 'ebbf193760',
email: {email: entry + '#gmail.com'},
merge_vars: {
FNAME: 'subscriber-first-name',
LNAME: 'subscriber-last-name'
},
'double_optin': false,
'send_welcome': true
}
// submit subscription request to mail chimp
mc.lists.subscribe(mcReq, function(data) {
console.log(data);
}, function(error) {
console.log(error);
});
};
Add this route your route file
app.route('/mailchimp-users/subscribe')
.post(mailchimpUsers.subscribe);
Here's how I got it to work using the MailChimp API v3.0, the method below supports adding/updating a subscriber, as well as adding/removing him to/from a Group!
Prerequisite:
You need to get an MD5 hash method to convert the user's email into a hash.
Here's the one I used: http://www.webtoolkit.info/javascript-md5.html#.Vuz-yjZOwXV
Copy the code in the link, and paste it into a newly created file, name it "md5js.js" for example.
Update the code you copied to start with exports.MD5 = function (string) {
You can test the conversion you got from the copy/pasted module by comparing the result with this online tool: http://www.miraclesalad.com/webtools/md5.php
var jsmd5 = require('cloud/md5js.js');
// here replace that with your own data center (by looking at your API key).
var datacenter = "us13";
var MAILCHIMP_URL = "https://<any_string>:<apikey>#" + datacenter + ".api.mailchimp.com/3.0/";
var MAILCHIMP_LIST_NEWSLETTER_ID = <yourlistId>;
Parse.Cloud.define("SubscribeUserToMailingList", function(request, response) {
if (!request.params ||
!request.params.email){
response.error("Must supply email address, firstname and lastname to Mailchimp signup");
return;
}
var email = request.params.email;
var firstName = request.params.firstname;
var lastName = request.params.lastname;
// this converts the email string into an MD5 hash.
// this is Required if you want to use a "PUT" which allows add/update of an entry, compared to the POST that allows only adding a new subscriber.
var emailHash = jsmd5.MD5(email);
var mailchimpData = {
'email_address': email,
'status': "subscribed",
'merge_fields': {
'FNAME': firstName,
'LNAME': lastName
},
'interests': {
"<groupID>": true // optional, if you want to add the user to a "Group".
}
};
var url = MAILCHIMP_URL + "lists/" + MAILCHIMP_LIST_NEWSLETTER_ID + "/members/" + emailHash;
// using a "PUT" allows you to add/update an entry.
Parse.Cloud.httpRequest({
method: 'PUT',
url: url,
body: JSON.stringify(mailchimpData),
success: function(httpResponse) {
console.log(httpResponse.text);
response.success("Successfully subscribed");
},
error: function(httpResponse) {
console.error('Request failed with response code ' + httpResponse.status);
console.error(httpResponse.text);
response.error('Mailchimp subscribe failed with response code ' + httpResponse.status);
}
});
});

Resources