@n8n/imap 0.6.0 → 0.8.19

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. package/LICENSE +19 -0
  2. package/README.md +754 -0
  3. package/deps/encoding/encoding-indexes.js +73 -0
  4. package/deps/encoding/encoding.js +2340 -0
  5. package/deps/test/utf7-imap.js +48 -0
  6. package/deps/test/utf7-rfc2152.js +78 -0
  7. package/deps/utf7.js +104 -0
  8. package/index.d.ts +396 -0
  9. package/lib/Connection.js +2131 -0
  10. package/lib/Parser.js +1026 -0
  11. package/package.json +18 -40
  12. package/test/test-connection-fetch-dup.js +92 -0
  13. package/test/test-connection-fetch-frag.js +92 -0
  14. package/test/test-connection-fetch-spillover.js +176 -0
  15. package/test/test-connection-fetch-stringbody.js +104 -0
  16. package/test/test-connection-idle-normal.js +144 -0
  17. package/test/test-connection-idle-order.js +138 -0
  18. package/test/test-parse-bodystructure.js +83 -0
  19. package/test/test-parse-envelope-addrs.js +117 -0
  20. package/test/test-parse-expr.js +92 -0
  21. package/test/test-parse-header.js +109 -0
  22. package/test/test-parser.js +543 -0
  23. package/test/test.js +4 -0
  24. package/LICENSE.md +0 -86
  25. package/LICENSE_EE.md +0 -27
  26. package/dist/ImapSimple.d.ts +0 -16
  27. package/dist/ImapSimple.js +0 -121
  28. package/dist/ImapSimple.js.map +0 -1
  29. package/dist/PartData.d.ts +0 -24
  30. package/dist/PartData.js +0 -99
  31. package/dist/PartData.js.map +0 -1
  32. package/dist/build.tsbuildinfo +0 -1
  33. package/dist/errors.d.ts +0 -12
  34. package/dist/errors.js +0 -30
  35. package/dist/errors.js.map +0 -1
  36. package/dist/helpers/getMessage.d.ts +0 -3
  37. package/dist/helpers/getMessage.js +0 -37
  38. package/dist/helpers/getMessage.js.map +0 -1
  39. package/dist/index.d.ts +0 -7
  40. package/dist/index.js +0 -86
  41. package/dist/index.js.map +0 -1
  42. package/dist/types.d.ts +0 -30
  43. package/dist/types.js +0 -3
  44. package/dist/types.js.map +0 -1
@@ -0,0 +1,138 @@
1
+ var assert = require('assert'),
2
+ net = require('net'),
3
+ Imap = require('../lib/Connection');
4
+
5
+ var result, body = '', bodyInfo;
6
+
7
+ var CRLF = '\r\n';
8
+
9
+ var RESPONSES = [
10
+ ['* CAPABILITY IMAP4rev1 UNSELECT IDLE NAMESPACE QUOTA CHILDREN',
11
+ 'A0 OK Thats all she wrote!',
12
+ ''
13
+ ].join(CRLF),
14
+ ['* CAPABILITY IMAP4rev1 UNSELECT IDLE NAMESPACE QUOTA CHILDREN UIDPLUS MOVE',
15
+ 'A1 OK authenticated (Success)',
16
+ ''
17
+ ].join(CRLF),
18
+ ['* NAMESPACE (("" "/")) NIL NIL',
19
+ 'A2 OK Success',
20
+ ''
21
+ ].join(CRLF),
22
+ ['* LIST (\\Noselect) "/" "/"',
23
+ 'A3 OK Success',
24
+ ''
25
+ ].join(CRLF),
26
+ ['* FLAGS (\\Answered \\Flagged \\Draft \\Deleted \\Seen)',
27
+ '* OK [PERMANENTFLAGS ()] Flags permitted.',
28
+ '* OK [UIDVALIDITY 2] UIDs valid.',
29
+ '* 685 EXISTS',
30
+ '* 0 RECENT',
31
+ '* OK [UIDNEXT 4422] Predicted next UID.',
32
+ 'A4 OK [READ-ONLY] INBOX selected. (Success)',
33
+ ''
34
+ ].join(CRLF),
35
+ ['* 1 FETCH (UID 1)',
36
+ '* 1 FETCH (INTERNALDATE "05-Sep-2004 00:38:03 +0000" UID 1000)',
37
+ '* 1 FETCH (BODY[TEXT] "IMAP is terrible")',
38
+ '* 1 FETCH (FLAGS (\\Seen))',
39
+ 'A5 OK Success',
40
+ ''
41
+ ].join(CRLF),
42
+ ['* STATUS test (MESSAGES 231 RECENT 0 UNSEEN 0 UIDVALIDITY 123 UIDNEXT 442)',
43
+ 'A6 OK STATUS completed',
44
+ ''
45
+ ].join(CRLF),
46
+ ['* BYE LOGOUT Requested',
47
+ 'A7 OK good day (Success)',
48
+ ''
49
+ ].join(CRLF)
50
+ ];
51
+ var EXPECTED = [
52
+ 'A0 CAPABILITY',
53
+ 'A1 LOGIN "foo" "bar"',
54
+ 'A2 NAMESPACE',
55
+ 'A3 LIST "" ""',
56
+ 'A4 EXAMINE "INBOX"',
57
+ 'A5 FETCH 1 (UID FLAGS INTERNALDATE BODY.PEEK[TEXT])',
58
+ 'IDLE IDLE',
59
+ 'DONE',
60
+ 'A6 STATUS "test" (MESSAGES RECENT UNSEEN UIDVALIDITY UIDNEXT)',
61
+ 'A7 LOGOUT'
62
+ ];
63
+
64
+ var exp = -1,
65
+ res = -1,
66
+ sentCont = false;
67
+
68
+ var srv = net.createServer(function(sock) {
69
+ sock.write('* OK asdf\r\n');
70
+ var buf = '', lines;
71
+ sock.on('data', function(data) {
72
+ buf += data.toString('utf8');
73
+ if (buf.indexOf(CRLF) > -1) {
74
+ lines = buf.split(CRLF);
75
+ buf = lines.pop();
76
+ lines.forEach(function(l) {
77
+ assert(l === EXPECTED[++exp], 'Unexpected client request: ' + l);
78
+ if (l === 'DONE') {
79
+ assert(sentCont, 'DONE seen before continuation sent');
80
+ sock.write('IDLE ok\r\n');
81
+ } else if (l === 'IDLE IDLE') {
82
+ setTimeout(function() {
83
+ sentCont = true;
84
+ sock.write('+ idling\r\n');
85
+ }, 100);
86
+ } else {
87
+ assert(RESPONSES[++res], 'No response for client request: ' + l);
88
+ sock.write(RESPONSES[res]);
89
+ }
90
+ });
91
+ }
92
+ });
93
+ });
94
+ srv.listen(0, '127.0.0.1', function() {
95
+ var port = srv.address().port;
96
+ var imap = new Imap({
97
+ user: 'foo',
98
+ password: 'bar',
99
+ host: '127.0.0.1',
100
+ port: port,
101
+ keepalive: true
102
+ });
103
+ imap.on('ready', function() {
104
+ srv.close();
105
+ imap.openBox('INBOX', true, function() {
106
+ var f = imap.seq.fetch(1, { bodies: ['TEXT'] });
107
+ f.on('message', function(m) {
108
+ m.on('body', function(stream, info) {
109
+ bodyInfo = info;
110
+ stream.on('data', function(chunk) { body += chunk.toString('utf8'); });
111
+ });
112
+ m.on('attributes', function(attrs) {
113
+ result = attrs;
114
+ });
115
+ });
116
+ f.on('end', function() {
117
+ imap.status('test', function(err, status) {
118
+ imap.end();
119
+ });
120
+ });
121
+ });
122
+ });
123
+ imap.connect();
124
+ });
125
+
126
+ process.once('exit', function() {
127
+ assert.deepEqual(result, {
128
+ uid: 1,
129
+ date: new Date('05-Sep-2004 00:38:03 +0000'),
130
+ flags: [ '\\Seen' ]
131
+ });
132
+ assert.equal(body, 'IMAP is terrible');
133
+ assert.deepEqual(bodyInfo, {
134
+ seqno: 1,
135
+ which: 'TEXT',
136
+ size: 16
137
+ });
138
+ });
@@ -0,0 +1,83 @@
1
+ var parseBodyStructure = require('../lib/Parser').parseBodyStructure;
2
+
3
+ var assert = require('assert'),
4
+ inspect = require('util').inspect;
5
+
6
+ [
7
+ { source: '("TEXT" "PLAIN" ("CHARSET" "US-ASCII") NIL NIL "7BIT" 1152 23)'
8
+ + '("TEXT" "PLAIN" ("CHARSET" "US-ASCII" "NAME" "cc.diff")'
9
+ + ' "<960723163407.20117h@cac.washington.edu>" "Compiler diff"'
10
+ + ' "BASE64" 4554 73)'
11
+ + '"MIXED"',
12
+ expected: [ { type: 'mixed' },
13
+ [ { partID: '1',
14
+ type: 'text',
15
+ subtype: 'plain',
16
+ params: { charset: 'US-ASCII' },
17
+ id: null,
18
+ description: null,
19
+ encoding: '7BIT',
20
+ size: 1152,
21
+ lines: 23
22
+ }
23
+ ],
24
+ [ { partID: '2',
25
+ type: 'text',
26
+ subtype: 'plain',
27
+ params: { charset: 'US-ASCII', name: 'cc.diff' },
28
+ id: '<960723163407.20117h@cac.washington.edu>',
29
+ description: 'Compiler diff',
30
+ encoding: 'BASE64',
31
+ size: 4554,
32
+ lines: 73
33
+ }
34
+ ]
35
+ ],
36
+ what: 'RFC3501 example #1'
37
+ },
38
+ { source: 'NIL NIL ("CHARSET" "GB2312") NIL NIL NIL 176 NIL NIL NIL',
39
+ expected: [ { type: null,
40
+ params: null,
41
+ disposition: null,
42
+ language: [ 'CHARSET', 'GB2312' ],
43
+ location: null,
44
+ extensions: null
45
+ }
46
+ ],
47
+ what: 'Issue 477'
48
+ },
49
+ { source: '"TEXT" "PLAIN" ("CHARSET" "US-ASCII") NIL NIL "7BIT" 3028 92',
50
+ expected: [ { partID: '1',
51
+ type: 'text',
52
+ subtype: 'plain',
53
+ params: { charset: 'US-ASCII' },
54
+ id: null,
55
+ description: null,
56
+ encoding: '7BIT',
57
+ size: 3028,
58
+ lines: 92
59
+ }
60
+ ],
61
+ what: 'RFC3501 example #2'
62
+ },
63
+ ].forEach(function(v) {
64
+ var result;
65
+ try {
66
+ result = parseBodyStructure(v.source);
67
+ } catch (e) {
68
+ console.log(makeMsg(v.what, 'JS Exception: ' + e.stack));
69
+ return;
70
+ }
71
+ assert.deepEqual(result,
72
+ v.expected,
73
+ makeMsg(v.what,
74
+ 'Result mismatch:'
75
+ + '\nParsed: ' + inspect(result, false, 10)
76
+ + '\nExpected: ' + inspect(v.expected, false, 10)
77
+ )
78
+ );
79
+ });
80
+
81
+ function makeMsg(what, msg) {
82
+ return '[' + what + ']: ' + msg;
83
+ }
@@ -0,0 +1,117 @@
1
+ var parseExpr = require('../lib/Parser').parseExpr,
2
+ parseEnvelopeAddresses = require('../lib/Parser').parseEnvelopeAddresses;
3
+
4
+ var assert = require('assert'),
5
+ inspect = require('util').inspect;
6
+
7
+ [
8
+ { source: '("Terry Gray" NIL "gray" "cac.washington.edu")',
9
+ expected: [ { name: 'Terry Gray',
10
+ mailbox: 'gray',
11
+ host: 'cac.washington.edu'
12
+ }
13
+ ],
14
+ what: 'RFC3501 example #1'
15
+ },
16
+ { source: '(NIL NIL "imap" "cac.washington.edu")',
17
+ expected: [ { name: null,
18
+ mailbox: 'imap',
19
+ host: 'cac.washington.edu'
20
+ }
21
+ ],
22
+ what: 'RFC3501 example #2'
23
+ },
24
+ { source: '("=?utf-8?Q?=C2=A9=C2=AEAZ=C2=A5?=" NIL "crazy" "example.org")',
25
+ expected: [ { name: '©®AZ¥',
26
+ mailbox: 'crazy',
27
+ host: 'example.org'
28
+ }
29
+ ],
30
+ what: 'Name with encoded word(s)'
31
+ },
32
+ { source: '(NIL NIL "imap" NIL)'
33
+ + '(NIL NIL NIL NIL)',
34
+ expected: [ { group: 'imap',
35
+ addresses: []
36
+ }
37
+ ],
38
+ what: 'Zero-length group'
39
+ },
40
+ { source: '(NIL NIL "imap" NIL)'
41
+ + '("Terry Gray" NIL "gray" "cac.washington.edu")'
42
+ + '(NIL NIL NIL NIL)',
43
+ expected: [ { group: 'imap',
44
+ addresses: [
45
+ { name: 'Terry Gray',
46
+ mailbox: 'gray',
47
+ host: 'cac.washington.edu'
48
+ }
49
+ ]
50
+ }
51
+ ],
52
+ what: 'One-length group'
53
+ },
54
+ { source: '(NIL NIL "imap" NIL)'
55
+ + '("Terry Gray" NIL "gray" "cac.washington.edu")'
56
+ + '(NIL NIL NIL NIL)'
57
+ + '(NIL NIL "imap" "cac.washington.edu")',
58
+ expected: [ { group: 'imap',
59
+ addresses: [
60
+ { name: 'Terry Gray',
61
+ mailbox: 'gray',
62
+ host: 'cac.washington.edu'
63
+ }
64
+ ]
65
+ },
66
+ { name: null,
67
+ mailbox: 'imap',
68
+ host: 'cac.washington.edu'
69
+ }
70
+ ],
71
+ what: 'One-length group and address'
72
+ },
73
+ { source: '(NIL NIL "imap" NIL)'
74
+ + '("Terry Gray" NIL "gray" "cac.washington.edu")',
75
+ expected: [ { group: 'imap',
76
+ addresses: [
77
+ { name: 'Terry Gray',
78
+ mailbox: 'gray',
79
+ host: 'cac.washington.edu'
80
+ }
81
+ ]
82
+ }
83
+ ],
84
+ what: 'Implicit group end'
85
+ },
86
+ { source: '("Terry Gray" NIL "gray" "cac.washington.edu")'
87
+ + '(NIL NIL NIL NIL)',
88
+ expected: [ { name: 'Terry Gray',
89
+ mailbox: 'gray',
90
+ host: 'cac.washington.edu'
91
+ }
92
+ ],
93
+ what: 'Group end without start'
94
+ },
95
+ ].forEach(function(v) {
96
+ var result;
97
+
98
+ try {
99
+ result = parseEnvelopeAddresses(parseExpr(v.source));
100
+ } catch (e) {
101
+ console.log(makeMsg(v.what, 'JS Exception: ' + e.stack));
102
+ return;
103
+ }
104
+
105
+ assert.deepEqual(result,
106
+ v.expected,
107
+ makeMsg(v.what,
108
+ 'Result mismatch:'
109
+ + '\nParsed: ' + inspect(result, false, 10)
110
+ + '\nExpected: ' + inspect(v.expected, false, 10)
111
+ )
112
+ );
113
+ });
114
+
115
+ function makeMsg(what, msg) {
116
+ return '[' + what + ']: ' + msg;
117
+ }
@@ -0,0 +1,92 @@
1
+ var parseExpr = require('../lib/Parser').parseExpr;
2
+
3
+ var assert = require('assert'),
4
+ inspect = require('util').inspect;
5
+
6
+ [
7
+ { source: '',
8
+ expected: [],
9
+ what: 'Empty value'
10
+ },
11
+ { source: '""',
12
+ expected: [''],
13
+ what: 'Empty quoted string'
14
+ },
15
+ { source: 'FLAGS NIL RFC822.SIZE 44827',
16
+ expected: ['FLAGS', null, 'RFC822.SIZE', 44827],
17
+ what: 'Simple, two key-value pairs with nil'
18
+ },
19
+ { source: 'FLAGS (\\Seen) RFC822.SIZE 44827',
20
+ expected: ['FLAGS', ['\\Seen'], 'RFC822.SIZE', 44827],
21
+ what: 'Simple, two key-value pairs with list'
22
+ },
23
+ { source: 'RFC822.SIZE 9007199254740993',
24
+ expected: ['RFC822.SIZE', '9007199254740993'],
25
+ what: 'Integer exceeding JavaScript max int size'
26
+ },
27
+ { source: 'FLAGS (\\Seen) INTERNALDATE "17-Jul-1996 02:44:25 -0700"',
28
+ expected: ['FLAGS', ['\\Seen'], 'INTERNALDATE', '17-Jul-1996 02:44:25 -0700'],
29
+ what: 'Quoted string'
30
+ },
31
+ { source: '("Foo")("Bar") ("Baz")',
32
+ expected: [['Foo'], ['Bar'], ['Baz']],
33
+ what: 'Lists with varying spacing'
34
+ },
35
+ { source: '"\\"IMAP\\" is terrible :\\\\"',
36
+ expected: ['"IMAP" is terrible :\\'],
37
+ what: 'Quoted string with escaped chars'
38
+ },
39
+ { source: '"\\\\"IMAP\\" is terrible :\\\\"',
40
+ expected: ['\\"IMAP" is terrible :\\'],
41
+ what: 'Quoted string with escaped chars #2'
42
+ },
43
+ { source: '"Who does not think \\"IMAP\\" is terrible\\\\bad?"',
44
+ expected: ['Who does not think "IMAP" is terrible\\bad?'],
45
+ what: 'Quoted string with escaped chars #3'
46
+ },
47
+ { source: '"Who does not think \\\\"IMAP\\" is terrible\\\\bad?"',
48
+ expected: ['Who does not think \\"IMAP" is terrible\\bad?'],
49
+ what: 'Quoted string with escaped chars #4'
50
+ },
51
+ { source: 'ENVELOPE ("Wed, 30 Mar 2014 02:38:23 +0100" "=?ISO-8859-1?Q?##ALLCAPS##123456## - ?= =?ISO-8859-1?Q?[ALERT][P3][ONE.TWO.FR] ?= =?ISO-8859-1?Q?Some Subject Line \\"D:\\\\\\"?=" (("Test Account (Rltvty L)" NIL "account" "test.com")) (("Test Account (Rltvty L)" NIL "account" "test.com")) ((NIL NIL "account" "test.com")) ((NIL NIL "one.two" "test.fr") (NIL NIL "two.three" "test.fr")) NIL NIL NIL "<message@test.eu>")',
52
+ expected: [
53
+ 'ENVELOPE',
54
+ [ 'Wed, 30 Mar 2014 02:38:23 +0100',
55
+ '=?ISO-8859-1?Q?##ALLCAPS##123456## - ?= =?ISO-8859-1?Q?[ALERT][P3][ONE.TWO.FR] ?= =?ISO-8859-1?Q?Some Subject Line "D:\\"?=',
56
+ [ [ 'Test Account (Rltvty L)', null, 'account', 'test.com' ] ],
57
+ [ [ 'Test Account (Rltvty L)', null, 'account', 'test.com' ] ],
58
+ [ [ null, null, 'account', 'test.com' ] ],
59
+ [ [ null, null, 'one.two', 'test.fr' ],
60
+ [ null, null, 'two.three', 'test.fr' ]
61
+ ],
62
+ null,
63
+ null,
64
+ null,
65
+ '<message@test.eu>'
66
+ ]
67
+ ],
68
+ what: 'Triple backslash in quoted string (GH Issue #345)'
69
+ },
70
+ ].forEach(function(v) {
71
+ var result;
72
+
73
+ try {
74
+ result = parseExpr(v.source);
75
+ } catch (e) {
76
+ console.log(makeMsg(v.what, 'JS Exception: ' + e.stack));
77
+ return;
78
+ }
79
+
80
+ assert.deepEqual(result,
81
+ v.expected,
82
+ makeMsg(v.what,
83
+ 'Result mismatch:'
84
+ + '\nParsed: ' + inspect(result, false, 10)
85
+ + '\nExpected: ' + inspect(v.expected, false, 10)
86
+ )
87
+ );
88
+ });
89
+
90
+ function makeMsg(what, msg) {
91
+ return '[' + what + ']: ' + msg;
92
+ }
@@ -0,0 +1,109 @@
1
+ var parseHeader = require('../lib/Parser').parseHeader;
2
+
3
+ var assert = require('assert'),
4
+ inspect = require('util').inspect;
5
+
6
+ var CRLF = '\r\n';
7
+
8
+ [
9
+ { source: ['To: Foo', CRLF,
10
+ ' Bar Baz', CRLF],
11
+ expected: { to: [ 'Foo Bar Baz' ] },
12
+ what: 'Folded header value (plain -- space)'
13
+ },
14
+ { source: ['To: Foo', CRLF,
15
+ '\tBar\tBaz', CRLF],
16
+ expected: { to: [ 'Foo\tBar\tBaz' ] },
17
+ what: 'Folded header value (plain -- tab)'
18
+ },
19
+ { source: ['Subject: =?iso-8859-1?Q?=A1Hola,_se=F1or!?=', CRLF],
20
+ expected: { subject: [ '¡Hola, señor!' ] },
21
+ what: 'MIME encoded-word in value'
22
+ },
23
+ { source: ['Subject: =?iso-8859-1*es?Q?=A1Hola,_se=F1or!?=', CRLF],
24
+ expected: { subject: [ '¡Hola, señor!' ] },
25
+ what: 'MIME encoded-word in value with language set (RFC2231)'
26
+ },
27
+ { source: ['Subject: =?iso-8859-1*?Q?=A1Hola,_se=F1or!?=', CRLF],
28
+ expected: { subject: [ '¡Hola, señor!' ] },
29
+ what: 'MIME encoded-word in value with empty language set'
30
+ },
31
+ { source: ['Subject: =?GB2312?Q?=B2=E2=CA=D4=CC=E2=C4=BF=D3=EB=D6=D0=B9=FA=D0=C5_long_subjects_are_not_OK_12?=', CRLF,
32
+ ' =?GB2312?Q?345678901234567890123456789012345678901234567890123456789012?=', CRLF,
33
+ ' =?GB2312?Q?345678901234567890?=', CRLF],
34
+ expected: { subject: [ '测试题目与中国信 long subjects are not OK 12345678901234567890123456789012345678901234567890123456789012345678901234567890' ] },
35
+ what: 'Folded header value (adjacent MIME encoded-words)'
36
+ },
37
+ { source: ['Subject: =?GB2312?Q?=B2=E2=CA=D4=CC=E2=C4=BF=D3=EB=D6=D0=B9=FA=D0=C5_long_subjects_are_not_OK_12?=', CRLF,
38
+ ' 3=?GB2312?Q?45678901234567890123456789012345678901234567890123456789012?=', CRLF,
39
+ ' 3=?GB2312?Q?45678901234567890?=', CRLF],
40
+ expected: { subject: [ '测试题目与中国信 long subjects are not OK 12 345678901234567890123456789012345678901234567890123456789012 345678901234567890' ] },
41
+ what: 'Folded header value (non-adjacent MIME encoded-words)'
42
+ },
43
+ { source: ['Subject: =?GB2312?Q?=B2=E2=CA=D4=CC=E2=C4=BF=D3=EB=D6=D0=B9=FA=D0=C5_long_subjects_are_not_OK_12?=', CRLF,
44
+ ' 3=?GB2312?Q?45678901234567890123456789012345678901234567890123456789012?=', CRLF,
45
+ ' =?GB2312?Q?345678901234567890?=', CRLF],
46
+ expected: { subject: [ '测试题目与中国信 long subjects are not OK 12 345678901234567890123456789012345678901234567890123456789012345678901234567890' ] },
47
+ what: 'Folded header value (one adjacent, one non-adjacent MIME encoded-words)'
48
+ },
49
+ { source: ['Subject: =?UTF-8?Q?=E0=B9=84=E0=B8=97=E0=B8=A2_=E0=B9=84?=', CRLF,
50
+ ' ', CRLF,
51
+ ' =?UTF-8?Q?=E0=B8=97=E0=B8=A2_=E0=B9=84=E0=B8=97?= =?UTF-8?Q?=E0=B8=A2?=', CRLF],
52
+ expected: { subject: [ 'ไทย ไทย ไทย' ] },
53
+ what: 'Folded header value (adjacent MIME encoded-words seperated by linear whitespace)'
54
+ },
55
+ { source: ['Subject: =?utf-8?Q?abcdefghij_=E0=B9=83=E0=B8=99_klmnopqr_=E0=B9=84=E0=B8=A1=E0=B9?=', CRLF,
56
+ ' =?utf-8?Q?=88=E0=B8=82=E0=B8=B6=E0=B9=89=E0=B8=99?=', CRLF],
57
+ expected: { subject: [ 'abcdefghij ใน klmnopqr ไม่ขึ้น' ] },
58
+ what: 'Folded header value (incomplete multi-byte character split)'
59
+ },
60
+ { source: ['Subject: =?utf-8?B?Rlc6IOC4quC4tOC5iOC4h+C4oeC4tQ==?=', CRLF,
61
+ ' =?utf-8?B?4LiK4Li14Lin4Li04LiV4Lir4LiZ4LmJ4Liy4LiV?=', CRLF,
62
+ ' =?utf-8?B?4Liy4LmB4Lib4Lil4LiBIOC5hiDguKPguK3=?=', CRLF,
63
+ ' =?utf-8?Q?=E0=B8=9A=E0=B9=82=E0=B8=A5=E0=B8=81?=', CRLF],
64
+ expected: { subject: [ 'FW: สิ่งมีชีวิตหน้าตาแปลก ๆ รอบโลก' ] },
65
+ what: 'Folded header value (consecutive complete base64-encoded words)'
66
+ },
67
+ { source: ['Subject: =?utf-8?B?4Lij4Li54Lib4Lig4Liy4Lie4LiX4Li14LmIIGVtYmVkIOC5g+C4meC5gOC4?=', CRLF,
68
+ ' =?utf-8?B?meC4t+C5ieC4reC5gOC4oeC4peC4peC5jOC5hOC4oeC5iOC5geC4quC4lOC4?=', CRLF,
69
+ ' =?utf-8?B?hw==?=', CRLF],
70
+ expected: { subject: [ 'รูปภาพที่ embed ในเนื้อเมลล์ไม่แสดง' ] },
71
+ what: 'Folded header value (consecutive partial base64-encoded words)'
72
+ },
73
+ { source: [' ', CRLF,
74
+ 'To: Foo', CRLF],
75
+ expected: { to: [ 'Foo' ] },
76
+ what: 'Invalid first line'
77
+ },
78
+ // header with body
79
+ { source: ['Subject: test subject', CRLF,
80
+ 'X-Another-Header: test', CRLF,
81
+ CRLF,
82
+ 'This is body: Not a header', CRLF],
83
+ expected: { subject: [ 'test subject' ], 'x-another-header': [ 'test' ] },
84
+ what: 'Header with the body'
85
+ },
86
+
87
+ ].forEach(function(v) {
88
+ var result;
89
+
90
+ try {
91
+ result = parseHeader(v.source.join(''));
92
+ } catch (e) {
93
+ console.log(makeMsg(v.what, 'JS Exception: ' + e.stack));
94
+ return;
95
+ }
96
+
97
+ assert.deepEqual(result,
98
+ v.expected,
99
+ makeMsg(v.what,
100
+ 'Result mismatch:'
101
+ + '\nParsed: ' + inspect(result, false, 10)
102
+ + '\nExpected: ' + inspect(v.expected, false, 10)
103
+ )
104
+ );
105
+ });
106
+
107
+ function makeMsg(what, msg) {
108
+ return '[' + what + ']: ' + msg;
109
+ }