Imap with Node.js, marking Email as read - node.js

I'm using Imap with node.js, and every time i connect it, it fetch al the emails from a data i gave it, but doens't mark them as read, so the following time it re-fecth them again.
Here is my code(All the functions implemented here are called in a main.js file), what can I change to mark the e-mail I'm fetching as read?
I've tried to do like written here (how to mark unseen email as seen with node-imap in node.js) but it didn't work..
var Imap = require('imap');
var inspect = require('util').inspect;
var formatter = require('./formatter.js');
var mailError = exports.mailError = [];
var imap = new Imap({
user: 'aaaaaaaaa#gmail.com',
password: 'xxxxxxx',
host: 'imap.gmail.com',
port: 993, //Perchè non 143, standard IMAP?
tls: true,
markSeen: true
});
function openInbox(cb) {
imap.openBox('INBOX', false, cb);
}
var onBodyCb = exports.onBodyCb = function(parsedHeaders, body){
var pos = (body.indexOf("Delivery to the following recipient failed permanently:") + 55);
var address = body.substr(pos,50);
var at = address.indexOf("#");
address = address.substr(0,at+formatter.company.length+formatter.domain.length+2);
address = address.replace(/ /g,'');
address = address.replace(/(\r\n|\n|\r)/gm,"");
console.log("onBodyCB: "+address+'\n');
mailError.push(address);
};
var onFinishedFetching = exports.onFinishedFetching = function(){};
imap.once('ready', function() {
var fs = require('fs'), fileStream;
openInbox(function(err, box) {
if (err) throw err;
imap.search([ 'UNSEEN', ['SINCE', 'July 10, 2014'] ], function(err, results) {
if (err) throw err;
// a questo abbiamo la box a cui possiamo accedere
var f = imap.fetch(results, { bodies: '' });
f.on('message', function(msg, seqno) {
//console.log('Message #%d', seqno);
var prefix = '(#' + seqno + ') ';
msg.on('body', function(stream, info) {
console.log(prefix + 'Body');
var buffer = '';
stream.on('data', function(chunk) {
buffer += chunk.toString('utf8');
});
//console.log(buffer);
stream.once('end', function() {
//console.log(prefix + 'Parsed header: %s', inspect());
var header = Imap.parseHeader(buffer);
exports.onBodyCb(header, buffer);
});
});
//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();
exports.onFinishedFetching();
});
});
});
});
imap.once('error', function(err) {
console.log(err);
});
imap.once('end', function() {
console.log('Connection ended');
});
exports.connect = function(){
imap.connect();
};
EDIT:
I've changed as suggested but it still doesn't work...
var Imap = require('imap');
var inspect = require('util').inspect;
var formatter = require('./formatter.js');
var mailError = exports.mailError = [];
var imap = new Imap({
user: 'marco.loco.recruiter#gmail.com',
password: 'coci2014',
host: 'imap.gmail.com',
port: 993, //Perchè non 143, standard IMAP?
tls: true,
markSeen : true,
markRead : true
});
function openInbox(cb) {
imap.openBox('INBOX', false, cb);
}
var onBodyCb = exports.onBodyCb = function(parsedHeaders, body){
var pos = (body.indexOf("Delivery to the following recipient failed permanently:") + 55);
var address = body.substr(pos,50);
var at = address.indexOf("#");
address = address.substr(0,at+formatter.company.length+formatter.domain.length+2);
address = address.replace(/ /g,'');
address = address.replace(/(\r\n|\n|\r)/gm,"");
console.log("onBodyCB: "+address+'\n');
mailError.push(address);
};
var onFinishedFetching = exports.onFinishedFetching = function(){};
imap.once('ready', function() {
var fs = require('fs'), fileStream;
openInbox(function(err, box) {
if (err) throw err;
imap.search([ 'UNSEEN', ['SINCE', 'July 10, 2014'] ], function(err, results) {
if (err) throw err;
// a questo abbiamo la box a cui possiamo accedere
var f = imap.fetch(results, { bodies: '' });
f.on('message', function(msg, seqno) {
//console.log('Message #%d', seqno);
var prefix = '(#' + seqno + ') ';
msg.on('body', function(stream, info) {
//console.log(prefix + 'Body');
var buffer = '';
stream.on('data', function(chunk) {
buffer += chunk.toString('utf8');
});
//console.log(buffer);
stream.once('end', function() {
//console.log(prefix + 'Parsed header: %s', inspect());
var header = Imap.parseHeader(buffer);
exports.onBodyCb(header, buffer);
});
});
//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();
exports.onFinishedFetching();
});
});
},false);
});
imap.once('error', function(err) {
console.log(err);
});
imap.once('end', function() {
console.log('Connection ended');
});
exports.connect = function(){
imap.connect();
};

var Imap = require("imap");
var MailParser = require("mailparser").MailParser;
var Promise = require("bluebird");
Promise.longStackTraces();
var imapConfig = {
user: 'USERNAME',
password: 'PASSWORD',
host: 'HOST',
port: 993,
tls: true
};
var imap = new Imap(imapConfig);
Promise.promisifyAll(imap);
imap.once("ready", execute);
imap.once("error", function(err) {
log.error("Connection error: " + err.stack);
});
imap.connect();
function execute() {
imap.openBox("INBOX", false, function(err, mailBox) {
if (err) {
console.error(err);
return;
}
imap.search(["UNSEEN"], function(err, results) {
if(!results || results.length){console.log("No unseen email available"); imap.end();return;}
imap.setFlags(results, ['\\Seen'], function(err) {
if (!err) {
console.log("marked as read");
} else {
console.log(JSON.stringify(err, null, 2));
}
});
var f = imap.fetch(results, { bodies: "" });
f.on("message", processMessage);
f.once("error", function(err) {
return Promise.reject(err);
});
f.once("end", function() {
console.log("Done fetching all unseen messages.");
imap.end();
});
});
});
}
function processMessage(msg, seqno) {
console.log("Processing msg #" + seqno);
// console.log(msg);
var parser = new MailParser();
parser.on("headers", function(headers) {
console.log("Header: " + JSON.stringify(headers));
});
parser.on('data', data => {
if (data.type === 'text') {
console.log(seqno);
console.log(data.text); /* data.html*/
}
// if (data.type === 'attachment') {
// console.log(data.filename);
// data.content.pipe(process.stdout);
// // data.content.on('end', () => data.release());
// }
});
msg.on("body", function(stream) {
stream.on("data", function(chunk) {
parser.write(chunk.toString("utf8"));
});
});
msg.once("end", function() {
// console.log("Finished msg #" + seqno);
parser.end();
});
}
{markRead: true} flag sometime it doesn't work, so you need to call set imap.setFlags([uuids], ['\Seen'], cb) explicitly

This is old question, but I had the same problem today. in the imap.seq.fetch call, there needs to be markSeen:true besides the bodies:"" . it should look like fetch(results,{bodies:"", markSeen:true}) –
And don't forget to open the Inbox in read-write mode as so many have said. imap.openBox('INBOX', false, cb)

Here is a working example to do the same.
var Imap = require('imap'),
inspect = require('util').inspect;
var imap = new Imap({
user: 'USERNAME',
password: 'PASSWORD',
host: 'IMAP_HOST',
port: 993, // Default port is 993
tls: true,
tlsOptions: {rejectUnauthorized: false}
});
function openInbox(cb) {
// openReadOnly = false
imap.openBox('Inbox', false, cb);
}
imap.once('ready', function () {
openInbox(function (err, box) {
if (err) throw err;
// Search emails having "Some Subject" in their Subject headers
imap.search([['HEADER', 'SUBJECT', 'Some Subject']], function (err, results) {
if (err) throw err;
try {
var f = imap.fetch(results, {bodies: 'TEXT'});
f.on('message', function (msg, seqno) {
msg.on('body', function (stream, info) {
var buffer = '';
stream.on('data', function (chunk) {
buffer += chunk.toString('utf8');
});
stream.once('end', function () {
// Mark the above mails as read
msg.once('attributes', function (attrs) {
let uid = attrs.uid;
imap.addFlags(uid, ['\\Seen'], function (err) {
if (err) {
console.log(err);
} else {
console.log("Marked as read!")
}
});
});
});
});
});
f.once('end', function () {
imap.end();
});
} catch (errorWhileFetching) {
console.log(errorWhileFetching.message);
imap.end();
}
});
});
});
imap.connect();

Related

Check Mailbox in a Loop, Read Email and Create PDF

I have a code that reads unseen emails and creates pdf.
The problem is;
I cannot pull email if any new unseen email exist without executing code again.
var Imap = require('imap');
const MailParser = require('mailparser').MailParser;
var pdf = require('html-pdf');
var fs = require('fs');
var Promise = require("bluebird");
Promise.longStackTraces();
var imapConfig = {
user: '*****',
password: '*****',
host: 'imap.gmail.com',
port: 993,
tls: true
};
var imap = new Imap(imapConfig);
Promise.promisifyAll(imap);
imap.once("ready", execute);
imap.once("error", function(err) {
log.error("Connection error: " + err.stack);
});
imap.connect();
function execute() {
imap.openBox("INBOX", false, function(err, mailBox) {
if (err) {
console.error(err);
return;
}
imap.search(["UNSEEN"], function(err, results) {
if(!results || !results.length){console.log("No unread mails");imap.end();return;}
var f = imap.fetch(results, { bodies: "" });
f.on("message", processMessage);
f.once("error", function(err) {
return Promise.reject(err);
});
f.once("end", function() {
console.log("Done fetching all unseen messages.");
imap.end();
});
});
});
}
const options = { format: 'A2', width:"19in", height:"17in", orientation: "portrait" };
function processMessage(msg, seqno) {
console.log("Processing msg #" + seqno);
// console.log(msg);
var parser = new MailParser();
parser.on("headers", function(headers) {
console.log("Header: " + JSON.stringify(headers));
});
parser.on('data', data => {
if (data.type === 'text') {
console.log(seqno);
console.log(data.html); /* data.html*/
var test = data.html
pdf.create(test, options).toStream(function(err, stream){
stream.pipe(fs.createWriteStream('./foo.pdf'));
});
}
});
msg.on("body", function(stream) {
stream.on("data", function(chunk) {
parser.write(chunk.toString("utf8"));
});
});
msg.once("end", function() {
// console.log("Finished msg #" + seqno);
parser.end();
});
}
Also I have tried to use setInterval to check new unseen emails but I get
'Error: Not authenticated'
How can I pull new unseen emails in a loop and create pdf from that email?
Your observation is correct. You must poll your IMAP (or POP3) server on a regular schedule to keep up with incoming messages. Depending on your requirements, a schedule of once every few minutes is good.
continous polling, or polling every second or so, is very rude. The operator of the IMAP server may block your application if you try to do that: it looks to them like an attempt to overload the server.

node.js mariasql return undefined

I believe i have a problem with the Syntax.
By the Function xx the return is undefined :(.
Here the Problem in one File.
var Client = require('mariasql');
var inspect = require('util').inspect;
var c = new Client();
c.connect({
host: '127.0.0.1',
user: 'root',
password: '38nudel5nu',
db: 'artikel2'
});
var login = function(){
console.log("LOGIN\n");
c.on('connect', function() {
console.log('Client connected');
})
.on('error', function(err) {
console.log('Client error: ' + err);
})
.on('close', function(hadError) {
console.log('Client closed');
});
}
var end = function(){
console.log("EXIT");
c.end();
}
login();
var xx = function(){
c.query("SELECT COUNT(ArtikelID) AS Count FROM artikel")
.on('result', function(res) {
res.on('row', function(row) {
return "YOLO";
})
.on('error', function(err) {
})
.on('end', function(info) {
});
})
.on('end', function() {
});
}
var autohaus = xx();
console.log("\n\n --> " + autohaus);
And here is the Output:
[cseipel#myhost testumgebung]$ node skript.js LOGIN
--> undefined Client connected
You're using an asynchronous function as if it were synchronous. That's not going to work. You need to pass in a callback to your ArtikelCount function and call the callback once you have the results you want (the typical convention for callbacks is to have the first argument be an error if an error occurred, otherwise it should be null).
Example:
var ArtikelCount = function(cb) {
var count,
error;
c.query('SELECT COUNT(ArtikelID) AS Count FROM artikel')
.on('result', function(res) {
res.on('row', function(row) {
count = row.Count;
})
.on('error', function(err) {
console.log('Result error: ' + inspect(err));
error = err;
})
.on('end', function(info) {
console.log('Result finished successfully');
});
})
.on('end', function() {
console.log('Done with all results');
cb(error, count);
});
}
Then use it like:
wc.ArtikelCount(function(err, count) {
if (err)
throw err;
else
console.log('Row count', count);
});

how to mark unseen email as seen with node-imap in node.js

i want to recieve email and mark email unseen as seen with node-imap. the recieving i have done, but i don't know how to mark email unseen as seen. the API offers a function seems like replace the code var f = imap.fetch(results, { bodies: '' }); with var f = imap.fetch(results, { markSeen : true });in the example,but it seems doesn't work. what should i do?
oh, i'va got solution. it's my fault to open mailbox in read-only mode, that's why i couldn't modify the mail's status.imap.openBox('INBOX', false, cb); the second args false means open mailbox not in read-only mode.
I tried setting mail status to false imap.openBox('INBOX', false, cb) but it didn't work at first.
But then I changed the data in body and set it to HEADER.FIELDS (FROM TO SUBJECT DATE) it worked. I don't know how is this related but it's working now while the mail box read-only status is false obviously.
Non working code:
imap.fetch(results, { bodies: '', markSeen: true });
Working code:
imap.fetch(results, { bodies: 'HEADER.FIELDS (FROM TO SUBJECT DATE)', markSeen: true });
Here is a working example for the same.
var Imap = require('imap'),
inspect = require('util').inspect;
var imap = new Imap({
user: 'USERNAME',
password: 'PASSWORD',
host: 'IMAP_HOST',
port: 993, // Default port is 993
tls: true,
tlsOptions: {rejectUnauthorized: false}
});
function openInbox(cb) {
// openReadOnly = false
imap.openBox('Inbox', false, cb);
}
imap.once('ready', function () {
openInbox(function (err, box) {
if (err) throw err;
// Search emails having "Some Subject" in their Subject headers
imap.search([['HEADER', 'SUBJECT', 'Some Subject']], function (err, results) {
if (err) throw err;
try {
var f = imap.fetch(results, {bodies: 'TEXT'});
f.on('message', function (msg, seqno) {
msg.on('body', function (stream, info) {
var buffer = '';
stream.on('data', function (chunk) {
buffer += chunk.toString('utf8');
});
stream.once('end', function () {
// Mark the above mails as read
msg.once('attributes', function (attrs) {
let uid = attrs.uid;
imap.addFlags(uid, ['\\Seen'], function (err) {
if (err) {
console.log(err);
} else {
console.log("Marked as read!")
}
});
});
});
});
});
f.once('end', function () {
imap.end();
});
} catch (errorWhileFetching) {
console.log(errorWhileFetching.message);
imap.end();
}
});
});
});
imap.connect();
imap.openBox("INBOX", false, function(err, mailBox) {
if (err) {
console.error(err);
return;
}
imap.search(["UNSEEN"], function(err, results) {
imap.setFlags(results, ['\\Seen'], function(err) {
if (!err) {
console.log("marked as read");
} else {
console.log(JSON.stringify(err, null, 2));
}
});
var f = imap.fetch(results, { bodies: "" });
f.on("message", processMessage);
f.once("error", function(err) {
return Promise.reject(err);
});
f.once("end", function() {
console.log("Done fetching all unseen messages.");
imap.end();
});
});
});
processMessage
function processMessage(msg seqno){
/*use mailparser*/}
so basically results contains the uuid
need to call imap.setFlags([uuids], ['\Seen'], cb) function explicitly to make it mark as read
client.messageFlagsAdd({uid: 116,seen: false}, ['\\Seen']);

How can i handle multiple imap connections in node.js?

how can i monitor multiple email accounts using imap at the same time using node.js?
I have a program to get notifications for single account using node-imap module and parsed emails using mail-parser.
var Imap = require('imap'),
inspect = require('util').inspect;
var MailParser = require('mailparser').MailParser;
var fs = require('fs');
var imap = new Imap(
{
user: 'any_email_address',
password: 'password',
host: 'imap.host.com',
port: 993,
tls: true,
tlsOptions:
{
rejectUnauthorized: false
}
});
function openInbox(cb)
{
imap.openBox('INBOX', true, cb);
}
var messages = []
imap.once('ready', function ()
{
openInbox(function (err, box)
{
console.log("open")
if (err) throw err;
imap.search(['ALL', []], function (err, results)
{
if (err) throw err;
var f = imap.fetch(results,
{
bodies: ''
});
f.on('message', function (msg, seqno)
{
var mailparser = new MailParser()
msg.on('body', function (stream, info)
{
stream.pipe(mailparser);
mailparser.on("end", function (mail)
{
fs.writeFile('msg-' + seqno + '-body.html', mail.html, function (err)
{
if (err) throw err;
console.log(seqno + 'saved!');
});
})
});
msg.once('end', function ()
{
console.log(seqno + '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();
this is simple
first, make a function that makes your connection and Global variable to put your connection on that and handle theme where ever you want
var Connection = [];
function connectImap(username, password, address, port, tls) {
if (typeof Connection[username] != typeof undefined &&
typeof Connection[username].state == typeof '' &&
Connection[username].state == 'authenticated' &&
Connection[username]._config.user == username &&
Connection[username]._config.password == password) {
console.log('IMAP-CLIENT-USE-AUTHENTICATED-CONNECTION ' + username);
} else {
port = port || 993;
tls = tls || true;
Connection[username] = new Imap({
user : username,
password : password,
host : address,
port : port,
authTimeout : 10000,
connTimeout : 10000,
keepalive : true,
tls : tls
});
console.log('IMAP-CLIENT-CONNECTED : ' + username);
}
}
now you have an array of different connection that means you can find the one you wanted.
i hope it helps
You have to create separate connections to monitor multiple accounts.

Read email body with node js imap

I'm trying to read the body of an e-mail that is retrieved with node js. I'm using this npm module: https://github.com/mscdex/node-imap
And I can get pretty much all the information of the email, except reading the content of the body.
Any ideas?
Thanks,
You can use this code to fetch email body and mark it as seen
var Imap = require("imap");
var MailParser = require("mailparser").MailParser;
var Promise = require("bluebird");
Promise.longStackTraces();
var imapConfig = {
user: 'USERNAME',
password: 'PASSWORD',
host: 'HOST',
port: 993,
tls: true
};
var imap = new Imap(imapConfig);
Promise.promisifyAll(imap);
imap.once("ready", execute);
imap.once("error", function(err) {
log.error("Connection error: " + err.stack);
});
imap.connect();
function execute() {
imap.openBox("INBOX", false, function(err, mailBox) {
if (err) {
console.error(err);
return;
}
imap.search(["UNSEEN"], function(err, results) {
if(!results || !results.length){console.log("No unread mails");imap.end();return;}
/* mark as seen
imap.setFlags(results, ['\\Seen'], function(err) {
if (!err) {
console.log("marked as read");
} else {
console.log(JSON.stringify(err, null, 2));
}
});*/
var f = imap.fetch(results, { bodies: "" });
f.on("message", processMessage);
f.once("error", function(err) {
return Promise.reject(err);
});
f.once("end", function() {
console.log("Done fetching all unseen messages.");
imap.end();
});
});
});
}
function processMessage(msg, seqno) {
console.log("Processing msg #" + seqno);
// console.log(msg);
var parser = new MailParser();
parser.on("headers", function(headers) {
console.log("Header: " + JSON.stringify(headers));
});
parser.on('data', data => {
if (data.type === 'text') {
console.log(seqno);
console.log(data.text); /* data.html*/
}
// if (data.type === 'attachment') {
// console.log(data.filename);
// data.content.pipe(process.stdout);
// // data.content.on('end', () => data.release());
// }
});
msg.on("body", function(stream) {
stream.on("data", function(chunk) {
parser.write(chunk.toString("utf8"));
});
});
msg.once("end", function() {
// console.log("Finished msg #" + seqno);
parser.end();
});
}
hope this code will help you :)
The Body of the message is in the spot where i have console.log("BUFFER", buffer)
I'm using node-imap npm module
imap.once('ready', function() {
openInbox(function(err, box) {
if (err) throw err;
var f = imap.seq.fetch(box.messages.total + ':*', { bodies: ['HEADER.FIELDS (FROM)','TEXT'] });
f.on('message', function(msg, seqno) {
console.log('Message #%d', seqno);
var prefix = '(#' + seqno + ') ';
msg.on('body', function(stream, info) {
if (info.which === 'TEXT')
console.log(prefix + 'Body [%s] found, %d total bytes', inspect(info.which), info.size);
var buffer = '', count = 0;
stream.on('data', function(chunk) {
count += chunk.length;
buffer += chunk.toString('utf8');
console.log("BUFFER", buffer)
if (info.which === 'TEXT')
console.log(prefix + 'Body [%s] (%d/%d)', inspect(info.which), count, info.size);
});
stream.once('end', function() {
if (info.which !== 'TEXT')
console.log(prefix + 'Parsed header: %s', inspect(Imap.parseHeader(buffer)));
else
console.log(prefix + 'Body [%s] Finished', inspect(info.which));
});
});
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();
});
});
});
Try:
msg.once('end', function() {
console.log(buffer);
});

Resources