wildduck/imap-core/lib/indexer/create-envelope.js

99 lines
2.9 KiB
JavaScript

'use strict';
const libmime = require('libmime');
const punycode = require('punycode');
// This module converts message structure into an ENVELOPE object
/**
* Convert a message header object to an ENVELOPE object
*
* @param {Object} message A parsed mime tree node
* @return {Object} ENVELOPE compatible object
*/
module.exports = function(header) {
let subject = Array.isArray(header.subject) ? header.subject.reverse().filter(line => line.trim()) : header.subject;
subject = Buffer.from(subject || '', 'binary').toString();
try {
subject = Buffer.from(libmime.decodeWords(subject).trim());
} catch (E) {
// failed to parse subject, keep as is (most probably an unknown charset is used)
}
return [
header.date || null,
subject,
processAddress(header.from),
processAddress(header.sender, header.from),
processAddress(header['reply-to'], header.from),
processAddress(header.to),
processAddress(header.cc),
processAddress(header.bcc),
header['in-reply-to'] || null,
header['message-id'] || null
];
};
/**
* Converts an address object to a list of arrays
* [{name: 'User Name', addres:'user@example.com'}] -> [['User Name', null, 'user', 'example.com']]
*
* @param {Array} arr An array of address objects
* @return {Array} A list of addresses
*/
function processAddress(arr, defaults) {
arr = [].concat(arr || []);
if (!arr.length) {
arr = [].concat(defaults || []);
}
if (!arr.length) {
return null;
}
let result = [];
arr.forEach(addr => {
if (!addr.group) {
let name = addr.name || null;
let user = (addr.address || '').split('@').shift() || null;
let domain = (addr.address || '').split('@').pop() || null;
if (name) {
try {
name = Buffer.from(libmime.decodeWords(name));
} catch (E) {
// failed to parse
}
}
if (user) {
try {
user = Buffer.from(libmime.decodeWords(user));
} catch (E) {
// failed to parse
}
}
if (domain) {
domain = Buffer.from(punycode.toUnicode(domain));
}
result.push([name, null, user, domain]);
} else {
// Handle group syntax
let name = addr.name || '';
if (name) {
try {
name = Buffer.from(libmime.decodeWords(name));
} catch (E) {
// failed to parse
}
}
result.push([null, null, name, null]);
result = result.concat(processAddress(addr.group) || []);
result.push([null, null, null, null]);
}
});
return result;
}