Comparing version 1.0.154 to 1.0.155
# Changelog | ||
## [1.0.155](https://github.com/postalsys/imapflow/compare/v1.0.154...v1.0.155) (2024-03-06) | ||
### Bug Fixes | ||
* **exchange:** handle special error response from exchange ([3ed4198](https://github.com/postalsys/imapflow/commit/3ed4198c1b5504ab0b46926fec179c682988b2e3)) | ||
## [1.0.154](https://github.com/postalsys/imapflow/compare/v1.0.153...v1.0.154) (2024-03-05) | ||
@@ -4,0 +11,0 @@ |
@@ -27,25 +27,33 @@ 'use strict'; | ||
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; | ||
} | ||
@@ -52,0 +60,0 @@ |
@@ -76,3 +76,6 @@ /* eslint new-cap: 0 */ | ||
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; | ||
} | ||
@@ -83,6 +86,29 @@ | ||
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; | ||
} | ||
@@ -98,7 +124,13 @@ | ||
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; | ||
} | ||
@@ -112,7 +144,13 @@ | ||
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; | ||
} | ||
@@ -119,0 +157,0 @@ |
@@ -39,3 +39,6 @@ /* eslint new-cap: 0 */ | ||
if (!node.isClosed) { | ||
throw new Error(`Unexpected end of input at position ${this.pos + this.str.length - 1} [E6]`); | ||
let error = new Error(`Unexpected end of input at position ${this.pos + this.str.length - 1} [E9]`); | ||
error.code = 'ParserError9'; | ||
error.parserContext = { input: this.str, pos: this.pos + this.str.length - 1 }; | ||
throw error; | ||
} | ||
@@ -153,3 +156,6 @@ | ||
if (this.currentNode.type !== 'LIST') { | ||
throw new Error(`Unexpected list terminator ) at position ${this.pos + i} [E7]`); | ||
let error = new Error(`Unexpected list terminator ) at position ${this.pos + i} [E10]`); | ||
error.code = 'ParserError10'; | ||
error.parserContext = { input: this.str, pos: this.pos + i, chr }; | ||
throw error; | ||
} | ||
@@ -167,3 +173,6 @@ | ||
if (this.currentNode.type !== 'SECTION') { | ||
throw new Error(`Unexpected section terminator ] at position ${this.pos + i} [E8]`); | ||
let error = new Error(`Unexpected section terminator ] at position ${this.pos + i} [E11]`); | ||
error.code = 'ParserError11'; | ||
error.parserContext = { input: this.str, pos: this.pos + i, chr }; | ||
throw error; | ||
} | ||
@@ -205,3 +214,6 @@ this.currentNode.isClosed = true; | ||
throw new Error(`Unexpected literal8 marker at position ${this.pos + i} [E9]`); | ||
let error = new Error(`Unexpected literal8 marker at position ${this.pos + i} [E12]`); | ||
error.code = 'ParserError12'; | ||
error.parserContext = { input: this.str, pos: this.pos + i, chr }; | ||
throw error; | ||
} | ||
@@ -289,3 +301,6 @@ this.expectedLiteralType = 'literal8'; | ||
if (imapFormalSyntax['ATOM-CHAR']().indexOf(chr) < 0 && chr !== '\\' && chr !== '%' && chr.charCodeAt(0) < 0x80) { | ||
throw new Error(`Unexpected char at position ${this.pos + i} [E10: ${JSON.stringify(chr)}]`); | ||
let error = new Error(`Unexpected char at position ${this.pos + i} [E13: ${JSON.stringify(chr)}]`); | ||
error.code = 'ParserError13'; | ||
error.parserContext = { input: this.str, pos: this.pos + i, chr }; | ||
throw error; | ||
} | ||
@@ -337,3 +352,6 @@ | ||
if (['BODY', 'BODY.PEEK', 'BINARY', 'BINARY.PEEK'].indexOf(this.currentNode.value.toUpperCase()) < 0) { | ||
throw new Error(`Unexpected section start char [ at position ${this.pos} [E11]`); | ||
let error = new Error(`Unexpected section start char [ at position ${this.pos + i} [E14]`); | ||
error.code = 'ParserError14'; | ||
error.parserContext = { input: this.str, pos: this.pos + i, chr }; | ||
throw error; | ||
} | ||
@@ -349,3 +367,6 @@ this.currentNode.endPos = this.pos + i; | ||
if (chr === '<') { | ||
throw new Error(`Unexpected start of partial at position ${this.pos} [E12]`); | ||
let error = new Error(`Unexpected start of partial at position ${this.pos + i} [E15]`); | ||
error.code = 'ParserError15'; | ||
error.parserContext = { input: this.str, pos: this.pos + i, chr }; | ||
throw error; | ||
} | ||
@@ -361,5 +382,11 @@ | ||
) { | ||
throw new Error(`Unexpected char at position ${this.pos + i} [E13: ${JSON.stringify(chr)}]`); | ||
let error = new Error(`Unexpected char at position ${this.pos + i} [E16: ${JSON.stringify(chr)}]`); | ||
error.code = 'ParserError16'; | ||
error.parserContext = { input: this.str, pos: this.pos + i, chr }; | ||
throw error; | ||
} else if (this.currentNode.value === '\\*') { | ||
throw new Error(`Unexpected char at position ${this.pos + i} [E14: ${JSON.stringify(chr)}]`); | ||
let error = new Error(`Unexpected char at position ${this.pos + i} [E17: ${JSON.stringify(chr)}]`); | ||
error.code = 'ParserError17'; | ||
error.parserContext = { input: this.str, pos: this.pos + i, chr }; | ||
throw error; | ||
} | ||
@@ -386,3 +413,6 @@ | ||
if (i >= len) { | ||
throw new Error(`Unexpected end of input at position ${this.pos + i} [E15]`); | ||
let error = new Error(`Unexpected end of input at position ${this.pos + i} [E18]`); | ||
error.code = 'ParserError18'; | ||
error.parserContext = { input: this.str, pos: this.pos + i }; | ||
throw error; | ||
} | ||
@@ -398,3 +428,6 @@ chr = this.str.charAt(i); | ||
if (this.currentNode.value.substr(-1) === '.') { | ||
throw new Error(`Unexpected end of partial at position ${this.pos} [E16]`); | ||
let error = new Error(`Unexpected end of partial at position ${this.pos + 1} [E19]`); | ||
error.code = 'ParserError19'; | ||
error.parserContext = { input: this.str, pos: this.pos + i, chr }; | ||
throw error; | ||
} | ||
@@ -410,11 +443,20 @@ this.currentNode.endPos = this.pos + i; | ||
if (chr === '.' && (!this.currentNode.value.length || this.currentNode.value.match(/\./))) { | ||
throw new Error(`Unexpected partial separator . at position ${this.pos} [E17]`); | ||
let error = new Error(`Unexpected partial separator . at position ${this.pos + 1} [E20]`); | ||
error.code = 'ParserError20'; | ||
error.parserContext = { input: this.str, pos: this.pos + i, chr }; | ||
throw error; | ||
} | ||
if (imapFormalSyntax.DIGIT().indexOf(chr) < 0 && chr !== '.') { | ||
throw new Error(`Unexpected char at position ${this.pos + i} [E18: ${JSON.stringify(chr)}]`); | ||
let error = new Error(`Unexpected char at position ${this.pos + i} [E21: ${JSON.stringify(chr)}]`); | ||
error.code = 'ParserError21'; | ||
error.parserContext = { input: this.str, pos: this.pos + i, chr }; | ||
throw error; | ||
} | ||
if (this.currentNode.value.match(/^0$|\.0$/) && chr !== '.') { | ||
throw new Error(`Invalid partial at position ${this.pos + i} [E19: ${JSON.stringify(chr)}]`); | ||
let error = new Error(`Invalid partial at position ${this.pos + i} [E22: ${JSON.stringify(chr)}]`); | ||
error.code = 'ParserError22'; | ||
error.parserContext = { input: this.str, pos: this.pos + i, chr }; | ||
throw error; | ||
} | ||
@@ -458,3 +500,6 @@ | ||
if (!('literalLength' in this.currentNode)) { | ||
throw new Error(`Unexpected literal prefix end char } at position ${this.pos + i} [E20]`); | ||
let error = new Error(`Unexpected literal prefix end char } at position ${this.pos + i} [E23]`); | ||
error.code = 'ParserError23'; | ||
error.parserContext = { input: this.str, pos: this.pos + i, chr }; | ||
throw error; | ||
} | ||
@@ -466,3 +511,6 @@ if (this.str.charAt(i + 1) === '\n') { | ||
} else { | ||
throw new Error(`Unexpected char at position ${this.pos + i} [E21: ${JSON.stringify(chr)}]`); | ||
let error = new Error(`Unexpected char at position ${this.pos + i} [E24: ${JSON.stringify(chr)}]`); | ||
error.code = 'ParserError24'; | ||
error.parserContext = { input: this.str, pos: this.pos + i, chr }; | ||
throw error; | ||
} | ||
@@ -508,6 +556,12 @@ | ||
if (imapFormalSyntax.DIGIT().indexOf(chr) < 0) { | ||
throw new Error(`Unexpected char at position ${this.pos + i} [E22: ${JSON.stringify(chr)}]`); | ||
let error = new Error(`Unexpected char at position ${this.pos + i} [E25: ${JSON.stringify(chr)}]`); | ||
error.code = 'ParserError25'; | ||
error.parserContext = { input: this.str, pos: this.pos + i, chr }; | ||
throw error; | ||
} | ||
if (this.currentNode.literalLength === '0') { | ||
throw new Error(`Invalid literal at position ${this.pos + i} [E23]`); | ||
let error = new Error(`Invalid literal at position ${this.pos + i} [E26]`); | ||
error.code = 'ParserError26'; | ||
error.parserContext = { input: this.str, pos: this.pos + i, chr }; | ||
throw error; | ||
} | ||
@@ -521,7 +575,13 @@ this.currentNode.literalLength = (this.currentNode.literalLength || '') + chr; | ||
if (!this.currentNode.value.substr(-1).match(/\d/) && this.currentNode.value.substr(-1) !== '*') { | ||
throw new Error(`Unexpected whitespace at position ${this.pos + i} [E24]`); | ||
let error = new Error(`Unexpected whitespace at position ${this.pos + i} [E27]`); | ||
error.code = 'ParserError27'; | ||
error.parserContext = { input: this.str, pos: this.pos + i, chr }; | ||
throw error; | ||
} | ||
if (this.currentNode.value !== '*' && this.currentNode.value.substr(-1) === '*' && this.currentNode.value.substr(-2, 1) !== ':') { | ||
throw new Error(`Unexpected whitespace at position ${this.pos + i} [E25]`); | ||
let error = new Error(`Unexpected whitespace at position ${this.pos + i} [E28]`); | ||
error.code = 'ParserError28'; | ||
error.parserContext = { input: this.str, pos: this.pos + i, chr }; | ||
throw error; | ||
} | ||
@@ -549,21 +609,39 @@ | ||
if (!this.currentNode.value.substr(-1).match(/\d/) && this.currentNode.value.substr(-1) !== '*') { | ||
throw new Error(`Unexpected range separator : at position ${this.pos + i} [E26]`); | ||
let error = new Error(`Unexpected range separator : at position ${this.pos + i} [E29]`); | ||
error.code = 'ParserError29'; | ||
error.parserContext = { input: this.str, pos: this.pos + i, chr }; | ||
throw error; | ||
} | ||
} else if (chr === '*') { | ||
if ([',', ':'].indexOf(this.currentNode.value.substr(-1)) < 0) { | ||
throw new Error(`Unexpected range wildcard at position ${this.pos + i} [E27]`); | ||
let error = new Error(`Unexpected range wildcard at position ${this.pos + i} [E30]`); | ||
error.code = 'ParserError30'; | ||
error.parserContext = { input: this.str, pos: this.pos + i, chr }; | ||
throw error; | ||
} | ||
} else if (chr === ',') { | ||
if (!this.currentNode.value.substr(-1).match(/\d/) && this.currentNode.value.substr(-1) !== '*') { | ||
throw new Error(`Unexpected sequence separator , at position ${this.pos + i} [E28]`); | ||
let error = new Error(`Unexpected sequence separator , at position ${this.pos + i} [E31]`); | ||
error.code = 'ParserError31'; | ||
error.parserContext = { input: this.str, pos: this.pos + i, chr }; | ||
throw error; | ||
} | ||
if (this.currentNode.value.substr(-1) === '*' && this.currentNode.value.substr(-2, 1) !== ':') { | ||
throw new Error(`Unexpected sequence separator , at position ${this.pos + i} [E29]`); | ||
let error = new Error(`Unexpected sequence separator , at position ${this.pos + i} [E32]`); | ||
error.code = 'ParserError32'; | ||
error.parserContext = { input: this.str, pos: this.pos + i, chr }; | ||
throw error; | ||
} | ||
} else if (!chr.match(/\d/)) { | ||
throw new Error(`Unexpected char at position ${this.pos + i} [E30: ${JSON.stringify(chr)}]`); | ||
let error = new Error(`Unexpected char at position ${this.pos + i} [E33: ${JSON.stringify(chr)}]`); | ||
error.code = 'ParserError33'; | ||
error.parserContext = { input: this.str, pos: this.pos + i, chr }; | ||
throw error; | ||
} | ||
if (chr.match(/\d/) && this.currentNode.value.substr(-1) === '*') { | ||
throw new Error(`Unexpected number at position ${this.pos + i} [E31: ${JSON.stringify(chr)}]`); | ||
let error = new Error(`Unexpected number at position ${this.pos + i} [E34: ${JSON.stringify(chr)}]`); | ||
error.code = 'ParserError34'; | ||
error.parserContext = { input: this.str, pos: this.pos + i, chr }; | ||
throw error; | ||
} | ||
@@ -570,0 +648,0 @@ |
{ | ||
"name": "imapflow", | ||
"version": "1.0.154", | ||
"version": "1.0.155", | ||
"description": "IMAP Client for Node", | ||
@@ -5,0 +5,0 @@ "main": "./lib/imap-flow.js", |
@@ -981,2 +981,10 @@ /*eslint no-unused-expressions: 0, prefer-arrow-callback: 0 */ | ||
module.exports['IMAP Parser, no tag or response (Exchange)'] = test => | ||
asyncWrapper(test, async test => { | ||
let parsed = await parser('Server Unavailable. 15'); | ||
console.log(parsed); | ||
test.equal(parsed.command, 'BAD'); | ||
test.deepEqual(parsed.attributes, [{ type: 'TEXT', value: 'Server Unavailable. 15' }]); | ||
}); | ||
module.exports['IMAP Parser, BAD with throttling'] = test => | ||
@@ -983,0 +991,0 @@ asyncWrapper(test, async test => { |
582187
12710