mirror of
https://github.com/Foundry376/Mailspring.git
synced 2024-11-11 18:32:20 +08:00
157 lines
4.5 KiB
JavaScript
157 lines
4.5 KiB
JavaScript
|
const _ = require('underscore');
|
||
|
|
||
|
const {
|
||
|
IMAPConnectionNotReadyError,
|
||
|
} = require('./imap-errors');
|
||
|
|
||
|
class IMAPBox {
|
||
|
constructor(imapConn, box) {
|
||
|
this._conn = imapConn
|
||
|
this._box = box
|
||
|
|
||
|
return new Proxy(this, {
|
||
|
get(target, name) {
|
||
|
const prop = Reflect.get(target, name)
|
||
|
if (!prop) {
|
||
|
return Reflect.get(target._box, name)
|
||
|
}
|
||
|
if (_.isFunction(prop) && target._conn._imap._box.name !== target._box.name) {
|
||
|
return () => Promise.reject(
|
||
|
new Error(`IMAPBox::${name} - Can't operate on a mailbox that is no longer open on the current IMAPConnection.`)
|
||
|
)
|
||
|
}
|
||
|
return prop
|
||
|
},
|
||
|
})
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @param {array|string} range - can be a single message identifier,
|
||
|
* a message identifier range (e.g. '2504:2507' or '*' or '2504:*'),
|
||
|
* an array of message identifiers, or an array of message identifier ranges.
|
||
|
* @return {Observable} that will feed each message as it becomes ready
|
||
|
*/
|
||
|
fetchEach(range, options, forEachMessageCallback) {
|
||
|
if (!options) {
|
||
|
throw new Error("IMAPBox.fetch now requires an options object.")
|
||
|
}
|
||
|
if (range.length === 0) {
|
||
|
return Promise.resolve()
|
||
|
}
|
||
|
|
||
|
return this._conn.createConnectionPromise((resolve, reject) => {
|
||
|
const f = this._conn._imap.fetch(range, options);
|
||
|
f.on('message', (imapMessage) => {
|
||
|
const parts = {};
|
||
|
let headers = null;
|
||
|
let attributes = null;
|
||
|
imapMessage.on('attributes', (attrs) => {
|
||
|
attributes = attrs;
|
||
|
});
|
||
|
imapMessage.on('body', (stream, info) => {
|
||
|
const chunks = [];
|
||
|
|
||
|
stream.on('data', (chunk) => {
|
||
|
chunks.push(chunk);
|
||
|
});
|
||
|
|
||
|
stream.once('end', () => {
|
||
|
const full = Buffer.concat(chunks).toString('utf8');
|
||
|
if (info.which === 'HEADER') {
|
||
|
headers = full;
|
||
|
} else {
|
||
|
parts[info.which] = full;
|
||
|
}
|
||
|
});
|
||
|
});
|
||
|
imapMessage.once('end', () => {
|
||
|
forEachMessageCallback({attributes, headers, parts});
|
||
|
});
|
||
|
})
|
||
|
f.once('error', reject);
|
||
|
f.once('end', resolve);
|
||
|
});
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @return {Promise} that resolves to requested message
|
||
|
*/
|
||
|
fetchMessage(uid) {
|
||
|
if (!uid) {
|
||
|
throw new Error("IMAPConnection.fetchMessage requires a message uid.")
|
||
|
}
|
||
|
return this.fetchEach([uid], {
|
||
|
bodies: ['HEADER', 'TEXT'],
|
||
|
})
|
||
|
}
|
||
|
|
||
|
fetchMessageStream(uid, options) {
|
||
|
if (!uid) {
|
||
|
throw new Error("IMAPConnection.fetchStream requires a message uid.")
|
||
|
}
|
||
|
if (!options) {
|
||
|
throw new Error("IMAPConnection.fetchStream requires an options object.")
|
||
|
}
|
||
|
return this._conn.createConnectionPromise((resolve, reject) => {
|
||
|
const f = this._conn._imap.fetch(uid, options);
|
||
|
f.on('message', (imapMessage) => {
|
||
|
imapMessage.on('body', (stream) => {
|
||
|
resolve(stream)
|
||
|
})
|
||
|
})
|
||
|
f.once('error', reject)
|
||
|
})
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* @param {array|string} range - can be a single message identifier,
|
||
|
* a message identifier range (e.g. '2504:2507' or '*' or '2504:*'),
|
||
|
* an array of message identifiers, or an array of message identifier ranges.
|
||
|
* @return {Promise} that resolves to a map of uid -> attributes for every
|
||
|
* message in the range
|
||
|
*/
|
||
|
fetchUIDAttributes(range) {
|
||
|
return this._conn.createConnectionPromise((resolve, reject) => {
|
||
|
const attributesByUID = {};
|
||
|
const f = this._conn._imap.fetch(range, {});
|
||
|
f.on('message', (msg) => {
|
||
|
msg.on('attributes', (attrs) => {
|
||
|
attributesByUID[attrs.uid] = attrs;
|
||
|
})
|
||
|
});
|
||
|
f.once('error', reject);
|
||
|
f.once('end', () => resolve(attributesByUID));
|
||
|
});
|
||
|
}
|
||
|
|
||
|
addFlags(range, flags) {
|
||
|
if (!this._conn._imap) {
|
||
|
throw new IMAPConnectionNotReadyError(`IMAPBox::addFlags`)
|
||
|
}
|
||
|
return this._conn._imap.addFlagsAsync(range, flags)
|
||
|
}
|
||
|
|
||
|
delFlags(range, flags) {
|
||
|
if (!this._conn._imap) {
|
||
|
throw new IMAPConnectionNotReadyError(`IMAPBox::delFlags`)
|
||
|
}
|
||
|
return this._conn._imap.delFlagsAsync(range, flags)
|
||
|
}
|
||
|
|
||
|
moveFromBox(range, folderName) {
|
||
|
if (!this._conn._imap) {
|
||
|
throw new IMAPConnectionNotReadyError(`IMAPBox::moveFromBox`)
|
||
|
}
|
||
|
return this._conn._imap.moveAsync(range, folderName)
|
||
|
}
|
||
|
|
||
|
closeBox({expunge = true} = {}) {
|
||
|
if (!this._conn._imap) {
|
||
|
throw new IMAPConnectionNotReadyError(`IMAPBox::closeBox`)
|
||
|
}
|
||
|
return this._conn._imap.closeBoxAsync(expunge)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
module.exports = IMAPBox;
|