UNPKG

@cull/imap

Version:

A simple, configurable javascript interface exposing mailboxes and messages via IMAP.

145 lines (131 loc) 5.62 kB
import test from 'ava'; import Response, { Status, ServerStatus, MessageStatus, MessageData, MessageDataItem } from './response'; import { Code } from './code'; import Envelope from './envelope'; test('Response can process a server response including multiple lines and string literals', t => { let response = new Response( Buffer.from('* OK Line 1\r\n* OK Line {4}\r\n2 \r\n\r\n* OK Line 3\r\n') ); t.is(response.lines.length, 3); t.deepEqual(response.lines, ['* OK Line 1', `* OK Line "2 \r\n"`, '* OK Line 3']); }); test('Response can process a server ready response.', t => { let response = new Response( Buffer.from('* OK Server ready for requests 0.0.0.0 54bv5g2dokk43x5g\r\n') ); t.is(response.status, Status.OK); }); test('Response can process a tagged server response and result.', t => { let response = new Response( Buffer.from(`* BYE IMAP4rev1 Server logging out\r\nA023 OK LOGOUT completed\r\n`) ); t.is(response.tag, 'A023'); t.is(response.status, Status.OK); }); test('Response can process a tagged server response and result with optional response code ALERT.', t => { let response = new Response( Buffer.from(`* OK [ALERT] System shutdown in 10 minutes\r\nA001 OK LOGIN Completed\r\n`) ); t.is(response.tag, 'A001'); t.is(response.status, Status.OK); t.is(response.codes.length, 1); t.is(response.codes[0].code, Code.ALERT); }); test('Response can process a tagged server response and result with optional response code CAPABILITY.', t => { let response = new Response( Buffer.from( `* OK [CAPABILITY IMAP4rev1 SASL-IR AUTH=PLAIN AUTH=XOAUTH2 AUTH=OAUTHBEARER ID MOVE NAMESPACE XYMHIGHESTMODSEQ UIDPLUS LITERAL+ CHILDREN X-MSG-EXT OBJECTID] IMAP4rev1 Hello\r\n` ) ); t.is(response.tag, undefined); t.is(response.status, Status.OK); t.is(response.codes.length, 1); t.is(response.codes[0].code, Code.CAPABILITY); t.is(response.codes[0].data.length, 14); }); test('Response can process an untagged CAPABILITY response.', t => { let response = new Response( Buffer.from( `* CAPABILITY IMAP4rev1 APPENDLIMIT=26214400 CHILDREN CONDSTORE ENABLE ID IDLE MOVE NAMESPACE QUOTA SPECIAL-USE UIDPLUS UNSELECT UNSELECT UTF8=ACCEPT XLIST` ) ); t.is(response.tag, undefined); t.is(response.status, undefined); t.is(response.data[ServerStatus.CAPABILITY].length, 16); }); test('Response can process an untagged LIST response.', t => { let response = new Response( Buffer.from( `* LIST (\\HasNoChildren) "/" "INBOX"\r\n* LIST () "/" "Foo"\r\n* LIST () "/" "Foo/Bar"` ) ); t.is(response.tag, undefined); t.is(response.status, undefined); t.is(response.data[ServerStatus.LIST].length, 3); let expected = { name: 'INBOX', delimiter: '/', attributes: ['\\HasNoChildren'] }; t.deepEqual(response.data[ServerStatus.LIST][0], expected); expected = { name: 'Foo/Bar', delimiter: '/', attributes: [] }; t.deepEqual(response.data[ServerStatus.LIST][2], expected); }); test('Response can process a tagged LIST response preceded with multiple untagged lines.', t => { let response = new Response( Buffer.from( `* LIST (\\HasNoChildren \\Drafts) "/" "Drafts"\r\n* LIST (\\HasNoChildren \\Junk) "/" "Junk"\r\n* LIST (\\HasNoChildren \\Sent) "/" "Sent Mail"\r\n* LIST (\\HasNoChildren \\Trash) "/" "Trash"\r\n4 OK LIST completed\r\n` ) ); t.is(response.tag, '4'); t.is(response.status, Status.OK); t.is(response.data[ServerStatus.LIST].length, 4); }); test('Response can process an untagged FLAGS response.', t => { let response = new Response(Buffer.from(`* FLAGS (\\Seen \\Drafts \\*)\r\n`)); t.is(response.tag, undefined); t.deepEqual(response.data[ServerStatus.FLAGS], ['\\Seen', '\\Drafts', '\\*']); }); test('Response can process an untagged OK response with PERMANENTFLAGS.', t => { let response = new Response( Buffer.from(`* OK [PERMANENTFLAGS (\\Seen \\Drafts \\*)] Flags permitted\r\n`) ); t.is(response.status, Status.OK); t.is(response.codes[0].code, Code.PERMANENTFLAGS); t.deepEqual(response.codes[0].data, ['\\Seen', '\\Drafts', '\\*']); }); test('Response can process an untagged OK response with UIDVALIDITY', t => { let response = new Response(Buffer.from(`* OK [UIDVALIDITY 1588148011] UIDs valid]\r\n`)); t.is(response.status, Status.OK); t.is(response.codes[0].code, Code.UIDVALIDITY); t.is(response.codes[0].data, '1588148011'); }); test('Response can process an EXPUNGE response with multiple sequences.', t => { let response = new Response(Buffer.from(`* 1 EXPUNGE\r\n* 5 EXPUNGE\r\n* 3 EXPUNGE\r\n`)); t.deepEqual(response.data[MessageStatus.EXPUNGE], [1, 5, 3]); }); test('Response can process a FETCH response with an envelope.', t => { let response = new Response( Buffer.from( `* 1 FETCH (UID 123 FLAGS () INTERNALDATE "25-May-2020 06:52:30 +0000" BODY[HEADER] {33}\r\nDelivered-To: jaclyn@cull.email\r\n ENVELOPE ("Sun, 24 May 2020 20:52:24 -1000" "test" (("Jon Adams" NIL "jon" "cull.email")) (("Jon Adams" NIL "jon" "cull.email")) (("Jon Adams" NIL "jon" "cull.email")) ((NIL NIL "manuel22" "ethereal.email")) NIL NIL NIL "<7F587D8A-7BBF-4FF8-8815-649279EF3D39@cull.email>"))\r\n` ) ); t.truthy(response.data[MessageStatus.FETCH]); let message = response.data[MessageStatus.FETCH]?.get(1) as MessageData; let uid = message[MessageDataItem.UID]; let envelope = message[MessageDataItem.ENVELOPE]; t.truthy(envelope); t.true(envelope instanceof Envelope); t.is(uid, '123'); t.is(envelope.date, 'Sun, 24 May 2020 20:52:24 -1000'); });