diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..84fae5498 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +.idea +.vscode +node_modules diff --git a/lib/Connection.js b/lib/Connection.js index 619862ff4..46ce06af1 100644 --- a/lib/Connection.js +++ b/lib/Connection.js @@ -1448,7 +1448,7 @@ Connection.prototype._resUntagged = function(info) { if (toget[i] === 'X-GM-LABELS') { var labels = info.text[keys[j]]; for (var k = 0, lenk = labels.length; k < lenk; ++k) - labels[k] = (''+labels[k]).replace(RE_ESCAPE, '\\'); + labels[k] = utf7.decode((''+labels[k]).replace(RE_ESCAPE, '\\')); } key = FETCH_ATTR_MAP[toget[i]]; if (!key) diff --git a/lib/Parser.js b/lib/Parser.js index 16297d366..44740ea76 100644 --- a/lib/Parser.js +++ b/lib/Parser.js @@ -428,7 +428,12 @@ function parseFetch(text, literals, seqno) { var list = parseExpr(text, literals)[0], attrs = {}, m, body; // list is [KEY1, VAL1, KEY2, VAL2, .... KEYn, VALn] for (var i = 0, len = list.length, key, val; i < len; i += 2) { - key = list[i].toLowerCase(); + // Coerce the key token to a string before lowercasing. Some servers send + // integer-shaped atoms at key positions in malformed FETCH responses; + // convStr returns a JS number for those, and Number has no .toLowerCase. + // Coercing here keeps value-position numeric atoms (RFC822.SIZE, MODSEQ, + // etc.) untouched. + key = String(list[i]).toLowerCase(); val = list[i + 1]; if (key === 'envelope') val = parseFetchEnvelope(val); diff --git a/package.json b/package.json index 3f1445855..98368648c 100644 --- a/package.json +++ b/package.json @@ -1,5 +1,5 @@ -{ "name": "imap", - "version": "0.8.19", +{ "name": "@integromat/imap", + "version": "0.8.22", "author": "Brian White ", "description": "An IMAP module for node.js that makes communicating with IMAP servers easy", "main": "./lib/Connection", @@ -13,5 +13,5 @@ "engines": { "node": ">=0.8.0" }, "keywords": [ "imap", "mail", "email", "reader", "client" ], "licenses": [ { "type": "MIT", "url": "http://github.com/mscdex/node-imap/raw/master/LICENSE" } ], - "repository": { "type": "git", "url": "http://github.com/mscdex/node-imap.git" } + "repository": { "type": "git", "url": "https://github.com/integromat/node-imap.git" } } diff --git a/test/test-parser.js b/test/test-parser.js index 39d1723d1..01236a749 100644 --- a/test/test-parser.js +++ b/test/test-parser.js @@ -310,6 +310,15 @@ var CR = '\r', LF = '\n', CRLF = CR + LF; ], what: 'Untagged FETCH with non-body literal' }, + { source: ['* 1 FETCH (12345 NIL)', CRLF], + expected: [ { type: 'fetch', + num: 1, + textCode: undefined, + text: { '12345': null } + } + ], + what: 'Untagged FETCH with integer-shaped key token (regression: no TypeError on .toLowerCase)' + }, { source: ['* 12 FETCH (INTERNALDATE {2', '6}' + CRLF + '17-Jul-1996 02:44:25 -0700)' + CRLF], expected: [ { type: 'fetch',