This commit is contained in:
Andris Reinman 2018-06-21 19:41:31 +03:00
parent 48d6e53d22
commit ca9455f813
4 changed files with 74 additions and 23 deletions

View file

@ -6,6 +6,16 @@ const utf7 = require('utf7').imap;
// tag LIST (SPECIAL-USE) "" "%" RETURN (SPECIAL-USE)
//"\\Sent", "\\Trash", "\\Junk", "\\Drafts", "\\Archive"
const XlistTags = new Map([
['INBOX', '\\Inbox'],
['\\Sent', '\\Sent'],
['\\Trash', '\\Trash'],
['\\Junk', '\\Spam'],
['\\Drafts', '\\Drafts'],
['\\Flagged', '\\Starred']
]);
module.exports = {
state: ['Authenticated', 'Selected'],
@ -43,6 +53,9 @@ module.exports = {
let arrPos = 0;
let commandName = (command.command || '').toString().toUpperCase();
let isXlist = commandName === 'XLIST' ? true : false;
// (SPECIAL-USE)
if (Array.isArray(command.attributes[0])) {
if (command.attributes[0].length) {
@ -53,7 +66,7 @@ module.exports = {
) {
filterSpecialUseFolders = true;
} else {
return callback(new Error('Invalid argument provided for LIST'));
return callback(new Error('Invalid argument provided for ' + commandName));
}
}
arrPos++;
@ -79,10 +92,10 @@ module.exports = {
) {
filterSpecialUseFlags = true;
} else {
return callback(new Error('Invalid argument provided for LIST'));
return callback(new Error('Invalid argument provided for ' + commandName));
}
} else {
return callback(new Error('Invalid argument provided for LIST'));
return callback(new Error('Invalid argument provided for ' + commandName));
}
}
@ -90,7 +103,7 @@ module.exports = {
if (typeof this._server.onList !== 'function') {
return callback(null, {
response: 'NO',
message: 'LIST not implemented'
message: commandName + ' not implemented'
});
}
@ -112,7 +125,7 @@ module.exports = {
let response = {
tag: '*',
command: 'LIST',
command: commandName,
attributes: []
};
@ -122,7 +135,26 @@ module.exports = {
flags = flags.concat(folder.flags || []);
}
flags = flags.concat(folder.specialUse || []);
let specialUseFlag = folder.specialUse;
if (specialUseFlag) {
if (isXlist && XlistTags.has(specialUseFlag)) {
// rewite flag to XLIST tag which is a bit different
specialUseFlag = XlistTags.get(specialUseFlag);
}
flags.push(specialUseFlag);
}
let path = folder.path;
if (!this.acceptUTF8Enabled) {
path = utf7.encode(path);
} else {
path = Buffer.from(path);
}
if (isXlist && path === 'INBOX') {
path = 'Inbox';
flags.push(XlistTags.get('INBOX'));
}
response.attributes.push(
flags.map(flag => ({
@ -132,12 +164,6 @@ module.exports = {
);
response.attributes.push('/');
let path = folder.path;
if (!this.acceptUTF8Enabled) {
path = utf7.encode(path);
} else {
path = Buffer.from(path);
}
response.attributes.push(path);
this.send(imapHandler.compiler(response));
@ -152,7 +178,7 @@ module.exports = {
// return delimiter only
let response = {
tag: '*',
command: 'LIST',
command: commandName,
attributes: [
[
{

View file

@ -17,6 +17,7 @@ const commands = new Map([
['AUTHENTICATE PLAIN-CLIENTTOKEN', require('./commands/authenticate-plain')],
['NAMESPACE', require('./commands/namespace')],
['LIST', require('./commands/list')],
['XLIST', require('./commands/list')],
['LSUB', require('./commands/lsub')],
['SUBSCRIBE', require('./commands/subscribe')],
['UNSUBSCRIBE', require('./commands/unsubscribe')],
@ -271,14 +272,14 @@ class IMAPCommand {
.concat(
response.code
? {
type: 'SECTION',
section: [
{
type: 'TEXT',
value: response.code
}
]
}
type: 'SECTION',
section: [
{
type: 'TEXT',
value: response.code
}
]
}
: []
)
.concat({

View file

@ -323,6 +323,27 @@ describe('IMAP Protocol integration tests', function() {
);
});
it('should list all mailboxes using XLIST', function(done) {
let cmds = ['T1 LOGIN testuser pass', 'T2 XLIST "" "*"', 'T3 LOGOUT'];
testClient(
{
commands: cmds,
secure: true,
port
},
function(resp) {
resp = resp.toString();
expect(resp.match(/^\* XLIST /gm).length).to.equal(6);
expect(resp.indexOf('\r\n* XLIST (\\HasNoChildren \\Inbox) "/" "Inbox"\r\n') >= 0).to.be.true;
expect(resp.indexOf('\r\n* XLIST (\\Noselect \\HasChildren) "/" "[Gmail]"\r\n') >= 0).to.be.true;
expect(resp.indexOf('\r\n* XLIST (\\HasNoChildren \\Sent) "/" "[Gmail]/Sent Mail"\r\n') >= 0).to.be.true;
expect(/^T2 OK/m.test(resp)).to.be.true;
done();
}
);
});
it('should list first level mailboxes', function(done) {
let cmds = ['T1 LOGIN testuser pass', 'T2 LIST "" "%"', 'T3 LOGOUT'];

View file

@ -1,6 +1,6 @@
{
"name": "wildduck",
"version": "1.2.1",
"version": "1.2.2",
"description": "IMAP/POP3 server built with Node.js and MongoDB",
"main": "server.js",
"scripts": {
@ -9,7 +9,10 @@
"apidoc": "apidoc -i lib/api/ -o docs/",
"show": "NODE_CONFIG_ONLY=true node server.js"
},
"keywords": ["imap", "mail server"],
"keywords": [
"imap",
"mail server"
],
"author": "Andris Reinman",
"license": "EUPL-1.1+",
"devDependencies": {