UNPKG

15.8 kBJavaScriptView Raw
1var Parser = require('../lib/Parser').Parser;
2
3var assert = require('assert'),
4 crypto = require('crypto'),
5 inspect = require('util').inspect;
6
7var CR = '\r', LF = '\n', CRLF = CR + LF;
8
9[
10 { source: ['A1 OK LOGIN completed', CRLF],
11 expected: [ { type: 'ok',
12 tagnum: 1,
13 textCode: undefined,
14 text: 'LOGIN completed'
15 }
16 ],
17 what: 'Tagged OK'
18 },
19 { source: ['IDLE OK IDLE terminated', CRLF],
20 expected: [ 'IDLE OK IDLE terminated' ],
21 what: 'Unknown line'
22 },
23 { source: ['+ idling', CRLF],
24 expected: [ { textCode: undefined,
25 text: 'idling'
26 }
27 ],
28 what: 'Continuation'
29 },
30 { source: ['+ [ALERT] idling', CRLF],
31 expected: [ { textCode: 'ALERT',
32 text: 'idling'
33 }
34 ],
35 what: 'Continuation with text code'
36 },
37 { source: ['+', CRLF],
38 expected: [ { textCode: undefined,
39 text: undefined
40 }
41 ],
42 what: 'Continuation (broken -- RFC violation) sent by AOL IMAP'
43 },
44 { source: ['* NAMESPACE ',
45 '(("" "/")) ',
46 '(("~" "/")) ',
47 '(("#shared/" "/")("#public/" "/")("#ftp/" "/")("#news." "."))',
48 CRLF],
49 expected: [ { type: 'namespace',
50 num: undefined,
51 textCode: undefined,
52 text: {
53 personal: [
54 { prefix: '',
55 delimiter: '/',
56 extensions: undefined
57 }
58 ],
59 other: [
60 { prefix: '~',
61 delimiter: '/',
62 extensions: undefined
63 }
64 ],
65 shared: [
66 { prefix: '#shared/',
67 delimiter: '/',
68 extensions: undefined
69 },
70 { prefix: '#public/',
71 delimiter: '/',
72 extensions: undefined
73 },
74 { prefix: '#ftp/',
75 delimiter: '/',
76 extensions: undefined
77 },
78 { prefix: '#news.',
79 delimiter: '.',
80 extensions: undefined
81 }
82 ]
83 }
84 }
85 ],
86 what: 'Multiple namespaces'
87 },
88 { source: ['* NAMESPACE ',
89 '(("" "/" "X-PARAM" ("FLAG1" "FLAG2"))) ',
90 'NIL ',
91 'NIL',
92 CRLF],
93 expected: [ { type: 'namespace',
94 num: undefined,
95 textCode: undefined,
96 text: {
97 personal: [
98 { prefix: '',
99 delimiter: '/',
100 extensions: {
101 'X-PARAM': [ 'FLAG1', 'FLAG2' ]
102 }
103 }
104 ],
105 other: null,
106 shared: null
107 }
108 }
109 ],
110 what: 'Multiple namespaces'
111 },
112 { source: ['* FLAGS (\\Answered \\Flagged \\Deleted \\Seen \\Draft)', CRLF],
113 expected: [ { type: 'flags',
114 num: undefined,
115 textCode: undefined,
116 text: [
117 '\\Answered',
118 '\\Flagged',
119 '\\Deleted',
120 '\\Seen',
121 '\\Draft'
122 ]
123 }
124 ],
125 what: 'Flags'
126 },
127 { source: ['* SEARCH 2 3 6', CRLF],
128 expected: [ { type: 'search',
129 num: undefined,
130 textCode: undefined,
131 text: [ 2, 3, 6 ]
132 }
133 ],
134 what: 'Search'
135 },
136 { source: ['* LIST (\\Noselect) "/" ~/Mail/foo', CRLF],
137 expected: [ { type: 'list',
138 num: undefined,
139 textCode: undefined,
140 text: {
141 flags: [ '\\Noselect' ],
142 delimiter: '/',
143 name: '~/Mail/foo'
144 }
145 }
146 ],
147 what: 'List'
148 },
149 { source: ['* STATUS blurdybloop (MESSAGES 231 UIDNEXT 44292)', CRLF],
150 expected: [ { type: 'status',
151 num: undefined,
152 textCode: undefined,
153 text: {
154 name: 'blurdybloop',
155 attrs: { messages: 231, uidnext: 44292 }
156 }
157 }
158 ],
159 what: 'Status'
160 },
161 { source: ['* OK [UNSEEN 17] Message 17 is the first unseen message', CRLF],
162 expected: [ { type: 'ok',
163 num: undefined,
164 textCode: {
165 key: 'UNSEEN',
166 val: 17
167 },
168 text: 'Message 17 is the first unseen message'
169 }
170 ],
171 what: 'Untagged OK (with text code, with text)'
172 },
173 { source: ['* OK [PERMANENTFLAGS (\\Deleted \\Seen \\*)] Limited', CRLF],
174 expected: [ { type: 'ok',
175 num: undefined,
176 textCode: {
177 key: 'PERMANENTFLAGS',
178 val: [ '\\Deleted', '\\Seen', '\\*' ]
179 },
180 text: 'Limited'
181 }
182 ],
183 what: 'Untagged OK (with text code, with text)'
184 },
185 { source: ['* OK [UNSEEN 17]', CRLF],
186 expected: [ { type: 'ok',
187 num: undefined,
188 textCode: undefined,
189 text: '[UNSEEN 17]'
190 }
191 ],
192 what: 'Untagged OK (no text code, with text) (RFC violation)'
193 },
194 { source: ['* OK IMAP4rev1 Service Ready', CRLF],
195 expected: [ { type: 'ok',
196 num: undefined,
197 textCode: undefined,
198 text: 'IMAP4rev1 Service Ready'
199 }
200 ],
201 what: 'Untagged OK (no text code, with text)'
202 },
203 { source: ['* OK', CRLF], // I have seen servers that send stuff like this ..
204 expected: [ { type: 'ok',
205 num: undefined,
206 textCode: undefined,
207 text: undefined
208 }
209 ],
210 what: 'Untagged OK (no text code, no text) (RFC violation)'
211 },
212 { source: ['* 18 EXISTS', CRLF],
213 expected: [ { type: 'exists',
214 num: 18,
215 textCode: undefined,
216 text: undefined
217 }
218 ],
219 what: 'Untagged EXISTS'
220 },
221 { source: ['* 2 RECENT', CRLF],
222 expected: [ { type: 'recent',
223 num: 2,
224 textCode: undefined,
225 text: undefined
226 }
227 ],
228 what: 'Untagged RECENT'
229 },
230 { source: ['* 12 FETCH (BODY[HEADER] {342}', CRLF,
231 'Date: Wed, 17 Jul 1996 02:23:25 -0700 (PDT)', CRLF,
232 'From: Terry Gray <gray@cac.washington.edu>', CRLF,
233 'Subject: IMAP4rev1 WG mtg summary and minutes', CRLF,
234 'To: imap@cac.washington.edu', CRLF,
235 'cc: minutes@CNRI.Reston.VA.US, John Klensin <KLENSIN@MIT.EDU>', CRLF,
236 'Message-Id: <B27397-0100000@cac.washington.edu>', CRLF,
237 'MIME-Version: 1.0', CRLF,
238 'Content-Type: TEXT/PLAIN; CHARSET=US-ASCII', CRLF, CRLF,
239 ')', CRLF],
240 expected: [ { seqno: 12,
241 which: 'HEADER',
242 size: 342
243 },
244 { type: 'fetch',
245 num: 12,
246 textCode: undefined,
247 text: {}
248 }
249 ],
250 bodySHA1s: ['1f96faf50f6410f99237791f9e3b89454bf93fa7'],
251 what: 'Untagged FETCH (body)'
252 },
253 { source: ['* 12 FETCH (INTERNALDATE {26}', CRLF,
254 '17-Jul-1996 02:44:25 -0700)' + CRLF],
255 expected: [ { type: 'fetch',
256 num: 12,
257 textCode: undefined,
258 text: {
259 internaldate: new Date('17-Jul-1996 02:44:25 -0700')
260 }
261 }
262 ],
263 what: 'Untagged FETCH with non-body literal'
264 },
265 { source: ['* 12 FETCH (INTERNALDATE {2',
266 '6}' + CRLF + '17-Jul-1996 02:44:25 -0700)' + CRLF],
267 expected: [ { type: 'fetch',
268 num: 12,
269 textCode: undefined,
270 text: {
271 internaldate: new Date('17-Jul-1996 02:44:25 -0700')
272 }
273 }
274 ],
275 what: 'Untagged FETCH with non-body literal (length split)'
276 },
277 { source: ['* 12 FETCH (INTERNALDATE {26}', CRLF,
278 '17-Jul-1996 02:44:25 -0700)' + CR,
279 LF],
280 expected: [ { type: 'fetch',
281 num: 12,
282 textCode: undefined,
283 text: {
284 internaldate: new Date('17-Jul-1996 02:44:25 -0700')
285 }
286 }
287 ],
288 what: 'Untagged FETCH with non-body literal (split CRLF)'
289 },
290 { source: ['* 12 FETCH (FLAGS (\\Seen)',
291 ' INTERNALDATE "17-Jul-1996 02:44:25 -0700"',
292 ' RFC822.SIZE 4286',
293 ' ENVELOPE ("Wed, 17 Jul 1996 02:23:25 -0700 (PDT)"',
294 ' "IMAP4rev1 WG mtg summary and minutes"',
295 ' (("Terry Gray" NIL "gray" "cac.washington.edu"))',
296 ' (("Terry Gray" NIL "gray" "cac.washington.edu"))',
297 ' (("Terry Gray" NIL "gray" "cac.washington.edu"))',
298 ' ((NIL NIL "imap" "cac.washington.edu"))',
299 ' ((NIL NIL "minutes" "CNRI.Reston.VA.US")',
300 '("John Klensin" NIL "KLENSIN" "MIT.EDU")) NIL NIL',
301 ' "<B27397-0100000@cac.washington.edu>")',
302 ' BODY ("TEXT" "PLAIN" ("CHARSET" "US-ASCII") NIL NIL "7BIT" 3028',
303 ' 92))',
304 CRLF],
305 expected: [ { type: 'fetch',
306 num: 12,
307 textCode: undefined,
308 text: {
309 flags: [ '\\Seen' ],
310 internaldate: new Date('17-Jul-1996 02:44:25 -0700'),
311 'rfc822.size': 4286,
312 envelope: {
313 date: new Date('Wed, 17 Jul 1996 02:23:25 -0700 (PDT)'),
314 subject: 'IMAP4rev1 WG mtg summary and minutes',
315 from: [
316 { name: 'Terry Gray',
317 mailbox: 'gray',
318 host: 'cac.washington.edu'
319 }
320 ],
321 sender: [
322 { name: 'Terry Gray',
323 mailbox: 'gray',
324 host: 'cac.washington.edu'
325 }
326 ],
327 replyTo: [
328 { name: 'Terry Gray',
329 mailbox: 'gray',
330 host: 'cac.washington.edu'
331 }
332 ],
333 to: [
334 { name: null,
335 mailbox: 'imap',
336 host: 'cac.washington.edu'
337 }
338 ],
339 cc: [
340 { name: null,
341 mailbox: 'minutes',
342 host: 'CNRI.Reston.VA.US'
343 },
344 { name: 'John Klensin',
345 mailbox: 'KLENSIN',
346 host: 'MIT.EDU'
347 }
348 ],
349 bcc: null,
350 inReplyTo: null,
351 messageId: '<B27397-0100000@cac.washington.edu>'
352 },
353 body: [
354 { partID: '1',
355 type: 'text',
356 subtype: 'plain',
357 params: { charset: 'US-ASCII' },
358 id: null,
359 description: null,
360 encoding: '7BIT',
361 size: 3028,
362 lines: 92
363 }
364 ]
365 }
366 }
367 ],
368 what: 'Untagged FETCH (flags, date, size, envelope, body[structure])'
369 },
370 // EXTENSIONS ================================================================
371 { source: ['* ESEARCH (TAG "A285") UID MIN 7 MAX 3800', CRLF],
372 expected: [ { type: 'esearch',
373 num: undefined,
374 textCode: undefined,
375 text: { min: 7, max: 3800 }
376 }
377 ],
378 what: 'ESearch UID, 2 items'
379 },
380 { source: ['* ESEARCH (TAG "A284") MIN 4', CRLF],
381 expected: [ { type: 'esearch',
382 num: undefined,
383 textCode: undefined,
384 text: { min: 4 }
385 }
386 ],
387 what: 'ESearch 1 item'
388 },
389 { source: ['* ESEARCH (TAG "A283") ALL 2,10:11', CRLF],
390 expected: [ { type: 'esearch',
391 num: undefined,
392 textCode: undefined,
393 text: { all: [ '2', '10:11' ] }
394 }
395 ],
396 what: 'ESearch ALL list'
397 },
398 { source: ['* QUOTA "" (STORAGE 10 512)', CRLF],
399 expected: [ { type: 'quota',
400 num: undefined,
401 textCode: undefined,
402 text: {
403 root: '',
404 resources: {
405 storage: { usage: 10, limit: 512 }
406 }
407 }
408 }
409 ],
410 what: 'Quota'
411 },
412 { source: ['* QUOTAROOT INBOX ""', CRLF],
413 expected: [ { type: 'quotaroot',
414 num: undefined,
415 textCode: undefined,
416 text: {
417 roots: [ '' ],
418 mailbox: 'INBOX'
419 }
420 }
421 ],
422 what: 'QuotaRoot'
423 },
424].forEach(function(v) {
425 var ss = new require('stream').Readable(), p, result = [];
426 ss._read = function(){};
427
428 p = new Parser(ss);
429 p.on('tagged', function(info) {
430 result.push(info);
431 });
432 p.on('untagged', function(info) {
433 result.push(info);
434 });
435 p.on('continue', function(info) {
436 result.push(info);
437 });
438 p.on('other', function(line) {
439 result.push(line);
440 });
441 p.on('body', function(stream, info) {
442 result.push(info);
443 if (Array.isArray(v.bodySHA1s)) {
444 var hash = crypto.createHash('sha1');
445 stream.on('data', function(d) {
446 hash.update(d);
447 });
448 stream.on('end', function() {
449 var calculated = hash.digest('hex'),
450 expected = v.bodySHA1s.shift();
451 assert.equal(calculated,
452 expected,
453 makeMsg(v.what,
454 'Body SHA1 mismatch:'
455 + '\nCalculated: ' + calculated
456 + '\nExpected: ' + expected
457 )
458 );
459 });
460 }
461 });
462
463 try {
464 v.source.forEach(function(chunk) {
465 ss.push(chunk);
466 });
467 } catch (e) {
468 console.log(makeMsg(v.what, 'JS Exception: ' + e.stack));
469 return;
470 }
471 assert.deepEqual(result,
472 v.expected,
473 makeMsg(v.what,
474 'Result mismatch:'
475 + '\nParsed: ' + inspect(result, false, 10)
476 + '\nExpected: ' + inspect(v.expected, false, 10)
477 )
478 );
479});
480
481function makeMsg(what, msg) {
482 return '[' + what + ']: ' + msg;
483}
\No newline at end of file