Node JS Imap-simple disconnect error after some time - javascript

I fetch unread messages in a middle ware that triggers my function every five minutes. It is successfully completing the request but eventually It triggers and crashes my nodejs process. With an error of:
Error: This socket has been ended by the other party
I have tried adding all these catches and error handling but It seams it eventually times out my connection to my inbox? Am I not reconnecting on every request to access my inbox?
Here is my code (also I have tried with authTimeout: 3000 in the config before anyone suggests that is the issue):
imap: {
user: 'myemail#gmail.com',
password: 'myPW',
host: 'imap.gmail.com',
port: 993,
tls: true,
keepalive: true
}
imaps.connect(settings.emailConfig).then(function (connection) {
return connection.openBox('INBOX').then(function () {
var searchCriteria = ['UNSEEN'];//only grab unread messages in LTS email
var fetchOptions = {
bodies: ['HEADER', 'TEXT', ''],
markSeen: true//mark as read
};
return connection.search(searchCriteria, fetchOptions).then(function (messages) {
console.log('looking for unread messages')
if (messages.length > 0) {
console.log('unread messages to save')
console.log('looking at messages : ' + util.inspect(messages, { depth: null }))
var saveUnreadEmais = messages.map(function (item) {//resolve each promise of unread message
var all = _.find(item.parts, { "which": "" })
var id = item.attributes.uid;
var idHeader = "Imap-Id: " + id + "\r\n";
simpleParser(idHeader + all.body, (err, mail) => {
var BarCode = "";
var subject = mail.subject;
var to = mail.to.value[0].address;
var from = mail.from.value[0].address;
var text = mail.text;
if (mail.subject.includes('Barcode :')) {//if the message to the system includes BarCode in the subject line grab it
var split = mail.subject.split(':');
BarCode = split[1];
}
if (!subject) {
subject = "LTS Email Recieved - Barcode : " + BarCode;
}
if (!text) {
text = "LTS auto email"
}
var newrec = {};
newrec.MessageDate = new Date();
newrec.MessageFor = to;
newrec.MessageFrom = from;
newrec.Message = text;
newrec.MessageAbout = BarCode;
newrec.MessageSubject = subject;
newrec.MessageStatusCode = 1;//1 sent, 2 read, 3 saved, -1 deleted
//console.log('saving message with details of : ' + util.inspect(newrec, { depth: null }))
return db.knex('dbo.PersonnelMessages').insert(newrec).then((data) => {
return "sent";
});
});
});
return Promise.all(saveUnreadEmais).then(() => {
//do anything you want after saving all unred emails to our db.
}).catch((err) => { console.log("error : " + err) })
}
else {
console.log('no new emails')
}
}).catch((err) => { console.log("error : " + err) })
}).catch((err) => { console.log("opening inbox error : " + err) })
}).then(function () {
console.log('In the INBOX');
}).catch(function (e) {
console.log('error : ' + e);
});

Related

Google Cloud Function frozen for over minute

have a strange thing happening running a Google cloud function. The function starts and logs the user id and job id as expected. Then it calls firestore db and basically sits there for 1 minute, sometimes 2 before it executes the first call... It was even timing out on 240 seconds.
const AWS = require('aws-sdk');
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp();
exports.run = functions.https.onCall((data, context) => {
var id = data.id;
var userid = data.uid;
var retry = data.retry;
var project;
var db = admin.firestore();
var storage = admin.storage();
console.log("Starting Collect");
console.log("UID: " + userid);
console.log("id ID: " + id);
// Times out on this call
db.collection("users").doc(userid).collection("ids").doc(id).get().then(function(doc) {
console.log("Loaded DB");
project = doc.data();
createexport();
}).catch(function(err) {
console.log(err);
error('Loading DB Error, ' + err, false);
});
function createexport() {
db.collection("exports").doc(id).set({
status: 'Collecting',
stage: 'Export Checker',
percent: 0,
id: id,
}).then(function() {
console.log("Creating Export");
setdb();
}).catch(function(err) {
error("Error creating export in database :" + err, true)
});
}
function setdb() {
db.collection("users").doc(userid).collection("ids").doc(id).update({
status: 'Analyzing Files',
stage: 'Collecting'
}).then(function() {
getaudio();
}).catch(function(err) {
error("Error updating users id in database :" + err, true)
});
}
function getaudio() {
const from = userid + '/projects/' + project.originalproject.id + '/audio.' + project.originalproject.extension;
const to = userid + '/' + id + '/audio.' + project.originalproject.extension;
storage.bucket('---------').file(from).copy(storage.bucket('---------').file(to)).then(function() {
console.log("Collecting files");
copy2();
}).catch(function(err) {
error('Collecting Audio Error, ' + err, true);
});
}
function copy2() {
const from = userid + '/projects/' + project.originalproject.id + '/overlay.png';
const to = userid + '/' + id + '/overlay.png';
storage.bucket('--------.appspot.com').file(from).copy(storage.bucket('---------').file(to)).then(function() {
updateexport();
}).catch(function(err) {
error('Collecting Overlay Error, ' + err, true);
});
}
function updateexport() {
db.collection("exports").doc(id).update({ status: "Waiting" }).then(function() {
console.log("All files collected");
return { status: 'Success' };
}).catch(function(err) {
error("Error creating export entry in database :" + err, true)
});
}
function error(evt, evt2) {
AWS.config.update({ region: "us-east-1" });
var html;
var sub = 'Error with id ' + id;
console.log(evt);
if (evt2) {
db.collection('users').doc(userid).collection('ids').doc(id).update({
status: 'Error'
}).catch(function(err) {
console.log(err);
});
db.collection("exports").doc(id).update({
status: 'Error',
stage: 'Collecting',
error: evt,
}).catch(function(err) {
console.log(err);
});
html = `
Username: ${project.username} <br>
UserID: ${userid} <br>
Email: ${project.email} <br>
id: ${id}
`
} else {
html = `id: ${id}<br>
UserID: ${userid} <br>
Message: Error logged was: ${evt}
`
}
var params = {
Destination: {
ToAddresses: [
'errors#mail.com'
]
},
Message: {
Body: {
Html: {
Charset: "UTF-8",
Data: html
},
},
Subject: {
Charset: 'UTF-8',
Data: sub
}
},
Source: 'errors#mail.com',
ReplyToAddresses: [
project.email
],
};
var sendPromise = new AWS.SES({
apiVersion: "2010-12-01",
"accessKeyId": "-----------",
"secretAccessKey": "------------------------",
"region": "--------",
}).sendEmail(params).promise();
sendPromise.then(function(data) {
return { data: data };
}).catch(function(err) {
return { err: err };
});
}
});
Seems to me to be way too long for a database call of only a few kb. I will attach the cloud log to show time difference. After this initial slump it then performs as expected.
Cloud log image
Anyone got any ideas as to why this could be happening? Many thanks...
Your function is appearing to hang because it isn't handling promises correctly. Also, it doesn't appear to be sending a specific response to the client app. The main point of callable functions is to send a response.
I suggest reviewing the documentation, where you will learn that callable functions are required to return a promise that resolves with an object to send to the client app, after all the async work is complete.
Minimally, it will take a form like this:
return db.collection("users").doc(userid).collection("files").doc(id).get().then(function(doc) {
console.log("Loaded DB");
project = doc.data();
return { "data": "to send to the client" };
}
Note that the promise chain is being returned, and the promise itself resolves to an object to send to the client.

Unable to switch user to root using Node.js ssh2 module

Trying to SSH to a server and able to. However, when I try to run sudo command it prompts me to enter the password of the userid mentioned. How do I prevent any keyboard interruption and hardcode the password so it doesn't prompt for password.
server.js
const { Client } = require('ssh2');
const conn = new Client();
conn.on('ready', () => {
console.log('Client :: ready');
conn.exec('sudo ls -lrt',{ stdin: 'password\n', pty: true }, (err, stream) => {
if (err) throw err;
stream.on('close', (code, signal) => {
console.log('Stream :: close :: code: ' + code + ', signal: ' + signal);
conn.end();
}).on('data', (data) => {
console.log('STDOUT: ' + data);
}).stderr.on('data', (data) => {
console.log('STDERR: ' + data);
});
});
}).connect({
host: 'hostname',
port: 22,
username: 'user1',
password: 'password'
});
The prompt I get:
STDOUT: [sudo] password for user1:
STDOUT:
sudo: timed out reading password
The below code works for me.
const Client = require('ssh2').Client;
const conn = new Client();
const encode = 'utf8';
const connection = {
host: 'hostname.foo.com',
username: 'iamgroot',
password: 'root#1234'
}
conn.on('ready', function() {
// Avoid the use of console.log due to it adds a new line at the end of
// the message
process.stdout.write('Connection has been established');
let password = 'root#1234';
let command = '';
let pwSent = false;
let su = false;
let commands = [
`ls -lrt`,
`sudo su - root`,
`ls -lrt`
];
conn.shell((err, stream) => {
if (err) {
console.log(err);
}
stream.on('exit', function (code) {
process.stdout.write('Connection closed');
conn.end();
});
stream.on('data', function(data) {
process.stdout.write(data.toString(encode));
// Handles sudo su - root password prompt
if (command.indexOf('sudo su - root') !== -1 && !pwSent) {
if (command.indexOf('sudo su - root') > -1) {
su = true;
}
if (data.indexOf(':') >= data.length - 2) {
pwSent = true;
stream.write(password + '\n');
}
} else {
// Detect the right condition to send the next command
let dataLength = data.length > 2;
let commonCommand = data.indexOf('$') >= data.length - 2;
let suCommand = data.indexOf('#') >= data.length - 2;
console.log(dataLength);
console.log(commonCommand);
console.log(suCommand);
if (dataLength && (commonCommand || suCommand )) {
if (commands.length > 0) {
command = commands.shift();
stream.write(command + '\n');
} else {
// su requires two exit commands to close the session
if (su) {
su = false;
stream.write('exit\n');
} else {
stream.end('exit\n');
}
}
}
}
});
// First command
command = commands.shift();
stream.write(command + '\n');
});
}).connect(connection);

How can I setup anti-spam for my socket.io chatroom?

I want to add an anti-spam function in my socket.io chatroom using the socket-anti-spam module but I have no clue how to. I've tried a couple stuff, but they didn't seem to work.
If you can't help with the socket-anti-spam module, any other module is fine aswell. This version of my server.js has the anti-spam setup but it doesn't seem to work.
If you need any other information (which I doubt you'll need) like HTML or CSS, just comment and I'll update this question.
My server.js:
var PORT = process.env.PORT || 3000;
var express = require("express");
var app = express();
var http = require("http").Server(app);
var io = require("socket.io")(http);
var moment = require("moment");
var connectedUsers = {};
var prefix = "^";
var sysusername = "Twintails🎀";
function sleep(ms) {
var unixtime_ms = new Date().getTime();
while (new Date().getTime() < unixtime_ms + ms) {}
}
const SocketAntiSpam = require('socket-anti-spam')
const socketio = require('socket.io').listen(8080)
const socketAntiSpam = new SocketAntiSpam({
banTime: 30, // Ban time in minutes
kickThreshold: 2, // User gets kicked after this many spam score
kickTimesBeforeBan: 1, // User gets banned after this many kicks
banning: true, // Uses temp IP banning after kickTimesBeforeBan
io: socketio, // Bind the socket.io variable
})
app.use(express.static(__dirname + "/public"));
io.on("connection", function(socket) {
socketAntiSpam.event.on('ban', data => {
socket.emit("message", {
username: sysusername,
text: "A user was banned...",
timestamp: moment().valueOf()
});
})
console.log("A user is connected.");
socket.on("disconnect", function() {
var userData = connectedUsers[socket.id];
if (typeof userData !== "undefined") {
socket.leave(connectedUsers[socket.id]);
io.to(userData.room).emit("message", {
username: sysusername,
text: userData.username + " has left!",
timestamp: moment().valueOf()
});
delete connectedUsers[socket.id];
}
});
socket.on("joinRoom", function(req, callback) {
if (req.username.replace(/\s/g, "") !== "Twintails🎀") {
if (req.username.replace(/\s/g, "").length < 24) {
if (
req.room.replace(/\s/g, "").length > 0 &&
req.username.replace(/\s/g, "").length > 0
) {
var nameTaken = false;
Object.keys(connectedUsers).forEach(function(socketId) {
var userInfo = connectedUsers[socketId];
if (
userInfo.username.toUpperCase() === req.username.toUpperCase()
) {
nameTaken = true;
}
});
if (nameTaken) {
callback({
nameAvailable: false,
error: "This username is taken, please choose another one."
});
} else {
connectedUsers[socket.id] = req;
socket.join(req.room);
socket.broadcast.to(req.room).emit("message", {
username: sysusername,
text: req.username + " has joined!",
timestamp: moment().valueOf()
});
callback({
nameAvailable: true
});
}
} else {
callback({
nameAvailable: false,
error: "Please complete the forum."
});
}
} else {
callback({
nameAvailable: false,
error: "Please make a username less than 24 characters."
});
}
} else {
callback({
nameAvailable: false,
error: "Your username can't be: " + sysusername
});
}
});
socket.on("message", function(message, callback, req) {
if (message.text.length > null) {
if (message.text !== " ") {
if (message.text !== " ") {
if (message.text !== " ") {
if (message.text !== " ") {
if (message.text !== " ") {
if (message.text !== " ") {
if (message.text !== " ") {
if (message.text !== " ") {
if (message.text !== " ") {
if (message.text.length < 200) {
message.timestamp = moment().valueOf();
io.to(connectedUsers[socket.id].room).emit(
"message",
message
);
}
}
}
}
}
}
}
}
}
}
}
});
socket.emit("message", {
username: sysusername,
text: "Ask someone to join this chat room to start talking.",
timestamp: moment().valueOf()
});
socket.on("message", function(message) {
if (message.text === prefix + "discord") {
socket.emit("message", {
username: sysusername,
text: "Join the Twintails🎀 server here: https://discord.gg/fK9ynNq",
timestamp: moment().valueOf()
});
sleep(1000);
}
});
socket.on("message", function(message) {
if (message.text === prefix + "bot") {
socket.emit("message", {
username: sysusername,
text: "Coming soon...",
timestamp: moment().valueOf()
});
sleep(1000);
}
});
});
http.listen(PORT, function() {
console.log("Server started on port " + PORT);
});
Thanks!
you can store the messages that the user sends and prevent if the current message is like the previous one

Cloud Functions for Firebase - Send FCM message to multiple tokens

I have to send a message to many token when a node is created in my realtime database.
I use that's code, but any notification are lost (people not receive its).
exports.sendMessage = functions.database.ref('/messages/{messageId}')
.onCreate((snapshot, context) => {
const original = snapshot.val();
let msg = {
message: {
data: {
title: 'title2 test',
body: 'body2 test',
notify_type: 'chat_message',
notify_id: ((new Date()).getTime()).toString(),
},
apns: {
headers: {
'apns-priority': '10',
'apns-expiration': '0'
},
payload: {
aps: { contentAvailable: true, sound:'' },
'acme1': 'bar',
title: 'title test',
body: 'body test',
notify_type: 'chat_message',
notify_id: ((new Date()).getTime()).toString()
}
},
token: token
}
};
var query = firebase.database().ref("users");
return query.once("value")
.then(function(snapshot) {
snapshot.forEach(function(childSnapshot) {
var user = childSnapshot.val();
var token = user.token;
var username = user.username;
msg.message.token = token;
admin.messaging().send(msg.message).then((response) => {
console.log('message sent to '+username);
}).catch((error) => {
console.log(error);
});
});
});
});
Is the "return" Promise right ? I think I have to wait all "admin.messagging() Promise, but I don't know how can I do this.
Thank you so much.
This is how you send a FCM to an array of tokens:
return Promise.all([admin.database().ref(`/users/${user}/account/tokensArray`).once('value')]).then(results => {
const tokens = results[0];
if (!tokens.hasChildren()) return null;
let payload = {
notification: {
title: 'title',
body: 'message',
icon: 'icon-192x192.png'
}
};
const tokensList = Object.keys(tokens.val());
return admin.messaging().sendToDevice(tokensList, payload);
});
You can send notifications to an array of tokens. I am using this code to send notifications
return admin.messaging().sendToDevice(deviceTokenArray, payload, options).then(response => {
console.log("Message successfully sent : " + response.successCount)
console.log("Message unsuccessfully sent : " + response.failureCount)
});
I think you can find more information here
https://firebase.google.com/docs/cloud-messaging/admin/legacy-fcm
To return a Promise for all the send actions, modify your code to this:
return query.once("value")
.then(function(snapshot) {
var allPromises = [];
snapshot.forEach(function(childSnapshot) {
var user = childSnapshot.val();
var token = user.token;
var username = user.username;
msg.message.token = token;
const promise = admin.messaging().send(msg.message).then((response) => {
console.log('message sent to '+username);
}).catch((error) => {
console.log(error);
});
allPromises.push(promise);
});
return Promise.all(allPromises);
});

Error promise after publish data to MQTT broker in My Alexa Lambda node js

I have problem with my Lambda, actually in promise nodejs. I have wrote code like this in my Lambda:
'use strict'
const Alexa = require('alexa-sdk');
const mqtt = require('mqtt');
const APP_ID = undefined;
const WELCOME_MESSAGE = 'Welcome to the lamp control mode';
const WELCOME_REPROMT = 'If you new please say help'
const HELP_MESSAGE = 'In this skill you can controlling lamp to turn off or on, dim the lamp, change the lamp color and schedule the lamp';
const STOP_MESSAGE = 'Thanks for using this skill, Goodbye!';
const OFF_RESPONSE = 'Turning off the lamp';
const ON_RESPONSE = 'Turning on the lamp';
const DIM_RESPONSE = 'Dimming the lamp';
const CHANGE_RESPONSE = 'Changing the lamp color';
const AFTER_RESPONSE = 'Wanna control something again ?';
const handlers = {
'LaunchRequest': function () {
this.emit(':ask', WELCOME_MESSAGE, WELCOME_REPROMT);
},
'OnOffIntent' : function () {
var status = this.event.request.intent.slots.status.value;
var location = this.event.request.intent.slots.location.value;
console.log(status);
console.log(location);
if (status == 'on') {
// Promise Start
var mqttPromise = new Promise(function(resolve, reject) {
var options = {
port: '1883',
clientId: 'mqttjs_' + Math.random().toString(16).substr(2, 8),
username: 'username',
password: 'password',
};
var client = mqtt.connect('mqtt://broker-address', options)
client.on('connect', function() {
client.publish("lamp/status", status + ' ' + location, function() {
console.log("Message is published");
client.end();
resolve('Done Sending');
});
});
});
mqttPromise.then(
function(data) {
console.log('Function called succesfully', data);
this.emit(':ask', ON_RESPONSE, AFTER_RESPONSE);
}, function(err) {
console.log('An error occurred: ', err);
}
);
// Promise END
// this.emit(':ask', ON_RESPONSE, AFTER_RESPONSE);
// client.publish("lamp/status", status + ' ' + location);
} else if (status == 'off') {
this.emit(':ask', OFF_RESPONSE, AFTER_RESPONSE);
// client.publish("lamp/status", status + ' ' + location);
}
},
'DimIntent' : function () {
// to do here
},
'ChangeColorIntent' : function () {
// to do here
},
'ShceduleIntent' : function () {
// to do here
},
'AMAZON.HelpIntent': function () {
this.emit(':ask', HELP_MESSAGE, 'Wanna control something ?');
},
'AMAZON.StopIntent': function () {
this.emit(':tell', STOP_MESSAGE);
}
};
exports.handler = function (event, context, callback) {
const alexa = Alexa.handler(event, context, callback);
alexa.APP_ID = APP_ID;
alexa.registerHandlers(handlers);
alexa.execute();
}
I test my code with Service Simulator in Alexa Developer and get this result :
Result Image
So I checked output in Lambda and I got this error report :
Error in Lamda
Can anyone please help me? I have no idea with this because this is my first trial :)
The crux of your error seems to be this specific line in the log:
Cannot read property 'emit' of undefined
And after following the flow of your program, it's likely ocurring here:
mqttPromise.then(
function(data) {
console.log('Function called succesfully', data);
// It's probably ocurring in this line below
this.emit(':ask', ON_RESPONSE, AFTER_RESPONSE);
}, function(err) {
console.log('An error occurred: ', err);
}
)
The log is saying that you tried using this, it's undefined and doesn't have an emit property. Thats ocurring because of how this works in Js. You could workaround this problem by saving a reference to this
var that = this;
var mqttPromise = new Promise(function(resolve, reject) {
var options = {
port: '1883',
clientId: 'mqttjs_' + Math.random().toString(16).substr(2, 8),
username: 'username',
password: 'password',
};
var client = mqtt.connect('mqtt://broker-address', options)
client.on('connect', function() {
client.publish("lamp/status", status + ' ' + location, function() {
console.log("Message is published");
client.end();
resolve('Done Sending');
});
});
});
mqttPromise.then(
function(data) {
console.log('Function called succesfully', data);
that.emit(':ask', ON_RESPONSE, AFTER_RESPONSE);
}, function(err) {
console.log('An error occurred: ', err);
}
);
I would also recommend reading up a bit on "How 'this' works in Javascript"
MDN
Stack Overflow - "how does 'this' work"

Categories

Resources