node.js sending by request module - node.js

I need to send a lot of messages. I use external api and request module:
email.js
var request = require('request');
module.exports = function(subject, email){
var message = ... ;
var options = {
method: 'POST',
url: 'https://api.emails.net.com/api/sendmail',
form: {
smtp_account: smtp,
to: {},
subject: subject,
html: message,
from: 'myapp#email.com',
from_name: 'Myapp'
},
headers: {
'Authorization': ' ... '
}
};
request(options, function (error, response) {
if (!error && response.statusCode === 200) return true;
return false;
});
};
And in another place:
var sendEmail = require('../email');
...
for( ... ){
if(sendEmail(subject, email)){
//do something
}
}
After success i want to do something but request return nothing. Is any way to check if post was success and do something in place where I require email module? I'm sending emails in loop and i must check one by one.

You can do something like this
var request = require('request');
var Promise = require('bluebird');
var email = function () {
return {
send: function (subject, email) {
var message = "test";
var options = {
method: 'POST',
url: 'https://api.emails.net.com/api/sendmail',
form: {
smtp_account: "smtp",
to: {},
subject: subject,
html: message,
from: 'myapp#email.com',
from_name: 'Myapp'
},
headers: {
'Authorization': ""
}
};
return new Promise(function (resolve, reject) {
request(options, function (error, response) {
if (!error && response.statusCode === 200) {
resolve(true);
} else {
reject(err);
}
});
})
}
}
};
module.exports = email();
And then you can consume this as below
for (var i = 0; i < 10; i++) {
console.log(i);
email
.send("test", "test#gmail.com")
.then(function (status) {
///Do what ever u want to do
})
.catch(function (err) {
console.log(err);
});
}

Related

how to get data outside request

I have a scenario where i need to take response (body) of request method outside request. How can i do it?
request.post({
url: 'http://localhost/api/messages',
form: { key: message }
}, function (err, httpResponse, body) {
tmsg = body;
})
console.log(tmsg);
I need this tmsg outside for next processing, Actual scenario is as below.
app.post('/incomemsg', function (req, res) {
var mediaCount = req.body.NumMedia;
if (mediaCount == 0) {
//var twiml = getResponse(message);
var twiml = new MessagingResponse();
request.post({
url: 'http://localhost:3978/api/messages',
form: { key: message }
}, function (err, httpResponse, body) {
tmsg = body;
})
console.log(tmsg);
}else {
//dosomething which outputs tmsg
}
res.writeHead(200, { 'Content-Type': 'text/xml' });
res.end(tmsg.toString());
});
The problem is you are trying to assign value to a global variable in request.post's callback() which is only called after request.post is executed by Asynchronous logic(API calls are all async), so a better way would be to promisify request.post and await the request.post to make it seem synchronous.
const requestPromisified = requestObject =>
new Promise((resolve, reject) => {
request.post(requestObject, function(err, httpResponse, body) {
if (err) {
reject(err);
}
resolve(body);
});
});
const body = await requestPromisified({
method: "POST",
url: "http://localhost/api/messages",
form: { key: message }
});
You only can do something with tmsg when you made the request so you need to rearrange your code like this:
app.post('/incomemsg', function (req, res) {
var mediaCount = req.body.NumMedia;
var twiml = new MessagingResponse();
request.post({
url: 'http://localhost:3978/api/messages',
form: { key: message }
}, function (err, httpResponse, body) {
tmsg = body;
console.log(tmsg);
if (mediaCount === 0) {
//do something with tmsg
} else {
//do something else with tmsg
}
res.writeHead(200, { 'Content-Type': 'text/xml' });
res.end(tmsg.toString());
});
});
Otherwise tmsg will be null because there was no request made to fill that variable.

method returning value before completing function execution

function rip(intent_update, output_rnr){
var headers_conv = {
'Content-Type': 'application/json',
'Accept': 'application/json',
'Authorization': 'Basic YWFjZWU2M'
};
var dataString = '{ "output": { "text": { "values": [' + output_rnr + '] } } }';
var options_conv = {
url: 'https://watson-api-explorer.mybluemix.net/'+ intent_update + '?version=2017-05-26',
method: 'POST',
headers: headers_conv,
body: dataString
};
function callback_conv(error, response, body) {
if (!error && response.statusCode === 200) {
console.log(body);
}
}
request(options_conv, callback_conv);
}
app.post('/api/message', function(req, res) {
var workspace = process.env.WORKSPACE_ID || '<workspace-id>';
}
var payload = {
workspace_id: workspace,
context: req.body.context || {},
input: req.body.input || {}
};
// Send the input to the conversation service
conversation.message(payload, function(err, data) {
if (err) {
return res.status(err.code || 500).json(err);
}
return res.json(updateMessage(payload, data));
});
});
function updateMessage(input, response) {
if (!response.output) {
response.output = {};
} else {
if (response.intents.length > 0 && (response.intents[0].intent === 'rnr')) {
response = getCalculationResult(response);
}
}
return response;
}
function getCalculationResult(response){
var result = '';
if(response.intents[0].intent === 'rnr'){
var question = response.input.text;
var query = qs.stringify({q: question, ranker_id: ranker_id, fl: 'contentHtml'});
solrClient.get('fcselect', query, function(err, searchResponse) {
if(err) {
console.log('Error searching for documents: ' + err);
}
else {
result = JSON.stringify(searchResponse.response.docs[0].contentHtml, null, 1);
rip(response.intents[0].intent, result);
}
});
}
/*
* if(result === ''){
setTimeout(function(){
response.output.text[0] = result + response.input.text;
}, 15000);
}
else{
var output = result + response.input.text;
response.output.text[0] = output;
}
*/
response.output[0].text = response.output[0].text + result;
return response;
}
This code is returning values from functions before completing execution of method. I have tried to use setTimeout but still the result is same. How can re write my methods to wait until method execution is completed before a value is returned. I have also tried writing with call back but unable to get desired result(may be i am implementing call back in wrong way)
You can use Promise.all, and say with one custom code something like: "Just if these functions are completed, then, do this".
For example...
var message = "";
promise1 = new Promise((resolve, reject) => {
setTimeout(() => {
message += "my";
resolve(message);
}, 2000)
})
promise2 = new Promise((resolve, reject) => {
setTimeout(() => {
message += " first";
resolve(message);
}, 2000)
})
promise3 = new Promise((resolve, reject) => {
setTimeout(() => {
message += " promise";
resolve(message);
}, 2000)
})
var printResult = (results) => {console.log("Results = ", results, "message = ", message)}
function main() {
// See the order of promises. Final result will be according to it
Promise.all([promise1, promise2, promise3]).then(printResult);
Promise.all([promise2, promise1, promise3]).then(printResult);
Promise.all([promise3, promise2, promise1]).then(printResult);
console.log("\"\"" + message);
}
main();
See the Official documentation about Promises here.
See this tutorial to understand with examples about Promises.
You can use simple callbacks to avoid this async nature.
function rip(intent_update, output_rnr){
var headers_conv = {
'Content-Type': 'application/json',
'Accept': 'application/json',
'Authorization': 'Basic YWFjZWU2M'
};
var dataString = '{ "output": { "text": { "values": [' + output_rnr + '] } } }';
var options_conv = {
url: 'https://watson-api-explorer.mybluemix.net/'+ intent_update + '?version=2017-05-26',
method: 'POST',
headers: headers_conv,
body: dataString
};
function callback_conv(error, response, body) {
if (!error && response.statusCode === 200) {
console.log(body);
}
}
request(options_conv, callback_conv);
}
app.post('/api/message', function(req, res) {
var workspace = process.env.WORKSPACE_ID || '<workspace-id>';
}
var payload = {
workspace_id: workspace,
context: req.body.context || {},
input: req.body.input || {}
};
// Send the input to the conversation service
conversation.message(payload, function(err, data) {
if (err) {
return res.status(err.code || 500).json(err);
}
updateMessage(payload,data,function(resultData){
if(resultData){
return res.json(resultData);
}
});
});
});
function updateMessage(input, response,callback) {
if (!response.output) {
response.output = {};
} else {
if (response.intents.length > 0 && (response.intents[0].intent === 'rnr')) {
getCalculationResult(response,function(result){
response=result;
if(callback){
callback(response);
return response;
}
});
}
}
}
function getCalculationResult(response,callback){
var result = '';
if(response.intents[0].intent === 'rnr'){
var question = response.input.text;
var query = qs.stringify({q: question, ranker_id: ranker_id, fl: 'contentHtml'});
solrClient.get('fcselect', query, function(err, searchResponse) {
if(err) {
console.log('Error searching for documents: ' + err);
}
else {
result = JSON.stringify(searchResponse.response.docs[0].contentHtml, null, 1);
rip(response.intents[0].intent, result);
}
});
if(callback){
response.output[0].text = response.output[0].text + result;
callback(response);
return response;
}
}
}

Sending response to client from within the request.post callback in koa

I have this koa route /landing which is resulting in 404.
function* landing() {
//this.body = "response"; //1
var request = require('request');
request.post('http://url.com/resource',
{ json: { key: "post data"} },
function (error, response, body) {
if (!error && response.statusCode == 200) {
var token = body.data;
getListByToken(token, function(list){
this.body = list; //2
});
}
});
}
See comment in the top //1 - that is how you define body of a response in koa in a route. Instead of //1 I want to send response from //2 i.e. from within that request.get.
When a user is routed to /landing a post request has to fetch some data from a url. That fetched data is to be used by getListByToken to bring some other data, list, which should be sent to the user. The above code should have worked but it results in 404 Not Found response by koa.
We can use promises, simple and clean way of managing asynchronous codes.
var request = require('request-promise');
. . .
function* landing() {
try {
let response = yield request( {
method: 'POST',,
url: 'http://url.com/resource',
headers: { 'content-type': 'application/json' },
body: JSON.stringify( { json: { key: "post data"} } )
} );
this.body = yield new Promise( function( resolve, reject ) {
if ( response.statusCode == 200 ) {
getListByToken( response.body.token, function( list ) {
resolve( list );
} );
}
} );
} catch ( err ) {
/* do something with your errors */
}
}
Solved it with q. It makes koa hold response until yield happens.
var q = require('q');
function* landing() {
var deferred = q.defer();
var request = require('request');
request.post('http://url.com/resource',
{ json: { key: "post data"} },
function (error, response, body) {
if (!error && response.statusCode == 200) {
var token = body.data;
getListByToken(token, function(list){
deferred.resolve(repolist);
});
}
});
this.body = yield deferred.promise;
}
Thanks to https://stackoverflow.com/a/22159513/1128379

Auto append unwanted character in nodejs put request

I have an api to file upload on Bluemix Object Storage by using request module. All are good but there is some unwanted character which append automatically.
example:
--38oi85df-b5d1-4d42-81ce-c547c860b512 //this is unwanted character
Email
abc#gmail.com
hsl#gmsl.com
pjeyjle#cse.com
--38oi85df-b5d1-4d42-81ce-c547c860b512-- // this is unwanted character
Here is my code:-
import request from 'request';
exports.putObjectStorageFile = function(authToken, file, csv, cb) {
var s = new stream.Readable();
s._read = function noop() {};
s.push(csv); //csv is string
s.push(null);
var options = {
url: 'https://xxxx.objectstorage.open.xxxx.com/v1/AUTH_' + config.objectStorage.projectId + '/xxxx/' + file,
method: 'PUT',
preambleCRLF: true,
postambleCRLF: true,
encoding: 'utf-8',
headers: {
'Content-Type': 'text/html; charset=UTF-8',
'Content-Length': 1,
'X-Auth-Token': authToken
},
multipart: {
chunked: false,
data: [
{ body: s }
]
} };
function callback(error, response) {
if (error) cb(error);
if (!error && response.statusCode == 201) {
cb(null);
}
}
request(options, callback);
You are sending a multipart message with a preambleCRLF and postambleCRLF in your request which is causing those lines.
You should use the pkgcloud library for uploading data to Object Storage:
https://github.com/pkgcloud/pkgcloud
Below is a sample of using pkgcloud with the Object Storage service on Bluemix (credentials from VCAP).
(function (module) {
var pkgcloud = require('pkgcloud'),
fs = require('fs');
function ObjectStorage(container, credentials) {
this.container = container;
this.config = {
provider: 'openstack',
useServiceCatalog: true,
useInternal: false,
keystoneAuthVersion: 'v3',
authUrl: credentials.auth_url,
tenantId: credentials.projectId,
domainId: credentials.domainId,
username: credentials.username,
password: credentials.password,
region: credentials.region
};
this.client = pkgcloud.storage.createClient(this.config);
}
ObjectStorage.prototype.validate = function () {
return new Promise(function (resolve, reject) {
this.client.auth(function (error) {
if (error) {
return reject(error);
}
resolve();
});
}.bind(this));
};
ObjectStorage.prototype.makeContainer = function () {
return new Promise(function (resolve, reject) {
this.client.createContainer({name: this.container}, function (error) {
if (error) {
return reject(error);
}
return resolve();
});
}.bind(this));
};
ObjectStorage.prototype.uploadFile = function (path, name) {
return new Promise(function (resolve, reject) {
var myPicture = fs.createReadStream(path);
var upload = this.client.upload({
container: this.container,
remote: name
});
upload.on('error', function (error) {
reject(error);
});
upload.on('success', function (file) {
resolve(file);
});
myPicture.pipe(upload);
}.bind(this));
};
module.exports = ObjectStorage;
})(module);
I got that lines due to sending data with multipart. I found a solution by adding just content-type,content-lenght and send data in body i.e,
var options = {
url: 'https://dal.objectstorage.open.softlayer.com/v1/AUTH_' + config.objectStorage.projectId + '/nrich-storage/' + file,
method: 'PUT',
headers: {
'Content-Type': 'text/csv',
'Content-Length': csv.length,
'X-Auth-Token': authToken
},
body:csv
};
function callback(error, response) {
if (error) cb(error);
if (!error && response.statusCode == 201) {
cb(null);
}
}
request(options, callback);

api call to sinch as promise

I've tested the interface and made some changes to use with my sailsjs (version 11) on the backend. In this case I use a sails service and things seem fine but I always get back a pending status.
```
SinchService.js
var sinchAuth = require('sinch-auth');
var request = require('request');
var sinchMessaging = {};
var Promise = require('bluebird');
//sinchMessaging.sendMessage = function (phoneNumber, message) {
//exports.sendMessage = function (phoneNumber, message) {
module.exports = {
sendMessage: function (phoneNumber, message) {
var auth = sinchAuth();
if (!auth) {
throw new Error("No Authorization was provided");
}
var options = {
method: 'POST',
url: "https://messagingApi.sinch.com/v1/sms/" + phoneNumber,
headers: {
"Content-Type": "application/json",
"Authorization": auth
},
body: "{\"Message\":\"" + message + "\"}"
// body: {"Message" : message }
};
return new Promise(function (resolve, reject) {
request(options, function (error, response, body) {
sails.log("Finished with call");
if (error) {
sails.log(error);
throw error;
}
else {
sails.log("Finished with body ", body);//.MessageId
return resolve(response.body);
}
});
})
},
getStatus: function (messageId) {
var auth = sinchAuth();
if (!auth) {
throw new Error("No Authorization was provided");
}
var options = {
method: 'GET',
url: "https://messagingApi.sinch.com/v1/sms/" + messageId,
headers: {
"Content-Type": "application/json",
"Authorization": auth
}
};
return new Promise(function (resolve, reject) {
request(options, function (error, response, body) {
sails.log("Finished with call");
if (error) {
sails.log(error);
throw error;
}
else {
return resolve(response.body);
}
});
})
}
};
```
agendaService.js
var jsonObjS;
SinchService.sendMessage(phoneNumber, message).then(function (results) {
var jsonObj = JSON.parse(results);
console.log('results sendMessage ', jsonObj.messageId);
if (jsonObj.messageId!==undefined){
SinchService.getStatus(jsonObj.messageId).then(function (results_s) {
jsonObjS = JSON.parse(results_s);
console.log('results getStatusS ', jsonObjS.status);
SinchService.getStatus(jsonObjS.messageId).then(function (results_s) {
var jsonObjS = JSON.parse(results_s);
console.log('results getStatusS ', jsonObjS.status);
});
});
```
Pending will always be the first status, query again after some time to see the status of of the message.

Resources