How to download outlook attachment through node js - node.js

I am using below code to download the Gmail attachments. In windows this is working fine but when I am trying to run this same code in my Linux machine it is giving me an error as below.
Also can anyone help how can I perform the same thing for office outlook. in that I am getting an authentication error
Error :
Downloading attachments for pmgtesting1#gmail.com since 2020-11-25 to files/...
[connection] Connected to host
<= '* OK Gimap ready for requests from 51.103.27.188 l25mb237269790wmj'
=> 'A0 CAPABILITY'
<= '* CAPABILITY IMAP4rev1 UNSELECT IDLE NAMESPACE QUOTA ID XLIST CHILDREN X-GM-EXT-1 XYZZY SASL-IR AUTH=XOAUTH2 AUTH=PLAIN AUTH=PLAIN-CLIENTTOKEN AUTH=OAUTHBEARER AUTH=XOAUTH'
<= 'A0 OK Thats all she wrote! l25mb237269790wmj'
=> 'A1 LOGIN "pmgtesting1#gmail.com" "pswd****"'
<= '* NO [WEBALERT https://accounts.google.com/signin/continue?sarp=1&scc=1&plt=AKgnsbv-cVj07x6UiZjwizvTzmqYRNNyofoJ8yiGr960BU9t1OKkU83L43n5ocMP2SlhJ3MqWkb04Wj4ye1XxDbTSALJhCRkQ373HLB_tcH_yHBmmDycIiLGnX3NNETY0QakllRJFVjR] Web login required.'
<= 'A1 NO [ALERT] Please log in via your web browser: https://support.google.com/mail/accounts/answer/78754 (Failure)'
[connection] Ended
[connection] Closed
disconnected from pmgtesting1#gmail.com
Error ----> {
latestTime: undefined,
lastSyncId: 0,
uidvalidity: undefined,
handledIds: [],
errors: [
Error: Please log in via your web browser: https://support.google.com/mail/accounts/answer/78754 (Failure)
at Connection._resTagged (/home/textify/Mail-attachement/node_modules/imap/lib/Connection.js:1488:11)
at Parser.<anonymous> (/home/textify/Mail-attachement/node_modules/imap/lib/Connection.js:193:10)
at Parser.emit (events.js:314:20)
at Parser._resTagged (/home/textify/Mail-attachement/node_modules/imap/lib/Parser.js:175:10)
at Parser._parse (/home/textify/Mail-attachement/node_modules/imap/lib/Parser.js:139:16)
at Parser._tryread (/home/textify/Mail-attachement/node_modules/imap/lib/Parser.js:82:15)
at TLSSocket.Parser._cbReadable (/home/textify/Mail-attachement/node_modules/imap/lib/Parser.js:53:12)
at TLSSocket.emit (events.js:314:20)
at emitReadable_ (_stream_readable.js:558:12)
at processTicksAndRejections (internal/process/task_queues.js:83:21) {
type: 'no',
textCode: 'ALERT',
source: 'authentication'
}
]
}
NOTE : I have enabled the Less secure app connection
const downloadEmailAttachments = require('download-email-attachments');
const moment = require('moment');
const todaysDate = moment().format('YYYY-MM-DD');
var reTry = 1;
var paraObj = {
invalidChars: /\W/g,
account: `"****#gmail.com":Paswd******#imap.gmail.com:993`,
// all options and params
//besides account are optional
directory: './files',
filenameTemplate: '{filename}',
// filenameTemplate: '{day}-{filename}',
filenameFilter: /.txt?$/,
timeout: 10000,
log: { warn: console.warn, debug: console.info, error: console.error, info:
console.info },
since: todaysDate,
lastSyncIds: ['234', '234', '5345'], // ids already dowloaded and ignored, helpful
//because since is only supporting dates without time
attachmentHandler: function (attachmentData, callback, errorCB) {
console.log(attachmentData);
callback()
}
}
var onEnd = (result) => {
if (result.errors || result.error) {
console.log("Error ----> ", result);
if(reTry < 4 ) {
console.log('retrying....', reTry++)
return downloadEmailAttachments(paraObj, onEnd);
} else console.log('Failed to download attachment')
} else console.log("done ----> ");
}
downloadEmailAttachments(paraObj, onEnd);
const downloadEmailAttachments = require('download-email-attachments');
const moment = require('moment');
const todaysDate = moment().format('YYYY-MM-DD');
var reTry = 1;
var paraObj = {
invalidChars: /\W/g,
account: `"****#gmail.com":Paswd******#imap.gmail.com:993`,
// all options and params
//besides account are optional
directory: './files',
filenameTemplate: '{filename}',
// filenameTemplate: '{day}-{filename}',
filenameFilter: /.txt?$/,
timeout: 10000,
log: { warn: console.warn, debug: console.info, error: console.error, info:
console.info },
since: todaysDate,
lastSyncIds: ['234', '234', '5345'], // ids already dowloaded and ignored, helpful
//because since is only supporting dates without time
attachmentHandler: function (attachmentData, callback, errorCB) {
console.log(attachmentData);
callback()
}
}
var onEnd = (result) => {
if (result.errors || result.error) {
console.log("Error ----> ", result);
if(reTry < 4 ) {
console.log('retrying....', reTry++)
return downloadEmailAttachments(paraObj, onEnd);
} else console.log('Failed to download attachment')
} else console.log("done ----> ");
}
downloadEmailAttachments(paraObj, onEnd);

I got the answer just enable the 2-factor authentication in Gmail and then register your app and use the app password to fetch the email. Note: For the outlook part, I don't have the admin right to generate the app password if you have then this will also work for you Will update with the other solution as soon as I find them

Related

Node.JS aws-sdk getting "socket hang up" error

I am trying to get the pricing information of AmazonEC2 machines using "#aws-sdk/client-pricing-node" package.
Each time I will send a request to get the pricing information, process it, and send the request again, until all the information is obtained (no NextToken anymore). The following is my code.
const {
PricingClient,
} = require('#aws-sdk/client-pricing-node/PricingClient');
const {
GetProductsCommand,
} = require('#aws-sdk/client-pricing-node/commands/GetProductsCommand');
const agent = new https.Agent({
maxSockets: 30,
keepAlive: true,
});
const pricing = new PricingClient({
region: "us-east-1",
httpOptions: {
timeout: 45000,
connectTimeout: 45000,
agent,
},
maxRetries: 10,
retryDelayOptions: {
base: 500,
},
});
const getProductsCommand = new GetProductsCommand( { ServiceCode: 'AmazonEC2', });
async function sendRequest() {
let result = false;
while (!result) {
try {
const data = await pricing.send(getProductsCommand);
result = await handleReqResults(data);
} catch (error) {
console.error(error);
}
}
}
async function handleReqResults(data) {
// some data handling code here
// ...
//return false when there is "NextToken" in the response data
if (data.NextToken) {
setNextToken(data.NextToken);
return false;
}
return true;
}
The code will run for a while (variable time) and then stop with the following error:
{ Error: socket hang up
at createHangUpError (_http_client.js:332:15)
at TLSSocket.socketOnEnd (_http_client.js:435:23)
at TLSSocket.emit (events.js:203:15)
at TLSSocket.EventEmitter.emit (domain.js:448:20)
at endReadableNT (_stream_readable.js:1145:12)
at process._tickCallback (internal/process/next_tick.js:63:19)
code: 'ECONNRESET',
'$metadata': { retries: 0, totalRetryDelay: 0 } }
I had tried to run it on a GCP VM instance, and there was no such a problem. But the problem happens when I run it on my local machine.
Do anyone have any idea how to solve this problem?
(BTW: my node version is v10.20.1)

Error method sendAll() in nodejs using firebase-admin

I use firebase-admin for nodejs(version 7.3.0) for sending push
notifications. For 40k distinct messages sending with method sendAll often server received this error:
"Credential implementation provided to initializeApp() via the "credential"
property failed to fetch a valid Google OAuth2 access token with the
following error: "Error fetching access token: Error while making request:
socket hang up. Error code: ECONNRESET".
Sometimes it works well but not all the time.
var admin = require('firebase-admin');
serviceAccount = require('/path_json_adminsdk/yyyyyyyyyy.json');
var defaultApp = admin.initializeApp({
credential: admin.credential.cert(serviceAccount),
databaseURL: 'https://api-project-yyyyyy'
});
var k = 42000;
var contorMessages = 0;
var messages = [];
for(var i=0;i <em><</em> k; i++){
//.......
contorMessages = contorMessages + 1;
var tmp = {
alert: body.alert,
payload: body.payload
};
//form the array to be sent
messages.push({
data: {"body": JSON.stringify(tmp)},
token: body.token
});
if(contorMessages == 100){
SEDispatcher.emit('sendMessageFirebaseMulticast',messages);
contorMessages = 0;
messages = [];
}
}
SEDispatcher.on('sendMessageFirebaseMulticast', function(messages){
var dryRun = true;
admin.messaging().sendAll(messages, dryRun)
.then(function(response) {
//console.log("response:",response);
//responses = response.responses;
//.......
})
.catch((error) => {
console.log(' +++ Error sending message:', error);
});
});
the error that occurs sometimes:
+++ Error sending message: { Error: Credential implementation provided to initializeApp() via the "credential" property failed to fetch a
valid Google OAuth2 access token with the following error: "Error
fetching access token: Error while making request: socket hang up.
Error code: ECONNRESET".
at FirebaseAppError.Error (native)
at FirebaseAppError.FirebaseError [as constructor] (/opt/node/test/node_modules/firebase-admin/lib/utils/error.js:42:28)
at FirebaseAppError.PrefixedFirebaseError [as constructor] (/opt/node/test/node_modules/firebase-admin/lib/utils/error.js:88:28)
at new FirebaseAppError (/opt/node/test/node_modules/firebase-admin/lib/utils/error.js:122:28)
at /opt/node/test/node_modules/firebase-admin/lib/firebase-app.js:121:23
at process._tickCallback (internal/process/next_tick.js:103:7) errorInfo: { code: 'app/invalid-credential',
message: 'Credential implementation provided to initializeApp() via the "credential" property failed to fetch a valid Google OAuth2
access token with the following error: "Error fetching access token:
Error while making request: socket hang up. Error code: ECONNRESET".'
}, codePrefix: 'app' }
const messaging = getMessaging(defaultApp);
Need to be load
let serviceAccount = require('./google.json');
function messaging() {
const defaultApp = initializeApp({
credential: admin.credential.cert(serviceAccount)
});
const messaging = getMessaging(defaultApp);
const topic = 'highScores';
const message = [
{
data: {
score: '850',
time: '2:45'
},
topic: topic
}
];
messaging
.sendAll(message, true)
.then(function (response) {
console.log('response:', response);
})
.catch((error) => {
console.log(' +++ Error sending message:', error);
});
}
Assuming that the JSON is the file that contains your private key that is generated when registering the project

Saving data to Postgres from AWS Lambda

I'm building a lambda function that is supposed to save a game feedback, like a performance grade, into my Postgres database, which is in AWS RDS.
I'm using NodeJS typescript and the function is kinda working, but in a strange way.
I made an API Gateway so I can POST data to the URL to the lambda process it and save it, the thing is, when I POST the data the function seems to process it until it reaches a max limit of connected clients, and than it seems to lose the other clients'data.
Another problem is that every time I POST data I get a response saying that there was a Internal Server Error and with a 'X-Cache→Error from cloudfront' header. For a GET request I figured it out that it was giving me this response because the format of the response was incorrect, but in this case I fixed the response format and still get this problem...
Sometimes I get a timeout response.
My function's code:
import { APIGatewayEvent, Callback, Context, Handler } from "aws-lambda";
import { QueryConfig, Client, Pool, PoolConfig } from "pg";
export const insert: Handler = async (
event: APIGatewayEvent,
context: Context,
cb: Callback
) => {
// context.callbackWaitsForEmptyEventLoop = false;
const config: PoolConfig = {
user: process.env.PG_USER,
host: process.env.PG_HOST,
database: process.env.PG_DB,
password: process.env.PG_PASS,
port: parseInt(process.env.PG_PORT),
idleTimeoutMillis: 0,
max: 10000
};
const pool = new Pool(config);
let postdata = event.body || event;
console.log("POST DATA:", postdata);
if (typeof postdata == "string") {
postdata = JSON.parse(postdata);
}
let query: QueryConfig = <QueryConfig>{
name: "get_all_questions",
text:
"INSERT INTO gamefeedback (gameid, userid, presenterstars, gamestars) VALUES ($1, $2, $3, $4);",
values: [
parseInt(postdata["game_id"]),
postdata["user_id"],
parseInt(postdata["presenter_stars"]),
parseInt(postdata["game_stars"])
]
};
console.log("Before Connect");
let con = await pool.connect();
let res = await con.query(query);
console.log("res.rowCount:", res.rowCount);
if (res.rowCount != 1) {
cb(new Error("Error saving the feedback."), {
statusCode: 400,
body: JSON.stringify({
message: "Error saving data!"
})
});
}
cb(null, {
statusCode: 200,
body: JSON.stringify({
message: "Saved successfully!"
})
});
console.log("The End");
};
Than the log from CloudWatch error with max number of clients connected looks like this:
2018-08-03T15:56:04.326Z b6307573-9735-11e8-a541-950f760c0aa5 (node:1) UnhandledPromiseRejectionWarning: error: sorry, too many clients already
at u.parseE (/var/task/webpack:/node_modules/pg/lib/connection.js:553:1)
at u.parseMessage (/var/task/webpack:/node_modules/pg/lib/connection.js:378:1)
at Socket.<anonymous> (/var/task/webpack:/node_modules/pg/lib/connection.js:119:1)
at emitOne (events.js:116:13)
at Socket.emit (events.js:211:7)
at addChunk (_stream_readable.js:263:12)
at readableAddChunk (_stream_readable.js:250:11)
at Socket.Readable.push (_stream_readable.js:208:10)
at TCP.onread (net.js:607:20)
Can any of you guys help me with this strange problem?
Thanks
Well for one thing you need to put creating a pool above the handler, like so:
const config: PoolConfig = {
user: process.env.PG_USER,
...
};
const pool = new Pool(config);
export const insert: Handler = async (
event: APIGatewayEvent,
context: Context,
cb: Callback
) => {
..etc
The way you have it you are creating a pool on every invocation. If you create the pool outside the handler it gives Lambda a chance to share the pool between invocations.

Unable to connect to Realm Object Server using NodeJs

I've installed Realm Object Server using the docker container method on a VM on the google cloud platform. The container is running and I am able to connect in a browser and see the ROS page. I am able to connect to it using Realm Studio and add a user.
I have a nodeJS app running locally on a Mac and I'm trying to use that to sign in and write to realm on the server. When I run the app I get an error and the user returned is an empty object. Not sure what I'm doing wrong.
I'm new to NodeJS.
Code:
var theRealm;
const serverUrl = "http://xx.xx.xx.xx:9080";
const username = "xxxx";
const password = "xxxx";
var token = "long-token-for-enterprise-trial";
Realm.Sync.setFeatureToken(token);
console.log("Will log in user");
Realm.Sync.User.login(serverUrl, username, password)
.then(user => {
``
// user is logged in
console.log("user is logged in " + util.inspect(user));
// do stuff ...
console.log("Will create config");
const config = {
schema:[
schema.interventionSchema,
schema.reportSchema
],
sync: {
user: user,
url: serverUrl
}
};
console.log("Will open realm with config: " + config);
const realm = Realm.open(config)
.then(realm => {
// use the realm instance here
console.log("Realm is active " + realm);
console.log("Will create Realm");
theRealm = new Realm({
path:'model/realm_db/theRealm.realm',
schema:[
schema.interventionSchema,
schema.reportSchema
]
});
console.log("Did create Realm: " + theRealm);
})
.catch(error => {
// Handle the error here if something went wrong
console.log("Error when opening Realm: " + error);
});
})
.catch(error => {
// an auth error has occurred
console.log("Error when logging in user: " + error);
});
Output:
Will log in user
Server is running...
user is logged in {}
Will create config
Will open realm with config: [object Object]
TypeError: Cannot read property 'token_data' of undefined
at performFetch.then.then (/pathToProject/node_modules/realm/lib/user-methods.js:203:49)
at <anonymous>
at process._tickCallback (internal/process/next_tick.js:188:7)
TypeError: Cannot read property 'token_data' of undefined
at performFetch.then.then (/pathToProject/node_modules/realm/lib/user-methods.js:203:49)
at <anonymous>
at process._tickCallback (internal/process/next_tick.js:188:7)
Error # user-methods.js:203:49
const tokenData = json.access_token.token_data;
json is:
{ user_token:
{ token: 'xxxxxxxx',
token_data:
{ app_id: 'io.realm.Auth',
identity: 'xxxxxxx',
salt: 'xxxxxxxx',
expires: 1522930743,
is_admin: false } } };
So json.access_token.token_data is undefined but json. user_token.token_data would not be.
I would suggest you to try the ROS connection with realm studio in that u can check logs as well which will help you to fix the error. If your still not able to fix then you can contact Realm support team even they helped me to fix the issue of ROS connection in Xamarin Forms using Docker.

Error from Azure IoT Hub library when sending a message

Im using the Node.JS libraries for Azure IoT Hub to send some telemetry data, and intermittently I get the following error thrown from the libraries.
Unhandled rejection TypeError: Cannot read property 'on' of undefined
at C:\Source\Messenger\app.js:156:17
at Amqp. (C:\Source\Messenger\node_modules\azure-iot-device\node_modules\azure-iot-common\lib\amqp.js:157:17)
at C:\Source\Messenger\node_modules\azure-iot-device\node_modules\azure-iot-common\lib\amqp.js:54:19
at C:\Source\Messenger\node_modules\azure-iot-device\node_modules\azure-iot-common\lib\amqp.js:84:17
at tryCatcher (C:\Source\Messenger\node_modules\azure-iot-device\node_modules\azure-iot-common\node_modules\amqp10\node_modules\bluebird\js\release\util.js:11:23)
at Promise._settlePromiseFromHandler (C:\Source\Messenger\node_modules\azure-iot-device\node_modules\azure-iot-common\node_modules\amqp10\node_modules\bluebird\js\release\promise.js:489:31)
at Promise._settlePromise (C:\Source\Messenger\node_modules\azure-iot-device\node_modules\azure-iot-common\node_modules\amqp10\node_modules\bluebird\js\release\promise.js:546:18)
at Promise._settlePromise0 (C:\Source\Messenger\node_modules\azure-iot-device\node_modules\azure-iot-common\node_modules\amqp10\node_modules\bluebird\js\release\promise.js:591:10)
at Promise._settlePromises (C:\Source\Messenger\node_modules\azure-iot-device\node_modules\azure-iot-common\node_modules\amqp10\node_modules\bluebird\js\release\promise.js:670:18)
at Async._drainQueue (C:\Source\Messenger\node_modules\azure-iot-device\node_modules\azure-iot-common\node_modules\amqp10\node_modules\bluebird\js\release\async.js:129:16)
at Async._drainQueues (C:\Source\Messenger\node_modules\azure-iot-device\node_modules\azure-iot-common\node_modules\amqp10\node_modules\bluebird\js\release\async.js:139:10)
at Immediate.Async.drainQueues [as _onImmediate] (C:\Source\Messenger\node_modules\azure-iot-device\node_modules\azure-iot-common\node_modules\amqp10\node_modules\bluebird\js\release\async.js:16:14)
At the moment im running my scripts through forever so it recovers when the error is generated.
Has anyone else had this issue and managed to resolve it ?
My code looks like as follows
azureClient = azureDevice.Client.fromConnectionString(connectionString, azureDevice.Amqp);
var message = new azureDevice.Message(JSON.stringify('TEST MESSAGE'));
azureClient.sendEvent(message, function (err) {
if (err != null) {
Configure();
}
});
For this issue, I recommend you can use the AMQPWS or HTTP transport to send and receive messages.
Please refer to my steps to achieve to send and receive the message:
Firstly, we should create a device and get the device id and SAS. After created the IOT hub on Azure new portal, I ran those command on node.js command line:
create IOT hub on new portal.
npm install -g iothub-explorer
iothub-explorer HostName=****.azure-devices.net;SharedAccessKeyName=iothubowner;SharedAccessKey=****/****= create mydevice --connection-string
I got the result as following:
Created device mydevice
-
deviceId: mydevice
generationId: 635881160181557968
etag: MA==
connectionState: Disconnected
status: enabled
statusReason: null
connectionStateUpdatedTime: 0001-01-01T00:00:00
statusUpdatedTime: 0001-01-01T00:00:00
lastActivityTime: 0001-01-01T00:00:00
cloudToDeviceMessageCount: 0
authentication:
SymmetricKey:
primaryKey: ****/****=
secondaryKey: ****/****=
-
connectionString: HostName=****.azure-devices.net;DeviceId=mydevice;SharedAccessKey=****/****=
Secondly, I installed the SDK on node.js project, the folder structure is same as this picture:
Thirdly, I run this code on my project:
var device = require('azure-iot-device');
var connectionString = 'HostName=****.azure-devices.net;DeviceId=mydevice;SharedAccessKey=****/****=';
var client = device.Client.fromConnectionString(connectionString,device.AmqpWS);
setInterval(function () {
var windSpeed = 10 + (Math.random() * 4); // range: [10, 14]
var data = JSON.stringify({ deviceId: 'mydevice', windSpeed: windSpeed });
var message = new device.Message(data);
message.properties.add('myproperty', 'myvalue');
console.log("Sending message: " + message.getData());
client.sendEvent(message, printResultFor('send'));
}, 1000);
client.getReceiver(function (err, receiver) {
receiver.on('message', function (msg) {
console.log('Id: ' + msg.properties.messageId + ' Body: ' + msg.body);
receiver.complete(msg, function () {
console.log('completed');
// receiver.reject(msg, function() {
// console.log('rejected');
// });
// receiver.abandon(msg, function() {
// console.log('abandoned');
// });
});
receiver.on('errorReceived', function (err) {
console.warn(err);
});
});
});
function printResultFor(op) {
return function printResult(err, res) {
if (err) console.log(op + ' error: ' + err.toString());
if (res) console.log(op + ' status: ' + res);
};
}
it works fine. Also if you used the "Http" transport, it also works fine.
You need use this code:
var client = device.Client.fromConnectionString(connectionString);
This is the reason why I recommend you use the AMQPWS, because of this code in "azure-iot-device\node_modules\azure-iot-common\node_modules\amqp10-transport-ws":
if (this.uri.startsWith('wss')) {
var wsTransport = require('amqp10-transport-ws');
wsTransport.register(amqp10.TransportProvider);
}
If the URI is format with 'wss', it will be register the AMQP transport. But AMQP transport's format is like "amqp://". Hope this helps.
The Azure IoT Hub was by far a preview feature service on Azure. And the Azure IoT device SDK for Node.js is on the fast development.
I am trying to involve someone familiar with this topic to further look at this issue. There might be some time delay.
Appreciate your patience.

Resources