How to get email contents using EWS/MAPI for nodejs - javascript

Using this node-ews package, I can send email, but I haven't been able to find a good example of how to read mails from the Inbox folder and get the email's text and attachments.
I've read the Microsoft documentation, such as this one: https://learn.microsoft.com/en-us/exchange/client-developer/exchange-web-services/how-to-work-with-exchange-mailbox-items-by-using-ews-in-exchange#get-an-item-by-using-the-ews-managed-api, but the examples are in C#, C++, or VB.
However, I would like to use Nodejs for this.

**I have found a best way extract every content using mailparser. see bellow
// At first Read emails from Inbox
const EWS = require('node-ews');
const simpleParser = require('mailparser').simpleParser;
// exchange server connection info
const ewsConfig = {
username: 'username',
password: 'password',
host: 'hostname'
};
const options = {
rejectUnauthorized: false,
strictSSL: false
};
// initialize node-ews
const ews = new EWS(ewsConfig, options);
var ewsFunction = 'FindItem';
var ewsArgs = {
'attributes': {
'Traversal': 'Shallow'
},
'ItemShape': {
't:BaseShape': 'Default'
},
'ParentFolderIds' : {
'DistinguishedFolderId': {
'attributes': {
'Id': 'inbox'
}
}
}
};
// Itreate over all the emails and store Id and ChangeKey.
ews.run(ewsFunction, ewsArgs, ewsSoapHeader)
.then(result => {
// Iterate over the result and extract Id and ChangeKey of the messages and pass those to GetItem function to read messages
})
// For reading individual messages returned by FindItem (using Id and ChangeKey)
var ewsFunction = 'GetItem';
var ewsArgs = {
'ItemShape': {
'BaseShape': 'Default',
'AdditionalProperties': {
'FieldURI': [
{ 'attributes': { 'FieldURI': 'item:MimeContent'}}
]
}
},
'ItemIds': {
'ItemId': {
'attributes': {
'Id': Id,
'ChangeKey': ChangeKey
}
}
}
};
await ews.run(ewsFunction, ewsArgs, ewsSoapHeader)
.then(result => {
// Iterate over the result and extract meesage
const {Message} = result.ResponseMessages.GetItemResponseMessage.Items
let mimeContent = Buffer.from(Message.MimeContent['$value'], 'base64').toString('binary');// decode mime content
simpleParser(mimeContent).then(async function (mail) {
console.log("mail")
console.log(mail.attachments)
console.log(mail.headers.get('message-id'))
console.log(mail.headers.get('references'))
console.log(mail.headers.get('in-reply-to'))
console.log({
// text: mail.text,
// html: mail.html ? mail.html.replace(/<meta([^>]+)>/g, "") : "",
from: (mail.from) ? mail.from.value.map(item => item.address) : [],
to: (mail.to) ? mail.to.value.map(item => item.address) : [],
cc: (mail.cc) ? mail.cc.value.map(item => item.address) : [],
bcc: (mail.bcc) ? mail.bcc.value.map(item => item.address) : [],
messageId: mail.messageId,
subject: mail.subject
})
}).catch((err) => {
console.log("err")
console.log(err)
})
})
Here you will get the full parsed mail contents with attachments. Happy Coding!!!

Related

Working with javascript and API exasperates me: Always Response 400

I am trying to work with an API (that provides data about movies in the media centers of german public broadcasting) but I can't get a single useful response.
I got an example code in javascript but since I dont know anything about that language I try to understand as much as I can and write an equivalent python program. Can someone tell me my mistake? The code should return a list of movies along with their duration and some similar information.
The original goes like:
`
const query = {
queries: [
{
fields: ['title', 'topic'],
query: 'sturm der liebe'
},
{
fields: ['channel'],
query: 'ard'
}
],
sortBy: 'timestamp',
sortOrder: 'desc',
future: false,
offset: 0,
size: 10,
duration_min: 20,
duration_max: 100
};
const queryString = JSON.stringify(query); // I think this turns query into a json file
const request = new XMLHttpRequest(); // here I start to loose the understanding
const requestURL = 'https://mediathekviewweb.de/api/query';
request.open("POST", requestURL);
request.addEventListener('load', function (event) {
let response;
try {
response = JSON.parse(request.responseText);
} catch (e) { }
if (request.status == 200 && typeof response != 'undefined') {
for (let i = 0; i < response.result.results.length; i++) {
let entry = response.result.results[i];
let row = $('<tr>');
row.append($('<td>').text(entry.channel));
row.append($('<td>').text(entry.topic));
row.append($('<td>').text(entry.title));
row.append($('<td>').text(entry.description));
row.append($('<td>').text(entry.url_video));
$('#mediathek > tbody').append(row);
}
$('#responseText').text(JSON.stringify(response, null, 2));
} else {
if (response) {
console.log(response.err);
$('#errorText').html(response.err.join('</br>'));
}
else {
$('#errorText').html(request.statusText + '</br>' + request.responseText);
}
}
});
request.send(queryString);
`
I started using requests:
`
import requests
import json
url = "https://mediathekviewweb.de/api/query"
answer = requests.post(url, json=queryString)
print(answer)
print(json.loads(answer.content))
`
Already in this minimal example answer returns "<Response [400]>" and the content is "{'result': None, 'err': ['Unexpected token o in JSON at position 1']}"
Can someone help me out? I didn't give a json, where does this error come from?
I get the same response when I try
`
import requests
import json
url = "https://mediathekviewweb.de/api/query"
query = {
"queries": [], // I want to search through all movies so this is left clear
"sortBy": "timestamp",
"sortOrder": "desc",
"future": False,
"offset": 0,
"size": 1000,
"duration_min": 90,
"content-type": "text/plain"
}
queryString = json.dumps(query) # hopefully this is equivalent to JSON.stringify()
answer = requests.post(url, json=queryString)
print(answer)
print(json.loads(answer.content))
`
I actually think this extra code isn't even used by the program.
I don't know if thats the right direction, but I think the javascript programm first opens a request and then in an other step inputs the data. I can't do that with the requests package as far as I know.
Don't use XMLHttpRequest. This adds to the confusion.
Here is the fetch option:
const query = {
queries: [
{
fields: ['title', 'topic'],
query: 'sturm der liebe',
},
{
fields: ['channel'],
query: 'ard',
},
],
sortBy: 'timestamp',
sortOrder: 'desc',
future: false,
offset: 0,
size: 10,
duration_min: 20,
duration_max: 100,
};
const requestURL = 'https://mediathekviewweb.de/api/query';
fetch(requestURL, { method: 'POST', body: JSON.stringify(query) })
.then((res) => res.json())
.then((res) => {
// success request logic
console.log('response', res);
})
.catch((error) => {
// error handling
console.error(error);
});

Transfer function for "eosio.token" smart contract is not working

const network = {
blockchain:'eos',
protocol:'https',
host:'jungle2.cryptolions.io',
port:443,
chainId: 'e70aaab8997e1dfce58fbfac80cbbb8fecec7b99cf982a9444273cbc64c41473',
sign: true,
broadcast: true,
debug: true,
verbose: false,
}
try {
const scatterInfo = await ScatterJS.scatter.connect('eosbetdice');
console.log({scatterInfo})
if ( scatterInfo ) {
const scatter = ScatterJS.scatter;
const requiredFields = { accounts:[network] };
const scatterVal = await scatter.getIdentity(requiredFields);
console.log({scatter,scatterVal})
if ( scatterVal ) {
const account = scatter.identity.accounts.find(x => x.blockchain === 'eos');
console.log("account",account)
const result = await api.transact({
actions: [{
account: 'eosio.token',
name: 'transfer',
authorization: [{
actor: account.name,
permission:'active',
signatures:[signature],
available_keys:[account.publicKey]
}],
data: {
from: 'abceristest2',
to: account.name,
quantity: betAsset,
memo: memo
},
}]
}, {
blocksBehind: 3,
expireSeconds: 30,
});
console.log({result})
return result;
}
} return false;
} catch ( exception ) {
console.log( exception )
}
I expect the transfer function will be work fine but It give me 401 unauthorized error. This transfer function hit the api of jungle testnet , "http://jungle.eosgen.io/v1/chain/get_required_keys"
How I can authenticate this function?
Error which I got, when this transfer function run
I don't check your codes in detail, but I think it is needed to set the data of "abceristest2" to authorization parameter.

Determining pr eliminating empty key:value from an object for multiple filtering purposes

My app has a feature where users can filter results based on "blood group" and "city", and areas. Results will be retrieved from DB using Axios for Vuejs through "URL" query strings. Example url is: http://example.com/api/results?blood=a+&city=london
It should work in a way that when a user select just blood group from select menu: the url would exclude the city parameter. But from my current code, I can't get it stripped of, as a result, the database query returns no results on the basis that cityreturns null value.
Here's what I have in my Vue component:
<script>
export default {
props: ['user'],
data() {
return {
auth_user: this.user,
results: {},
blood_groups: "",
cities: "",
districts: "",
areas: "",
donorUrl: "/api/donors",
requestedBlood: "",
requestedCity: "",
requestedDist: "",
requestedArea: "",
params: {}
};
},
created() {
this.fetchDonors();
this.fetchCities();
},
methods: {
fetchDonors() {
let url = "/api/donors";
axios.get(url).then(response => {
this.results = response.data.data;
this.blood_groups = [...new Set(response.data.data.map(x=> x.blood_group))];
});
},
fetchCities() {
let url = "/api/location_type/cities";
axios.get(url).then(response => {
this.cities = response.data.cities
})
},
selected_blood_group(event) {
this.requestedBlood = event.target.value;
this.get();
},
get_city(event) {
this.requestedCity = event.target.value;
this.get();
},
get() {
let request = {
params: {
blood: this.requestedBlood,
city: this.requestedCity,
dist: this.requestedDist,
area: this.requestedArea
}
}
axios.get('/api/donors', request).then(response => {
this.results = response.data.data
})
}
},
};
</script>
My query is how can I remove or check if any of the following properties contains empty value, so that I do not include them in axios params?
let request = {
params: {
blood: this.requestedBlood,
city: this.requestedCity,
dist: this.requestedDist,
area: this.requestedArea
}
}
You can try below code.
Create a new object(called testParams) and add that object in params.suppose requestedCity is selected(not only but any variable is selected ). Then you can do like below.
if(requestedCity.length!=0)
{
testParams["city"]=requestedCity; // OTHERWISE DON'T ADD IN testParams object
}
Finally while making request through axios add testParams in params object like below.
axios.get('/yourUrl/',{
params:{
testParams //here vue will automatically sets 'testParams':testParams
}
})
I got it working with the following approach:
let request = {
blood: this.requestedBlood,
city: this.requestedCity,
dist: this.requestedDist,
area: this.requestedArea
}
for(let k in request)
if(!request[k]) delete request[k];
axios.get('/api/donors', {
params: request
}).then(response => {
this.results = response.data.data
})

Rocket Chat Realtime API in browser

I want to create a Rocket Chat client to subscribe to a channel through browser using Realtime API. Documentation here does not provide step by step procedure. Please let me know how to achieve it.
Links to any documentation would be very helpful.
I had less idea about websockets when I asked this question. For the benefit of all, mentioning the steps I followed.
Open websocket
var rocketChatSocket = new WebSocket("ws://locahost:3000/websocket");
Connect
var connectRequest = {
"msg": "connect",
"version": "1",
"support": ["1", "pre2", "pre1"]
}
rocketChatSocket.send(JSON.stringify(connectRequest));
After connecting, keep responding with {"msg":"pong"} for {"msg":"ping"} from server.
Login with authToken received by calling this API
var loginRequest = {
"msg": "method",
"method": "login",
"id": "42",
"params": [
{ "resume": "authToken" }
]
}
rocketChatSocket.send(JSON.stringify(loginRequest));
Subscribe to room
var subscribeRequest = {
"msg": "sub",
"id": "unique-id",
"name": "stream-notify-room",
"params":[
"room-id/event",
false
]
}
rocketChatSocket.send(JSON.stringify(subscribeRequest));
Send message
var request={
"msg": "method",
"method": "sendMessage",
"id": "42",
"params":
[
{
"_id": "message-id",
"rid": "room-id",
"msg": "Hello World!"
}
]
}
rocketChatSocket.send(JSON.stringify(request));
Thank you Mr Nandan,we were able to use your answer to build fully custom client to talk with the rocket chat real time api
here's the link for future people who will want the same thing
https://github.com/lalosh/rocketchat.realTimeAPI.customClient/blob/master/main.js
and here's the code in case you want to check immediately
/*
Rocket Chat Real Time API Custom Client
even though this code works great I don't know what exactly each event we listen for is doing
you can go back to rocket chat real time api for further declarations
we were able to write this code after we test real normal use case of livechat in a web page
and we listen for WebSocket connection inside the browser Network tab(by filtering ws(WebSocket) connections)
*/
let socket = new WebSocket('ws://[rocketChatIP]:[rocketChatPort]/websocket');
//note messageCount is incremented with every message
//but it can works even if you didn't change it
let messagesCount = 1;
// the variables chatToken and chatRoomId are very important
// and they are the identifier to the room(the whole chat) you are using
// if you want to get access to the chat again you need these two variables tokens
let chatToken = generateHash(17);
let chatRoomId = generateHash(17);
let subId = generateHash(17);
let roomSubId = generateHash(17);
let streamLivechatchatRoomId = generateHash(17);
let steamNotifyRoomSubId = generateHash(17);
let name = 'user28';
let email = 'user28#gmail.com';
let guestName = 'guest';
// listen to messages passed to this socket
socket.onmessage = function(e) {
let response = JSON.parse(e.data);
console.log('response', response);
// you have to pong back if you need to keep the connection alive
// each ping from server need a 'pong' back
if (response.msg == 'ping') {
console.log('pong!');
socket.send(JSON.stringify({
msg: 'pong'
}));
return;
}
// here you receive messages from server //notive the event name is: 'stream-room-messages'
if (response.msg === 'changed' && response.collection === 'stream-room-messages') {
console.log('msg received ', response.fields.args[0].msg, 'timestamp ', response.fields.args[0].ts.$date, 'from ' + response.fields.args[0].u.name);
return;
}
// receive all messages which will only succeed if you already have messages
// in the room (or in case you send the first message immediately you can listen for history correctly)
if (response.msg === 'result' && response.result) {
if (response.result.messages) {
let allMsgs = response.result.messages;
console.log('-----previous msgs---------------');
allMsgs.map(x => console.log(x))
console.log('---------------------------------')
}
}
}
//////////////////////////////////////////////
// steps to achieve the connection to the rocket chat real time api through WebSocket
//1 connect
let connectObject = {
msg: 'connect',
version: '1',
support: ['1', 'pre2', 'pre1']
}
setTimeout(() => {
socket.send(JSON.stringify(connectObject));
}, 1000)
//////////////////////////////////////////////
//2 getInitialData
let getInitialDataObject = {
msg: 'method',
method: 'livechat:getInitialData',
params: [String(chatToken), null],
id: String(messagesCount++),
}
setTimeout(() => {
socket.send(JSON.stringify(getInitialDataObject));
}, 2000)
//////////////////////////////////////////////
//3 loginByToken
let loginByToken = {
msg: 'method',
method: 'livechat:loginByToken',
params: [String(chatToken)],
id: String(messagesCount++),
}
setTimeout(() => {
socket.send(JSON.stringify(loginByToken));
}, 3000)
//////////////////////////////////////////////
//4 subscribtion
let subObj = {
msg: 'sub',
id: subId,
name: 'meteor.loginServiceConfiguration',
params: []
}
setTimeout(() => {
socket.send(JSON.stringify(subObj));
}, 4000)
//////////////////////////////////////////////
//5 register // you may skip this if you alredy registered
// or you can re use it even though you are registered.. no problems
// the crucial part is the `chatToken` and later on the `chatRoomId`
let registerObj = {
msg: 'method',
method: 'livechat:registerGuest',
params: [{
token: chatToken,
name: name,
email: email,
'department': null
}],
id: String(messagesCount++),
};
setTimeout(() => {
socket.send(JSON.stringify(registerObj));
}, 5000)
//////////////////////////////////////////////////
//6 stream-notify-room
let streamNotifyObj = {
msg: 'method',
method: 'stream-notify-room',
params: [
'null/typing',
guestName, true, {
token: String(chatToken)
}
],
id: String(messagesCount++)
};
setTimeout(() => {
socket.send(JSON.stringify(streamNotifyObj));
}, 6000)
//////////////////////////////////////////////////
//7 send a msg //use the same method to send your own messages again when you are all connected
let myMsg = {
msg: 'method',
method: 'sendMessageLivechat',
params: [{
_id: String(generateHash(17)),
rid: chatRoomId,
msg: 'first message',
token: String(chatToken),
}, null],
id: String(messagesCount++),
}
setTimeout(() => {
socket.send(JSON.stringify(myMsg));
}, 7000)
//////////////////////////////////////////////////
//8 send userPresence
let UserPresence = {
msg: 'method',
method: 'UserPresence:connect',
params: [
String(chatToken),
{
visitor: String(chatToken)
}
],
id: String(messagesCount++)
}
setTimeout(() => {
socket.send(JSON.stringify(UserPresence));
}, 8000)
/////////////////////////////////////////////////
//9 loadHistory of old messages
let loadHistory = {
msg: 'method',
method: 'livechat:loadHistory',
params: [{
token: String(chatToken),
rid: String(chatRoomId),
ts: {
$date: new Date().getTime()
}, //current point of time
limit: 50
}],
id: String(messagesCount++)
};
setTimeout(() => {
socket.send(JSON.stringify(loadHistory));
}, 9000)
/////////////////////////////////////////////////
// 10 stream-room-messages
// listen to all received messages
let roomMessagesSub = {
msg: 'sub',
id: String(roomSubId),
name: 'stream-room-messages',
params: [
String(chatRoomId),
{
useCollection: false,
args: [{
visitorToken: String(chatToken)
}]
}
]
};
setTimeout(() => {
socket.send(JSON.stringify(roomMessagesSub));
}, 10000)
/////////////////////////////////////////////////
// 11 getAgentData
let getAgentData = {
msg: 'method',
method: 'livechat:getAgentData',
params: [{
roomId: String(chatRoomId),
token: String(chatToken),
}],
id: String(messagesCount++)
}
setTimeout(() => {
socket.send(JSON.stringify(getAgentData));
}, 11000)
/////////////////////////////////////////////////
//12 stream-livechat-room
let streamLivechatRoom = {
msg: 'sub',
id: String(streamLivechatchatRoomId),
name: 'stream-livechat-room',
params: [
String(chatRoomId),
{
useCollection: false,
args: [{
'visitorToken': String(chatToken)
}]
}
]
}
setTimeout(() => {
socket.send(JSON.stringify(streamLivechatRoom));
}, 12000)
//////////////////////////////////////////
//13 stream-notify-room
let steamNotifyRoomSub = {
msg: 'sub',
id: String(steamNotifyRoomSubId),
name: 'stream-notify-room',
params: [
`${String(chatRoomId)}/typing`,
{
useCollection: false,
args: [{
token: String(chatToken)
}]
}
]
}
setTimeout(() => {
socket.send(JSON.stringify(steamNotifyRoomSub));
}, 13000)
//////////////////////////////////////
//14 userpresence 2
let UserPresence2 = {
msg: 'method',
method: 'UserPresence:online',
params: [String(chatToken)],
id: String(messagesCount++),
}
setTimeout(() => {
socket.send(JSON.stringify(UserPresence2));
}, 14000)
//////////////////////////////////////
//use it to send new messages
function sendNewMsg(msg, messagesCount) {
let myMsg = {
msg: 'method',
method: 'sendMessageLivechat',
params: [{
_id: String(generateHash(17)),
rid: chatRoomId,
msg: String(msg),
token: String(chatToken),
}, null],
id: String(messagesCount++),
}
setTimeout(() => {
socket.send(JSON.stringify(myMsg));
}, 500);
}
function generateHash(targetLength) {
var text = '';
var possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
for (var i = 0; i < targetLength; i++)
text += possible.charAt(Math.floor(Math.random() * possible.length));
return text;
}
If you like to use an open source library for this purpose, here is one https://github.com/inf3cti0n95/Rocket.Chat.RealTime.API.RxJS
Here is the sample code:
import { RealTimeAPI } from "rocket.chat.realtime.api.rxjs";
const realTimeAPI = new RealTimeAPI("wss://demo.rocket.chat/websocket");
realTimeAPI.keepAlive();
const auth = realTimeApi.login(USERNAME, PASSWORD);
//Subscribe to messages and errors
auth.subscribe(
(data) => console.log(data),
(err) => console.log(err),
() => console.log('completed'));
//Subscribe to a specific channel, identified by roomId
realtimeAPI.sendMessage({
msg: 'sub',
id: '<a unique Id for subscription>',
name: 'stream-room-messages',
params: [roomId, false],
});

Not able to understand error in promise chain in ES6

I have a series of asynchronous operations in my Backend code . I have doing backend coding in node js .
My code is something like this
db.users
.findAll({
where: condition,
duplicating: false,
attributes: userAttributes,
include: inclusion,
group: ['users.id', 'organizationEntries.id'],
order: [['organizationEntries', 'createdAt', 'DESC']]
})
.then(users => {
let result = users.map(c => {
let output = {
user_id: c.id,
name: c.name,
mobile: c.mobile,
mobile_alternate: c.mobileAlternate,
email: c.email,
gender: c.gender,
dob: c.dob,
image: Utils.getImageUrl(c.image),
entry_id: c.organizationEntries[0].id,
doj: c.organizationEntries[0].fromDate,
status: c.organizationEntries[0].status
};
if (isPlayer && c.dataValues.amount) {
output.due_amount = c.dataValues.amount.toFixed(2);
}
let arenaPromise;
if (!isPlayer) {
output.address_text = addressController.prepareAddressText(c.address);
output.address = addressController.prepareAddressJson(c.address);
if (c.organizationEntries[0].arenaIds)
db.arenas
.findAll({
attributes: ['name'],
where: {
id: {
[Op.in]: c.organizationEntries[0].arenaIds
},
organizationId: req.ORG_ID
}
})
.then(arenas => {
console.log(arenas);
output.arenas = arenas.map(a => {
let arena = {};
arenas.forEach(element => {
arena.name = element.name;
// console.log(arena.name);
});
console.log(arena);
return arena;
});
console.log(output);
// res.send(output);
});
}
return output;
});
res.send(result);
All the things are working fine but in the last then block where I am trying to add arenas in the output object .
.then(arenas => {
console.log(arenas);
output.arenas = arenas[0].name;
output.arenas = arenas.map(a => {
let arena = {};
arenas.forEach(element => {
arena.name = element.name;
// console.log(arena.name);
});
console.log(arena);
return arena;
});
Actually what is happening I am able to fetch arenas data from database
but after fetching it is not assigning the arenas in output object .
I am learning promise chain so anyone can please help me or give me some hint

Categories