Skip to content

Commit

Permalink
fix(exchange): handle special error response from exchange
Browse files Browse the repository at this point in the history
  • Loading branch information
andris9 committed Mar 6, 2024
1 parent b598358 commit 3ed4198
Show file tree
Hide file tree
Showing 4 changed files with 184 additions and 52 deletions.
46 changes: 27 additions & 19 deletions lib/handler/imap-parser.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,29 +24,37 @@ module.exports = async (command, options) => {
const parser = new ParserInstance(command, options);
const response = {};

response.tag = await parser.getTag();
await parser.getSpace();
response.command = await parser.getCommand();
try {
response.tag = await parser.getTag();

if (nullBytesRemoved) {
response.nullBytesRemoved = nullBytesRemoved;
}

if (['UID', 'AUTHENTICATE'].indexOf((response.command || '').toUpperCase()) >= 0) {
await parser.getSpace();
response.command += ' ' + (await parser.getElement(imapFormalSyntax.command()));
}
response.command = await parser.getCommand();

if (parser.remainder.trim().length) {
await parser.getSpace();
response.attributes = await parser.getAttributes();
}
if (nullBytesRemoved) {
response.nullBytesRemoved = nullBytesRemoved;
}

if (parser.humanReadable) {
response.attributes = (response.attributes || []).concat({
type: 'TEXT',
value: parser.humanReadable
});
if (['UID', 'AUTHENTICATE'].indexOf((response.command || '').toUpperCase()) >= 0) {
await parser.getSpace();
response.command += ' ' + (await parser.getElement(imapFormalSyntax.command()));
}

if (parser.remainder.trim().length) {
await parser.getSpace();
response.attributes = await parser.getAttributes();
}

if (parser.humanReadable) {
response.attributes = (response.attributes || []).concat({
type: 'TEXT',
value: parser.humanReadable
});
}
} catch (err) {
if (err.code === 'ParserErrorExchange' && err.parserContext && err.parserContext.value) {
return err.parserContext.value;
}
throw err;
}

return response;
Expand Down
52 changes: 45 additions & 7 deletions lib/handler/parser-instance.js
Original file line number Diff line number Diff line change
Expand Up @@ -73,16 +73,42 @@ class ParserInstance {
let match, element, errPos;

if (this.remainder.match(/^\s/)) {
throw new Error(`Unexpected whitespace at position ${this.pos} [E1]`);
let error = new Error(`Unexpected whitespace at position ${this.pos} [E1]`);
error.code = 'ParserError1';
error.parserContext = { input: this.input, pos: this.pos };
throw error;
}

if ((match = this.remainder.match(/^\s*[^\s]+(?=\s|$)/))) {
element = match[0];
if ((errPos = imapFormalSyntax.verify(element, syntax)) >= 0) {
throw new Error(`Unexpected char at position ${this.pos + errPos} [E2: ${JSON.stringify(element.charAt(errPos))}]`);
if (this.tag === 'Server' && element === 'Unavailable.') {
// Exchange error
let error = new Error(`Server returned an error: ${this.input}`);
error.code = 'ParserErrorExchange';
error.parserContext = {
input: this.input,
element,
pos: this.pos,
value: {
tag: '*',
command: 'BAD',
attributes: [{ type: 'TEXT', value: this.input }]
}
};
throw error;
}

let error = new Error(`Unexpected char at position ${this.pos + errPos} [E2: ${JSON.stringify(element.charAt(errPos))}]`);
error.code = 'ParserError2';
error.parserContext = { input: this.input, element, pos: this.pos };
throw error;
}
} else {
throw new Error(`Unexpected end of input at position ${this.pos} [E3]`);
let error = new Error(`Unexpected end of input at position ${this.pos} [E3]`);
error.code = 'ParserError3';
error.parserContext = { input: this.input, pos: this.pos };
throw error;
}

this.pos += match[0].length;
Expand All @@ -93,11 +119,17 @@ class ParserInstance {

async getSpace() {
if (!this.remainder.length) {
throw new Error(`Unexpected end of input at position ${this.pos} [E4]`);
let error = new Error(`Unexpected end of input at position ${this.pos} [E4]`);
error.code = 'ParserError4';
error.parserContext = { input: this.input, pos: this.pos };
throw error;
}

if (imapFormalSyntax.verify(this.remainder.charAt(0), imapFormalSyntax.SP()) >= 0) {
throw new Error(`Unexpected char at position ${this.pos} [E5: ${JSON.stringify(this.remainder.charAt(0))}]`);
let error = new Error(`Unexpected char at position ${this.pos} [E5: ${JSON.stringify(this.remainder.charAt(0))}]`);
error.code = 'ParserError5';
error.parserContext = { input: this.input, element: this.remainder, pos: this.pos };
throw error;
}

this.pos++;
Expand All @@ -106,11 +138,17 @@ class ParserInstance {

async getAttributes() {
if (!this.remainder.length) {
throw new Error(`Unexpected end of input at position ${this.pos} [E6]`);
let error = new Error(`Unexpected end of input at position ${this.pos} [E6]`);
error.code = 'ParserError6';
error.parserContext = { input: this.input, pos: this.pos };
throw error;
}

if (this.remainder.match(/^\s/)) {
throw new Error(`Unexpected whitespace at position ${this.pos} [E7]`);
let error = new Error(`Unexpected whitespace at position ${this.pos} [E7]`);
error.code = 'ParserError7';
error.parserContext = { input: this.input, element: this.remainder, pos: this.pos };
throw error;
}

const tokenParser = new TokenParser(this, this.pos, this.remainder, this.options);
Expand Down
Loading

0 comments on commit 3ed4198

Please sign in to comment.