This code provides a function to programmatically search and retrieve emails from an IMAP server, allowing for filtering by sender, subject, date range, and mailbox.
npm run import -- "search for messages using simple-imap"
var chrono = require('chrono-node');
var importer = require('../Core');
var imapClient = importer.import("node imap client");
var util = require('util');
function flatten(messages) {
return messages.map(message => {
var header = message.parts.filter(function (part) {
return part.which.indexOf('HEADER') > -1;
});
var text = message.parts.filter(function (part) {
return part.which.indexOf('TEXT') > -1;
});
var subject = header[0].body.subject[0];
var from = header[0].body.from[0];
var to = header[0].body.to[0];
var date = header[0].body.date[0];
from = ((/.+<(.*?)>/ig).exec(from) || [])[1] || from;
to = ((/.+<(.*?)>/ig).exec(to) || [])[1] || to;
return {
id: message.attributes.uid,
email: from,
subject,
body: text[0].body,
date: chrono.parseDate(date),
to
};
})
}
function searchImap(from = '*', subject = '*', days = 7, mailbox = 'INBOX') {
// Fetch emails from the last number of {days}
var delay = 24 * 3600 * 1000 * days;
var lastWeek = new Date();
lastWeek.setTime(Date.now() - delay);
lastWeek = lastWeek.toISOString();
var searchCriteria = [['SINCE', lastWeek]];
if(from !== '*') {
searchCriteria.push(['FROM', from])
}
if(subject !== '*') {
searchCriteria.push(['SUBJECT', subject])
}
var fetchOptions = {
bodies: ['HEADER.FIELDS (FROM TO SUBJECT DATE)', 'TEXT'],
struct: true
};
var imap;
return imapClient()
.then(c => {
imap = c;
if(mailbox !== 'INBOX') {
return util.promisify(imap.openBox.bind(imap))(mailbox)
}
})
.then(() => util.promisify(imap.search.bind(imap))(searchCriteria, fetchOptions))
.then(r => {
r.flatten = () => flatten(r);
return r;
})
.catch(e => console.log(e))
}
module.exports = searchImap;
const chrono = require('chrono-node');
const { openBox, search, searchCriteria } = require('node-imap-client');
const { promisify } = require('util');
const moment = require('moment');
/**
* Flattens an array of email messages into a simple object format
* @param {Object[]} messages - Array of email messages
* @returns {Object[]} - Array of flattened email objects
*/
function flatten(messages) {
// Use array.map to create a new array of flattened email objects
return messages.map(message => {
// Extract the email header and body parts
const header = message.parts.find(part => part.which.indexOf('HEADER') > -1);
const text = message.parts.find(part => part.which.indexOf('TEXT') > -1);
// Extract email metadata from the header
const subject = header.body.subject[0];
const from = header.body.from[0];
const to = header.body.to[0];
const date = header.body.date[0];
// Parse email addresses and dates
from = ((/.+<(.*?)>/ig).exec(from) || [])[1] || from;
to = ((/.+<(.*?)>/ig).exec(to) || [])[1] || to;
date = chrono.parseDate(date);
// Return the flattened email object
return {
id: message.attributes.uid,
email: from,
subject,
body: text.body,
date,
to
};
});
}
/**
* Searches an IMAP mailbox for emails based on specified criteria
* @param {string} [from='*'] - Email address to search by
* @param {string} [subject='*'] - Email subject to search by
* @param {number} [days=7] - Number of days to search back in time
* @param {string} [mailbox='INBOX'] - IMAP mailbox to search
* @returns {Promise} - Promise resolving to an array of flattened email objects
*/
async function searchImap({ from = '*', subject = '*', days = 7, mailbox = 'INBOX' } = {}) {
try {
// Calculate the search date based on the number of days
const delay = 24 * 3600 * 1000 * days;
const lastWeek = moment().subtract(days, 'days').toDate();
const lastWeekIso = lastWeek.toISOString();
// Create the search criteria
const searchCriteria = searchCriteria([
['SINCE', lastWeekIso]
]);
// Add search criteria for email address and subject if specified
if (from!== '*') {
searchCriteria.push(['FROM', from]);
}
if (subject!== '*') {
searchCriteria.push(['SUBJECT', subject]);
}
// Set up the fetch options
const fetchOptions = {
bodies: ['HEADER.FIELDS (FROM TO SUBJECT DATE)', 'TEXT'],
struct: true
};
// Initialize and connect to the IMAP client
const imap = await promisify(openBox.bind(imapClient))(mailbox);
// Search for emails based on the specified criteria
const searchResult = await promisify(search.bind(imap))(searchCriteria, fetchOptions);
// Flatten the email search result
searchResult.flatten = () => flatten(searchResult);
// Return the flattened email array
return searchResult;
} catch (e) {
console.error(e);
return Promise.reject(e);
}
}
module.exports = searchImap;
This code defines a function searchImap
that retrieves emails from an IMAP server based on specified criteria.
Here's a breakdown:
Dependencies:
chrono-node
: Used for parsing dates from email headers.node-imap-client
: A library for interacting with IMAP servers.util
: Node.js utility module.flatten
Function:
searchImap
Function:
from
, subject
, days
(number of days to search back), and mailbox
.node-imap-client
to connect to the IMAP server and execute the search.flatten
function to process the retrieved messages.In essence, this code provides a way to programmatically search and retrieve emails from an IMAP server based on customizable criteria.