diff --git a/examples/push-message.js b/examples/push-message.js index 77cea5f6..577c4fd7 100644 --- a/examples/push-message.js +++ b/examples/push-message.js @@ -3,6 +3,7 @@ 'use strict'; const recipient = process.argv[2]; +const total = Number(process.argv[3]) || 1; if (!recipient) { console.error('Usage: node example.com username@exmaple.com'); // eslint-disable-line no-console @@ -22,7 +23,6 @@ const transporter = nodemailer.createTransport({ }); let sent = 0; -let total = 1; let startTime = Date.now(); function send() { @@ -74,7 +74,7 @@ function send() { if (sent >= total) { console.log('Sent %s messages in %s s', sent, (Date.now() - startTime) / 1000); return transporter.close(); - }else { + } else { send(); } }); diff --git a/imap-core/lib/indexer/indexer.js b/imap-core/lib/indexer/indexer.js index 49c9151d..9636c183 100644 --- a/imap-core/lib/indexer/indexer.js +++ b/imap-core/lib/indexer/indexer.js @@ -246,6 +246,7 @@ class Indexer { * @return {Object} Parsed mime tree */ storeAttachments(messageId, mimeTree, sizeLimit, callback) { + mimeTree.attachments = []; let walk = (node, next) => { let continueProcessing = () => { @@ -307,6 +308,16 @@ class Indexer { } }); + if (!['text/plain', 'text/html'].includes(contentType) || disposition === 'attachment') { + mimeTree.attachments.push({ + id: attachmentId, + fileName, + contentType, + disposition, + transferEncoding + }); + } + store.once('error', err => { if (returned) { return; diff --git a/imap.js b/imap.js index f938b8d2..0eeaf849 100644 --- a/imap.js +++ b/imap.js @@ -1213,6 +1213,22 @@ server.onSearch = function (path, options, session, callback) { }); } break; + case 'header': + { + if (!query.$and) { + query.$and = []; + } + query.$and.push(term.value ? { + 'headers.key': term.header, + 'headers.value': { + // FIXME: this does not match unicode symbols for whatever reason + $regex: Buffer.from(term.value, 'binary').toString().replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&') + } + } : { + 'headers.key': term.header + }); + } + break; case 'not': [].concat(term.value || []).forEach(term => { switch (term.key) { diff --git a/indexes.json b/indexes.json index f244d397..c6947d0e 100644 --- a/indexes.json +++ b/indexes.json @@ -102,6 +102,12 @@ "key": { "uid": 1 } + }, { + "name": "by_headers", + "key": { + "headers.key": 1, + "headers.value": 1 + } }] }, { "collection": "attachment.files", diff --git a/lib/message-handler.js b/lib/message-handler.js index d0f4add6..3c61eea4 100644 --- a/lib/message-handler.js +++ b/lib/message-handler.js @@ -7,6 +7,7 @@ const RedFour = require('redfour'); const Indexer = require('../imap-core/lib/indexer/indexer'); const ImapNotifier = require('./imap-notifier'); const tools = require('./tools'); +const libmime = require('libmime'); class MessageHandler { @@ -63,6 +64,23 @@ class MessageHandler { let messageId = envelope[9] || ('<' + uuidV1() + '@wildduck.email>'); + let headers = (mimeTree.header || []).map(line => { + line = Buffer.from(line, 'binary').toString(); + + let key = line.substr(0, line.indexOf(':')).trim().toLowerCase(); + let value = line.substr(line.indexOf(':') + 1).trim().toLowerCase().replace(/\s*\r?\n\s*/g, ' '); + + try { + value = libmime.decodeWords(value); + } catch (E) { + // ignore + } + return { + key, + value + }; + }); + this.getMailbox(options, (err, mailbox) => { if (err) { return callback(err); @@ -157,6 +175,7 @@ class MessageHandler { meta: options.meta || {}, + headers, mimeTree, envelope, bodystructure, diff --git a/package.json b/package.json index c75cd2d9..68c638e8 100644 --- a/package.json +++ b/package.json @@ -26,7 +26,6 @@ "joi": "^10.3.4", "libbase64": "^0.1.0", "libmime": "^3.1.0", - "mailparser": "^2.0.2", "mongodb": "^2.2.25", "nodemailer": "^3.1.8", "npmlog": "^4.0.2", diff --git a/server.js b/server.js index 76434950..93765d1c 100644 --- a/server.js +++ b/server.js @@ -10,12 +10,15 @@ log.level = config.log.level; require('./logger'); let printLogo = () => { - log.info('App', '.##...##..######..##......#####...#####...##..##...####...##..##.'); - log.info('App', '.##...##....##....##......##..##..##..##..##..##..##..##..##.##..'); - log.info('App', '.##.#.##....##....##......##..##..##..##..##..##..##......####...'); - log.info('App', '.#######....##....##......##..##..##..##..##..##..##..##..##.##..'); - log.info('App', '..##.##...######..######..#####...#####....####....####...##..##.'); - log.info('App', ' --- v' + packageData.version + ' ---'); + log.info('App', ''); + log.info('App', ' ## ## ###### ## ##### ##### ## ## #### ## ##'); + log.info('App', ' ## ## ## ## ## ## ## ## ## ## ## ## ## ##'); + log.info('App', ' ## # ## ## ## ## ## ## ## ## ## ## ####'); + log.info('App', ' ####### ## ## ## ## ## ## ## ## ## ## ## ##'); + log.info('App', ' ## ## ###### ###### ##### ##### #### #### ## ##'); + log.info('App', ''); + log.info('App', ' --- v' + packageData.version + ' ---'); + log.info('App', ''); }; if (!config.processes || config.processes <= 1) {