mail-listener6
Version:
Mail listener library for node.js. Get notification when new email arrived.
148 lines (138 loc) • 4.27 kB
JavaScript
/**@module mail-listener5
* @author Vijaykumar <matej@malicek.co>
* @version 1.0.0
* @date 15 April 2021
*/
// Require statements
var Imap = require('imap');
var EventEmitter = require('events').EventEmitter;
var simpleParser = require('mailparser').simpleParser;
var fs = require('fs');
var path = require('path');
var async = require('async');
class MailListener extends EventEmitter {
constructor(options) {
super();
this.markSeen = !! options.markSeen;
this.mailbox = options.mailbox || 'INBOX';
if ('string' === typeof options.searchFilter)
{
this.searchFilter = [options.searchFilter];
}
else
{
this.searchFilter = options.searchFilter || ['UNSEEN'];
}
this.fetchUnreadOnStart = !! options.fetchUnreadOnStart;
this.mailParserOptions = options.mailParserOptions || {};
if (options.attachments && options.attachmentOptions && options.attachmentOptions.stream)
{
this.mailParserOptions.streamAttachments = true;
}
this.attachmentOptions = options.attachmentOptions || {};
this.attachments = options.attachments || false;
this.attachmentOptions.directory = (this.attachmentOptions.directory ? this.attachmentOptions.directory : '');
this.imap = new Imap({
xoauth2: options.xoauth2,
user: options.username,
password: options.password,
host: options.host,
port: options.port,
tls: options.tls,
tlsOptions: options.tlsOptions || {},
connTimeout: options.connTimeout || null,
authTimeout: options.authTimeout || null,
debug: options.debug || null
});
this.imap.once('ready', this.imapReady.bind(this));
this.imap.once('close', this.imapClose.bind(this));
this.imap.on('error', this.imapError.bind(this));
}
start() {
this.imap.connect();
}
stop() {
this.imap.end();
}
imapReady() {
this.imap.openBox(this.mailbox, false, (error, mailbox) => {
if (error)
{
this.emit('error', error);
}
else
{
this.emit('server:connected');
this.emit('mailbox', mailbox);
if (this.fetchUnreadOnStart)
{
this.parseUnread.call(this);
}
let listener = this.imapMail.bind(this);
this.imap.on('mail', listener);
this.imap.on('update', listener);
}
});
}
imapClose() {
this.emit('server:disconnected');
}
imapError(error) {
this.emit('error', error);
}
imapMail() {
this.parseUnread.call(this);
}
parseUnread() {
let self = this;
self.imap.search(self.searchFilter, (error, results) => {
if (error)
{
self.emit('error', err);
}
else if (results.length > 0)
{
async.each(results, (result, callback) => {
let f = self.imap.fetch(result, {
bodies: '',
markSeen: self.markSeen
});
f.on('message', (msg, seqno) => {
msg.on('body', async (stream, info) => {
let parsed = await simpleParser(stream);
self.emit('mail', parsed, seqno);
self.emit('headers', parsed.headers, seqno);
self.emit('body', {html: parsed.html, text: parsed.text, textAsHtml: parsed.textAsHtml}, seqno);
if (parsed.attachments.length>0)
{
for (let att of parsed.attachments)
{
if (self.attachments)
{
await fs.writeFile(`${self.attachmentOptions.directory}${att.filename}`, att.content, (error) =>{
self.emit('error', error);
});
self.emit('attachment', att, `${self.attachmentOptions.directory}${att.filename}`, seqno);
}
else
{
self.emit('attachment', att, null, seqno);
}
}
}
});
});
f.once('error', (error) => {
self.emit('error', error);
});
}, (error) => {
if (error)
{
self.emit('error', error);
}
});
}
});
}
};
module.exports.MailListener = MailListener;