Goal: I am trying to read the mails (outlook) with certain filters like 'from specified user','read','sent' etc. Used a module "IMAP" for parsing. I have to read the mail and download and store attachments from the mail in a certain location (preferably local). But my code is failing to connect to the mail server.
Below is my code which results in 'Auth:timeout error' when I ran.
Please let me know what is wrong with my code. Thanks in advance!
var Imap = require('imap'),
inspect = require('util').inspect;
var fs = require('fs'), fileStream;
var buffer = '';
var myMap;
var imap = new Imap({
user: "put user id here",
password: "put your password here",
host: "outlook.office365.com", //this may differ if you are using some other mail services like yahoo
port: 993,
tls: true,
// connTimeout: 10000, // Default by node-imap
// authTimeout: 5000, // Default by node-imap,
debug: console.log, // Or your custom function with only one incoming argument. Default: null
tlsOptions: true,
mailbox: "INBOX", // mailbox to monitor
searchFilter: ["UNSEEN", "FLAGGED"], // the search filter being used after an IDLE notification has been retrieved
markSeen: true, // all fetched email willbe marked as seen and not fetched next time
fetchUnreadOnStart: true, // use it only if you want to get all unread email on lib start. Default is `false`,
mailParserOptions: { streamAttachments: true }, // options to be passed to mailParser lib.
attachments: true, // download attachments as they are encountered to the project directory
attachmentOptions: { directory: "attachments/" } // specify a download directory for attachments
});
function openInbox(cb) {
imap.openBox('INBOX', false, cb);
}
imap.once('ready', function () {
openInbox(function (err, box) {
if (err) throw err;
imap.search(['UNSEEN', ['SUBJECT', 'Give Subject Here']], function (err, results) {
if (err) throw err;
var f = imap.fetch(results, { bodies: '1', markSeen: true });
f.on('message', function (msg, seqno) {
console.log('Message #%d' + seqno);
console.log('Message type' + msg.text)
var prefix = '(#' + seqno + ') ';
msg.on('body', function (stream, info) {
stream.on('data', function (chunk) {
buffer += chunk.toString('utf8');
console.log("BUFFER" + buffer)
})
stream.once('end', function () {
if (info.which === '1') {
console.log("BUFFER" + buffer)
}
});
console.log(prefix + 'Body');
stream.pipe(fs.createWriteStream('msg-' + seqno + '-body.txt'));
});
msg.once('attributes', function (attrs) {
console.log(prefix + 'Attributes: %s', inspect(attrs, false, 8));
});
msg.once('end', function () {
console.log(prefix + 'Finished');
});
});
f.once('error', function (err) {
console.log('Fetch error: ' + err);
});
f.once('end', function () {
console.log('Done fetching all messages!');
imap.end();
});
});
});
});
imap.once('error', function (err) {
console.log(err);
});
imap.once('end', function () {
console.log('Connection ended');
});
imap.connect();
It's not exactly what you asked for but an alternative implementation that uses ImapFlow module instead of node-imap, and that I just verified to work against Outlook looks like the script below. If you still get timeouts etc. then it is probably a firewall issue.
const { ImapFlow } = require("imapflow");
const fs = require("fs").promises;
const client = new ImapFlow({
host: "outlook.office365.com",
port: 993,
secure: true,
auth: {
user: "example.user#hotmail.com",
pass: "secretpass",
},
logger: false, // set to true if you want to see IMAP transaction logs
});
// can't run await in main scope, have to wrap it to an async function
async function main() {
// establish the connection and log in
await client.connect();
// open INBOX folder
let mailbox = await client.mailboxOpen("INBOX");
// list messages matching provided criteria
for await (let msg of client.fetch(
{
// search query to filter messages
// https://imapflow.com/global.html#SearchObject
seen: false,
subject: "Give Subject Here",
},
{
// attributes to request for
// https://imapflow.com/global.html#FetchQueryObject
uid: true,
flags: true,
internalDate: true,
bodyStructure: true,
// include full message body in the response as well
source: true,
}
)) {
// extract variables
let { seq, uid, flags, bodyStructure, internalDate, source } = msg;
console.log(`#${seq} Attributes:`, { seq, uid, flags, bodyStructure, internalDate });
// store message body as an eml file
await fs.writeFile(`msg-${seq}.eml`, source);
}
// close the connection
await client.logout();
}
main().catch(console.error);
Related
I want to isolate subscriberCount: '15' to it's own variable but nothing I do works here is all the data I have (some censored for security reasons) please try to help me!
Code
const Youtube = require("youtube-api")
, fs = require("fs")
, readJson = require("r-json")
, Lien = require("lien")
, Logger = require("bug-killer")
, opn = require("opn")
, prettyBytes = require("pretty-bytes")
;
// I downloaded the file from OAuth2 -> Download JSON
const CREDENTIALS = readJson(`${__dirname}/credentials.json`);
// Init lien server
let server = new Lien({
host: "localhost"
, port: 5000
});
// Authenticate
// You can access the Youtube resources via OAuth2 only.
// https://developers.google.com/youtube/v3/guides/moving_to_oauth#service_accounts
let oauth = Youtube.authenticate({
type: "oauth"
, client_id: CREDENTIALS.web.client_id
, client_secret: CREDENTIALS.web.client_secret
, redirect_url: CREDENTIALS.web.redirect_uris[0]
});
opn(oauth.generateAuthUrl({
access_type: "offline"
, scope: ["https://www.googleapis.com/auth/youtubepartner-channel-audit https://www.googleapis.com/auth/youtube https://www.googleapis.com/auth/youtubepartner-channel-audit https://www.googleapis.com/auth/youtube.readonly"]
}));
// Handle oauth2 callback
server.addPage("/oauth2callback", lien => {
Logger.log("Trying to get the token using the following code: " + lien.query.code);
oauth.getToken(lien.query.code, (err, tokens) => {
if (err) {
lien.lien(err, 400);
return Logger.log(err);
}
Logger.log("Got the tokens.");
oauth.setCredentials(tokens);
lien.end("Eyyy you logged in!");
// var req = Youtube.videos.insert({ });
function execute() {
return Youtube.channels.list({
"part": [
"statistics"
],
"mine": true,
"prettyPrint": true
})
.then(function(response) {
// Handle the results here (response.result has the parsed body).
//console.log("Response", response);
//console.log(typeof response.data.items);
//console.log(response.data.items);
//console.log(result);
console.log(response.data.items);
//console.log(response.statistics);
},
function(err) { console.error("Execute error", err); });
}
execute();
});
});
Response From google:
[
{
kind: 'youtube#channel',
etag: '*****',
id: '*****',
statistics: {
viewCount: '506',
subscriberCount: '15',
hiddenSubscriberCount: false,
videoCount: '12'
}
}
]
Jaromanda X gave the solution in a comment:
response.data.items is an Array, by the look of your question, ... so you'd need response.data.items[0].statistics.subscriberCount
I'd like to check emails every T minutes, using imap module for NodeJS.
So I set a timer:
_pollingTimer = setInterval(receiveEmails, constants.POLLING_TIME * 60 * 1000); // POLLING_TIME minutes polling
whereas the receiveEmails function is the following:
function receiveEmails() {
const imap = new Imap({
user: user_name,
password: user_pwd,
host: host_name,
port: host_port_imap,
tls: true
});
imap.once('ready', function () {
imap.openBox('INBOX', false, function (err, box) { //false means write enable
if (err) throw err;
imap.search(['UNSEEN'], function (err, results) {
if (err) throw err;
else if (!results || !results.length) {
logger.debug(`No new messages on the INBOX`);
}
else {
var f = imap.fetch(results, { bodies: ''});
f.on('message', _processMessage);
f.once('error', function (err) { console.log('Fetch error: ' + err); });
f.once('end', function() {
logger.debug(`Done fetching all messages!`);
imap.end();
});
}
});
});
});
imap.once('error', function (err) {
logger.error(`${err}`);
});
imap.once('end', function () {
logger.debug(`IMAP connection ended`);
});
imap.connect();
}
but calling this function multiple times returns LOGIN failed error. It seems related to multiple login attempts.
I tried declaring the imap variable outside the function but nothing changes.
So, how can I periodically check for new emails avoiding reconnections?
I need to configure the knexfile.js using the secrets retrieve from the secret manager.
I retrieve the secrets from secret manager and stores it in secret variable and use it in configuration.
var AWS = require('aws-sdk'),
endpoint = "abcd",
region = "us-east-1",
secretName = "abcd",
secret,
binarySecretData;
var client = new AWS.SecretsManager({
endpoint: endpoint,
region: region
});
client.getSecretValue({
SecretId: secretName
}, function (err, data) {
if (err) {
if (err.code === 'ResourceNotFoundException')
console.log("The requested secret " + secretName + " was not found");
else if (err.code === 'InvalidRequestException')
console.log("The request was invalid due to: " + err.message);
else if (err.code === 'InvalidParameterException')
console.log("The request had invalid params: " + err.message);
} else {
if (data.SecretString !== "") {
secret = data.SecretString;
} else {
binarySecretData = data.SecretBinary;
}
}
});
module.exports = {
development: {
client: secret.localClient,
connection: {
host: secret.localHost,
user: secret.localUser,
password: secret.localPassword,
database: secret.localDatabase,
charset: "utf8"
}
},
};
But it shows an error
TypeError: Cannot read property 'localClient' of undefined
This is now possible in Knex. You can pass an async function to the configuration.
async function getConfig() {
return new Promise((resolve, reject) => {
client.getSecretValue({ SecretId: 'SECRETID' }, function(
err,
data
) {
if (err) {
console.log('secretsErr', err);
reject(err);
} else {
console.log('Secrets Manager call successful');
if ('SecretString' in data) {
let secret = data.SecretString;
secret = JSON.parse(secret);
const config = {
user: secret.DbUser,
password: secret.DbPassword,
server: secret.DbServer,
database: secret.DbDatabase,
expirationChecker: () => false,
options: {
encrypt: true,
enableArithAbort: true
}
};
resolve(config);
} else {
console.log('no secret found');
reject();
}
}
});
}
let knex = require('knex')({
client: 'mssql',
connection: async function() {
return await getConfig();
}
});
Getting secret is asynchronous operation, so your variable secret it doesn't exist yet when you are trying to export it from knexfile.js.
You probably should first fetch secret to be stored somewhere locally, when starting up virtual machine and then in knexfile.js read it synchronously for example from local file.
How Can I insert New Telegram Bot user to CouchDB?
I inserted a Sample Data jack johnsin db and was ok, But I Don't Know How Should I Take Telegram users Username and Put That in Db.
This is My Code:
import 'babel-polyfill';
import './env';
import TelegramBot from 'node-telegram-bot-api';
const bot = new TelegramBot(process.env.BOT_TOKEN, {polling: true});
/////////////////////////////////// Sample Data
var server = require('couch-db')('http://localhost:5984');
var db = server.database('users');
db.destroy(function(err) {
// create a new database
db.create(function(err) {
// insert a document with id 'jack johns'
db.insert({ _id: 'jack johns', name: 'jack' }, function(err, body) {
if (err) {
console.log('insertion failed ', err.message);
return;
}
console.log(body);
// body will like following:
// { ok: true,
// id: 'jack johns',
// rev: '1-610953b93b8bf1bae12427e2de181307' }
});
});
});
//////////////////////////////
bot.onText(/^[\/!#]start$/, msg => {
const opts = {
reply_to_message_id: msg.message_id,
reply_markup: JSON.stringify({
keyboard: [['Store username']],
resize_keyboard:true,
one_time_keyboard: true
})
};
bot.sendMessage(msg.chat.id, 'You Are Exist in DB', opts);
});
Solved By Myselfe,
For User ID You Can Use User_ID: msg.from.id
This is My Code:
bot.onText(/^[\/!#]start$/, msg => {
db.insert({ _id: msg.from.username }, function(err, body) {
if (err) {
console.log('insertion failed ', err.message);
return;
}
console.log(body);
});
const opts = {
reply_to_message_id: msg.message_id,
reply_markup: JSON.stringify({
keyboard: [['Store username']],
resize_keyboard:true,
one_time_keyboard: true
})
};
bot.sendMessage(msg.chat.id, 'You Are Exist in DB', opts);
});
Is it sensible to use Node.js to write a stand alone app that will connect two REST API's?
One end will be a POS - Point of sale - system
The other will be a hosted eCommerce platform
There will be a minimal interface for configuration of the service. nothing more.
Yes, Node.js is perfectly suited to making calls to external APIs. Just like everything in Node, however, the functions for making these calls are based around events, which means doing things like buffering response data as opposed to receiving a single completed response.
For example:
// get walking directions from central park to the empire state building
var http = require("http");
url = "http://maps.googleapis.com/maps/api/directions/json?origin=Central Park&destination=Empire State Building&sensor=false&mode=walking";
// get is a simple wrapper for request()
// which sets the http method to GET
var request = http.get(url, function (response) {
// data is streamed in chunks from the server
// so we have to handle the "data" event
var buffer = "",
data,
route;
response.on("data", function (chunk) {
buffer += chunk;
});
response.on("end", function (err) {
// finished transferring data
// dump the raw data
console.log(buffer);
console.log("\n");
data = JSON.parse(buffer);
route = data.routes[0];
// extract the distance and time
console.log("Walking Distance: " + route.legs[0].distance.text);
console.log("Time: " + route.legs[0].duration.text);
});
});
It may make sense to find a simple wrapper library (or write your own) if you are going to be making a lot of these calls.
Sure. The node.js API contains methods to make HTTP requests:
http.request
http.get
I assume the app you're writing is a web app. You might want to use a framework like Express to remove some of the grunt work (see also this question on node.js web frameworks).
/*Below logics covered in below sample GET API
-DB connection created in class
-common function to execute the query
-logging through bunyan library*/
const { APIResponse} = require('./../commonFun/utils');
const createlog = require('./../lib/createlog');
var obj = new DB();
//Test API
routes.get('/testapi', (req, res) => {
res.status(201).json({ message: 'API microservices test' });
});
dbObj = new DB();
routes.get('/getStore', (req, res) => {
try {
//create DB instance
const store_id = req.body.storeID;
const promiseReturnwithResult = selectQueryData('tablename', whereField, dbObj.conn);
(promiseReturnwithResult).then((result) => {
APIResponse(200, 'Data fetched successfully', result).then((result) => {
res.send(result);
});
}).catch((err) => { console.log(err); throw err; })
} catch (err) {
console.log('Exception caught in getuser API', err);
const e = new Error();
if (err.errors && err.errors.length > 0) {
e.Error = 'Exception caught in getuser API';
e.message = err.errors[0].message;
e.code = 500;
res.status(404).send(APIResponse(e.code, e.message, e.Error));
createlog.writeErrorInLog(err);
}
}
});
//create connection
"use strict"
const mysql = require("mysql");
class DB {
constructor() {
this.conn = mysql.createConnection({
host: 'localhost',
user: 'root',
password: 'pass',
database: 'db_name'
});
}
connect() {
this.conn.connect(function (err) {
if (err) {
console.error("error connecting: " + err.stack);
return;
}
console.log("connected to DBB");
});
}
//End class
}
module.exports = DB
//queryTransaction.js File
selectQueryData= (table,where,db_conn)=>{
return new Promise(function(resolve,reject){
try{
db_conn.query(`SELECT * FROM ${table} WHERE id = ${where}`,function(err,result){
if(err){
reject(err);
}else{
resolve(result);
}
});
}catch(err){
console.log(err);
}
});
}
module.exports= {selectQueryData};
//utils.js file
APIResponse = async (status, msg, data = '',error=null) => {
try {
if (status) {
return { statusCode: status, message: msg, PayLoad: data,error:error }
}
} catch (err) {
console.log('Exception caught in getuser API', err);
}
}
module.exports={
logsSetting: {
name: "USER-API",
streams: [
{
level: 'error',
path: '' // log ERROR and above to a file
}
],
},APIResponse
}
//createlogs.js File
var bunyan = require('bunyan');
const dateFormat = require('dateformat');
const {logsSetting} = require('./../commonFun/utils');
module.exports.writeErrorInLog = (customError) => {
let logConfig = {...logsSetting};
console.log('reached in writeErrorInLog',customError)
const currentDate = dateFormat(new Date(), 'yyyy-mm-dd');
const path = logConfig.streams[0].path = `${__dirname}/../log/${currentDate}error.log`;
const log = bunyan.createLogger(logConfig);
log.error(customError);
}
A more easy and useful tool is just using an API like Unirest; URest is a package in NPM that is just too easy to use jus like
app.get('/any-route', function(req, res){
unirest.get("https://rest.url.to.consume/param1/paramN")
.header("Any-Key", "XXXXXXXXXXXXXXXXXX")
.header("Accept", "text/plain")
.end(function (result) {
res.render('name-of-the-page-according-to-your-engine', {
layout: 'some-layout-if-you-want',
markup: result.body.any-property,
});
});