Initial
This commit is contained in:
33
test/imaps/node_modules/node-imap/.eslintrc.js
generated
vendored
Normal file
33
test/imaps/node_modules/node-imap/.eslintrc.js
generated
vendored
Normal file
@@ -0,0 +1,33 @@
|
||||
module.exports = {
|
||||
'env': {
|
||||
'es6': true,
|
||||
'node': true
|
||||
},
|
||||
'extends': 'eslint:recommended',
|
||||
'globals': {
|
||||
'Atomics': 'readonly',
|
||||
'SharedArrayBuffer': 'readonly'
|
||||
},
|
||||
'parserOptions': {
|
||||
'ecmaVersion': 11,
|
||||
'sourceType': 'module'
|
||||
},
|
||||
'rules': {
|
||||
'indent': [
|
||||
'error',
|
||||
2
|
||||
],
|
||||
'linebreak-style': [
|
||||
'error',
|
||||
'unix'
|
||||
],
|
||||
'quotes': [
|
||||
'error',
|
||||
'single'
|
||||
],
|
||||
'semi': [
|
||||
'error',
|
||||
'never'
|
||||
]
|
||||
}
|
||||
}
|
||||
32
test/imaps/node_modules/node-imap/.github/workflows/nodejs.yml
generated
vendored
Normal file
32
test/imaps/node_modules/node-imap/.github/workflows/nodejs.yml
generated
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
# This workflow will do a clean install of node dependencies, build the source code and run tests across different versions of node
|
||||
# For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions
|
||||
|
||||
name: node-imap CI
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ master ]
|
||||
pull_request:
|
||||
branches: [ master ]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: [10.x, 12.x]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Use Node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
- name: Install dependencies
|
||||
run: npm ci
|
||||
- run: npm run build --if-present
|
||||
- run: npm test
|
||||
env:
|
||||
CI: true
|
||||
19
test/imaps/node_modules/node-imap/LICENSE
generated
vendored
Normal file
19
test/imaps/node_modules/node-imap/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
Copyright Brian White. All rights reserved.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to
|
||||
deal in the Software without restriction, including without limitation the
|
||||
rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
sell copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
IN THE SOFTWARE.
|
||||
784
test/imaps/node_modules/node-imap/README.md
generated
vendored
Normal file
784
test/imaps/node_modules/node-imap/README.md
generated
vendored
Normal file
@@ -0,0 +1,784 @@
|
||||
|
||||

|
||||
|
||||
|
||||
Note
|
||||
====
|
||||
|
||||
This a fork of [Node-IMAP](https://github.com/mscdex/node-imap) that aims to bring the package up-to-date and incorporate all the Pull Requests from the original repo. (See the list of applied Pull requets below).
|
||||
|
||||
|
||||
|
||||
Description
|
||||
===========
|
||||
|
||||
node-imap is an IMAP client module for [node.js](http://nodejs.org/).
|
||||
|
||||
This module does not perform any magic such as auto-decoding of messages/attachments or parsing of email addresses (node-imap leaves all mail header values as-is).
|
||||
|
||||
An upgrade guide from node-imap v0.7.x to v0.8.x can be found [here](https://github.com/mscdex/node-imap/wiki/API-changes-between-v0.7-and-v0.8).
|
||||
|
||||
|
||||
Requirements
|
||||
============
|
||||
|
||||
* [node.js](http://nodejs.org/) -- v0.8.0 or newer
|
||||
|
||||
* NOTE: node v0.8.x users are supported via the readable-stream module which
|
||||
may not be up-to-date (compared to node v0.10 streams2 implementation)
|
||||
|
||||
* An IMAP server to connect to -- tested with gmail
|
||||
|
||||
|
||||
Installation
|
||||
============
|
||||
|
||||
npm install node-imap
|
||||
|
||||
Examples
|
||||
========
|
||||
|
||||
* Fetch the 'date', 'from', 'to', 'subject' message headers and the message structure of the first 3 messages in the Inbox:
|
||||
|
||||
```javascript
|
||||
var Imap = require('node-imap'),
|
||||
inspect = require('util').inspect;
|
||||
|
||||
var imap = new Imap({
|
||||
user: 'mygmailname@gmail.com',
|
||||
password: 'mygmailpassword',
|
||||
host: 'imap.gmail.com',
|
||||
port: 993,
|
||||
tls: true
|
||||
});
|
||||
|
||||
function openInbox(cb) {
|
||||
imap.openBox('INBOX', true, cb);
|
||||
}
|
||||
|
||||
imap.once('ready', function() {
|
||||
openInbox(function(err, box) {
|
||||
if (err) throw err;
|
||||
var f = imap.seq.fetch('1:3', {
|
||||
bodies: 'HEADER.FIELDS (FROM TO SUBJECT DATE)',
|
||||
struct: true
|
||||
});
|
||||
f.on('message', function(msg, seqno) {
|
||||
console.log('Message #%d', seqno);
|
||||
var prefix = '(#' + seqno + ') ';
|
||||
msg.on('body', function(stream, info) {
|
||||
var buffer = '';
|
||||
stream.on('data', function(chunk) {
|
||||
buffer += chunk.toString('utf8');
|
||||
});
|
||||
stream.once('end', function() {
|
||||
console.log(prefix + 'Parsed header: %s', inspect(Imap.parseHeader(buffer)));
|
||||
});
|
||||
});
|
||||
msg.once('attributes', function(attrs) {
|
||||
console.log(prefix + 'Attributes: %s', inspect(attrs, false, 8));
|
||||
});
|
||||
msg.once('end', function() {
|
||||
console.log(prefix + 'Finished');
|
||||
});
|
||||
});
|
||||
f.once('error', function(err) {
|
||||
console.log('Fetch error: ' + err);
|
||||
});
|
||||
f.once('end', function() {
|
||||
console.log('Done fetching all messages!');
|
||||
imap.end();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
imap.once('error', function(err) {
|
||||
console.log(err);
|
||||
});
|
||||
|
||||
imap.once('end', function() {
|
||||
console.log('Connection ended');
|
||||
});
|
||||
|
||||
imap.connect();
|
||||
```
|
||||
|
||||
* Retrieve the 'from' header and buffer the entire body of the newest message:
|
||||
|
||||
```javascript
|
||||
// using the functions and variables already defined in the first example ...
|
||||
|
||||
openInbox(function(err, box) {
|
||||
if (err) throw err;
|
||||
var f = imap.seq.fetch(box.messages.total + ':*', { bodies: ['HEADER.FIELDS (FROM)','TEXT'] });
|
||||
f.on('message', function(msg, seqno) {
|
||||
console.log('Message #%d', seqno);
|
||||
var prefix = '(#' + seqno + ') ';
|
||||
msg.on('body', function(stream, info) {
|
||||
if (info.which === 'TEXT')
|
||||
console.log(prefix + 'Body [%s] found, %d total bytes', inspect(info.which), info.size);
|
||||
var buffer = '', count = 0;
|
||||
stream.on('data', function(chunk) {
|
||||
count += chunk.length;
|
||||
buffer += chunk.toString('utf8');
|
||||
if (info.which === 'TEXT')
|
||||
console.log(prefix + 'Body [%s] (%d/%d)', inspect(info.which), count, info.size);
|
||||
});
|
||||
stream.once('end', function() {
|
||||
if (info.which !== 'TEXT')
|
||||
console.log(prefix + 'Parsed header: %s', inspect(Imap.parseHeader(buffer)));
|
||||
else
|
||||
console.log(prefix + 'Body [%s] Finished', inspect(info.which));
|
||||
});
|
||||
});
|
||||
msg.once('attributes', function(attrs) {
|
||||
console.log(prefix + 'Attributes: %s', inspect(attrs, false, 8));
|
||||
});
|
||||
msg.once('end', function() {
|
||||
console.log(prefix + 'Finished');
|
||||
});
|
||||
});
|
||||
f.once('error', function(err) {
|
||||
console.log('Fetch error: ' + err);
|
||||
});
|
||||
f.once('end', function() {
|
||||
console.log('Done fetching all messages!');
|
||||
imap.end();
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
* Save raw unread emails since May 20, 2010 to files:
|
||||
|
||||
```javascript
|
||||
// using the functions and variables already defined in the first example ...
|
||||
|
||||
var fs = require('fs'), fileStream;
|
||||
|
||||
openInbox(function(err, box) {
|
||||
if (err) throw err;
|
||||
imap.search([ 'UNSEEN', ['SINCE', 'May 20, 2010'] ], function(err, results) {
|
||||
if (err) throw err;
|
||||
var f = imap.fetch(results, { bodies: '' });
|
||||
f.on('message', function(msg, seqno) {
|
||||
console.log('Message #%d', seqno);
|
||||
var prefix = '(#' + seqno + ') ';
|
||||
msg.on('body', function(stream, info) {
|
||||
console.log(prefix + 'Body');
|
||||
stream.pipe(fs.createWriteStream('msg-' + seqno + '-body.txt'));
|
||||
});
|
||||
msg.once('attributes', function(attrs) {
|
||||
console.log(prefix + 'Attributes: %s', inspect(attrs, false, 8));
|
||||
});
|
||||
msg.once('end', function() {
|
||||
console.log(prefix + 'Finished');
|
||||
});
|
||||
});
|
||||
f.once('error', function(err) {
|
||||
console.log('Fetch error: ' + err);
|
||||
});
|
||||
f.once('end', function() {
|
||||
console.log('Done fetching all messages!');
|
||||
imap.end();
|
||||
});
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
|
||||
API
|
||||
===
|
||||
|
||||
#### Data types
|
||||
|
||||
* _MessageSource_ can be a single message identifier, a message identifier range (e.g. `'2504:2507'` or `'*'` or `'2504:*'`), an _array_ of message identifiers, or an _array_ of message identifier ranges.
|
||||
|
||||
* _Box_ is an object representing the currently open mailbox, and has the following properties:
|
||||
* **name** - _string_ - The name of this mailbox.
|
||||
* **readOnly** - _boolean_ - True if this mailbox was opened in read-only mode. **(Only available with openBox() calls)**
|
||||
* **newKeywords** - _boolean_ - True if new keywords can be added to messages in this mailbox.
|
||||
* **uidvalidity** - _integer_ - A 32-bit number that can be used to determine if UIDs in this mailbox have changed since the last time this mailbox was opened.
|
||||
* **uidnext** - _integer_ - The uid that will be assigned to the next message that arrives at this mailbox.
|
||||
* **flags** - _array_ - A list of system-defined flags applicable for this mailbox. Flags in this list but *not* in `permFlags` may be stored for the current session only. Additional server implementation-specific flags may also be available.
|
||||
* **permFlags** - _array_ - A list of flags that can be permanently added/removed to/from messages in this mailbox.
|
||||
* **persistentUIDs** - _boolean_ - Whether or not this mailbox has persistent UIDs. This should almost always be true for modern mailboxes and should only be false for legacy mail stores where supporting persistent UIDs was not technically feasible.
|
||||
* **messages** - _object_ - Contains various message counts for this mailbox:
|
||||
* **total** - _integer_ - Total number of messages in this mailbox.
|
||||
* **new** - _integer_ - Number of messages in this mailbox having the Recent flag (this IMAP session is the first to see these messages).
|
||||
* **unseen** - _integer_ - **(Only available with status() calls)** Number of messages in this mailbox not having the Seen flag (marked as not having been read).
|
||||
|
||||
* _ImapMessage_ is an object representing an email message. It consists of:
|
||||
* Events:
|
||||
* **body**(< _ReadableStream_ >stream, < _object_ >info) - Emitted for each requested body. Example `info` properties:
|
||||
* **which** - _string_ - The specifier for this body (e.g. 'TEXT', 'HEADER.FIELDS (TO FROM SUBJECT)', etc).
|
||||
* **size** - _integer_ - The size of this body in bytes.
|
||||
* **attributes**(< _object_ >attrs) - Emitted when all message attributes have been collected. Example `attrs` properties:
|
||||
* **uid** - _integer_ - A 32-bit ID that uniquely identifies this message within its mailbox.
|
||||
* **flags** - _array_ - A list of flags currently set on this message.
|
||||
* **date** - _Date_ - The internal server date for the message.
|
||||
* **struct** - _array_ - The message's body structure **(only set if requested with fetch())**. See below for an explanation of the format of this property.
|
||||
* **size** - _integer_ - The RFC822 message size **(only set if requested with fetch())**.
|
||||
* **end**() - Emitted when all attributes and bodies have been parsed.
|
||||
|
||||
* _ImapFetch_ is an object representing a fetch() request. It consists of:
|
||||
* Events:
|
||||
* **message**(< _ImapMessage_ >msg, < _integer_ >seqno) - Emitted for each message resulting from a fetch request. `seqno` is the message's sequence number.
|
||||
* **error**(< _Error_ >err) - Emitted when an error occurred.
|
||||
* **end**() - Emitted when all messages have been parsed.
|
||||
|
||||
A message structure with multiple parts might look something like the following:
|
||||
|
||||
```javascript
|
||||
[ { type: 'mixed',
|
||||
params: { boundary: '000e0cd294e80dc84c0475bf339d' },
|
||||
disposition: null,
|
||||
language: null,
|
||||
location: null
|
||||
},
|
||||
[ { type: 'alternative',
|
||||
params: { boundary: '000e0cd294e80dc83c0475bf339b' },
|
||||
disposition: null,
|
||||
language: null
|
||||
},
|
||||
[ { partID: '1.1',
|
||||
type: 'text',
|
||||
subtype: 'plain',
|
||||
params: { charset: 'ISO-8859-1' },
|
||||
id: null,
|
||||
description: null,
|
||||
encoding: '7BIT',
|
||||
size: 935,
|
||||
lines: 46,
|
||||
md5: null,
|
||||
disposition: null,
|
||||
language: null
|
||||
}
|
||||
],
|
||||
[ { partID: '1.2',
|
||||
type: 'text',
|
||||
subtype: 'html',
|
||||
params: { charset: 'ISO-8859-1' },
|
||||
id: null,
|
||||
description: null,
|
||||
encoding: 'QUOTED-PRINTABLE',
|
||||
size: 1962,
|
||||
lines: 33,
|
||||
md5: null,
|
||||
disposition: null,
|
||||
language: null
|
||||
}
|
||||
]
|
||||
],
|
||||
[ { partID: '2',
|
||||
type: 'application',
|
||||
subtype: 'octet-stream',
|
||||
params: { name: 'somefile' },
|
||||
id: null,
|
||||
description: null,
|
||||
encoding: 'BASE64',
|
||||
size: 98,
|
||||
lines: null,
|
||||
md5: null,
|
||||
disposition:
|
||||
{ type: 'attachment',
|
||||
params: { filename: 'somefile' }
|
||||
},
|
||||
language: null,
|
||||
location: null
|
||||
}
|
||||
]
|
||||
]
|
||||
```
|
||||
|
||||
The above structure describes a message having both an attachment and two forms of the message body (plain text and HTML).
|
||||
Each message part is identified by a partID which is used when you want to fetch the content of that part (see fetch()).
|
||||
|
||||
The structure of a message with only one part will simply look something like this:
|
||||
|
||||
```javascript
|
||||
[ { partID: '1',
|
||||
type: 'text',
|
||||
subtype: 'plain',
|
||||
params: { charset: 'ISO-8859-1' },
|
||||
id: null,
|
||||
description: null,
|
||||
encoding: '7BIT',
|
||||
size: 935,
|
||||
lines: 46,
|
||||
md5: null,
|
||||
disposition: null,
|
||||
language: null
|
||||
}
|
||||
]
|
||||
```
|
||||
|
||||
Therefore, an easy way to check for a multipart message is to check if the structure length is >1.
|
||||
|
||||
Lastly, here are the system flags defined by RFC3501 that may be added/removed:
|
||||
|
||||
* \Seen - Message has been read
|
||||
* \Answered - Message has been answered
|
||||
* \Flagged - Message is "flagged" for urgent/special attention
|
||||
* \Deleted - Message is marked for removal
|
||||
* \Draft - Message has not completed composition (marked as a draft).
|
||||
|
||||
It should be noted however that the IMAP server can limit which flags can be permanently modified for any given message. If in doubt, check the mailbox's **permFlags** first.
|
||||
Additional custom flags may be provided by the server. If available, these will also be listed in the mailbox's **permFlags**.
|
||||
|
||||
|
||||
require('imap') returns one object: **Connection**.
|
||||
|
||||
|
||||
Connection Events
|
||||
-----------------
|
||||
|
||||
* **ready**() - Emitted when a connection to the server has been made and authentication was successful.
|
||||
|
||||
* **alert**(< _string_ >message) - Emitted when the server issues an alert (e.g. "the server is going down for maintenance").
|
||||
|
||||
* **mail**(< _integer_ >numNewMsgs) - Emitted when new mail arrives in the currently open mailbox.
|
||||
|
||||
* **expunge**(< _integer_ >seqno) - Emitted when a message was expunged externally. `seqno` is the sequence number (instead of the unique UID) of the message that was expunged. If you are caching sequence numbers, all sequence numbers higher than this value **MUST** be decremented by 1 in order to stay synchronized with the server and to keep correct continuity.
|
||||
|
||||
* **uidvalidity**(< _integer_ >uidvalidity) - Emitted if the UID validity value for the currently open mailbox changes during the current session.
|
||||
|
||||
* **update**(< _integer_ >seqno, < _object_ >info) - Emitted when message metadata (e.g. flags) changes externally.
|
||||
|
||||
* **error**(< _Error_ >err) - Emitted when an error occurs. The 'source' property will be set to indicate where the error originated from.
|
||||
|
||||
* **close**(< _boolean_ >hadError) - Emitted when the connection has completely closed.
|
||||
|
||||
* **end**() - Emitted when the connection has ended.
|
||||
|
||||
|
||||
Connection Properties
|
||||
---------------------
|
||||
|
||||
* **state** - _string_ - The current state of the connection (e.g. 'disconnected', 'connected', 'authenticated').
|
||||
|
||||
* **delimiter** - _string_ - The (top-level) mailbox hierarchy delimiter. If the server does not support mailbox hierarchies and only a flat list, this value will be falsey.
|
||||
|
||||
* **namespaces** - _object_ - Contains information about each namespace type (if supported by the server) with the following properties:
|
||||
|
||||
* **personal** - _array_ - Mailboxes that belong to the logged in user.
|
||||
* **other** - _array_ - Mailboxes that belong to other users that the logged in user has access to.
|
||||
* **shared** - _array_ - Mailboxes that are accessible by any logged in user.
|
||||
|
||||
There should always be at least one entry (although the IMAP spec allows for more, it doesn't seem to be very common) in the personal namespace list, with a blank namespace prefix. Each property's array contains objects of the following format (with example values):
|
||||
|
||||
```javascript
|
||||
{ prefix: '', // A string containing the prefix to use to access mailboxes in this namespace
|
||||
delimiter: '/', // A string containing the hierarchy delimiter for this namespace, or boolean false
|
||||
// for a flat namespace with no hierarchy
|
||||
extensions: [ // An array of namespace extensions supported by this namespace, or null if none
|
||||
// are specified
|
||||
{ name: 'X-FOO-BAR', // A string indicating the extension name
|
||||
params: [ 'BAZ' ] // An array of strings containing the parameters for this extension,
|
||||
// or null if none are specified
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
Connection Static Methods
|
||||
-------------------------
|
||||
|
||||
* **parseHeader**(< _string_ >rawHeader[, < _boolean_ >disableAutoDecode]) - _object_ - Parses a raw header and returns an object keyed on header fields and the values are Arrays of header field values. Set `disableAutoDecode` to true to disable automatic decoding of MIME encoded-words that may exist in header field values.
|
||||
|
||||
|
||||
Connection Instance Methods
|
||||
---------------------------
|
||||
|
||||
**Note:** Message UID ranges are not guaranteed to be contiguous.
|
||||
|
||||
* **(constructor)**([< _object_ >config]) - _Connection_ - Creates and returns a new instance of _Connection_ using the specified configuration object. Valid config properties are:
|
||||
|
||||
* **user** - _string_ - Username for plain-text authentication.
|
||||
* **password** - _string_ - Password for plain-text authentication.
|
||||
* **xoauth** - _string_ - Base64-encoded OAuth token for [OAuth authentication](https://sites.google.com/site/oauthgoog/Home/oauthimap) for servers that support it (See Andris Reinman's [xoauth.js](https://github.com/andris9/inbox/blob/master/lib/xoauth.js) module to help generate this string).
|
||||
* **xoauth2** - _string_ - Base64-encoded OAuth2 token for [The SASL XOAUTH2 Mechanism](https://developers.google.com/google-apps/gmail/xoauth2_protocol#the_sasl_xoauth2_mechanism) for servers that support it (See Andris Reinman's [xoauth2](https://github.com/andris9/xoauth2) module to help generate this string).
|
||||
* **host** - _string_ - Hostname or IP address of the IMAP server. **Default:** "localhost"
|
||||
* **port** - _integer_ - Port number of the IMAP server. **Default:** 143
|
||||
* **tls** - _boolean_ - Perform implicit TLS connection? **Default:** false
|
||||
* **tlsOptions** - _object_ - Options object to pass to tls.connect() **Default:** (none)
|
||||
* **autotls** - _string_ - Set to 'always' to always attempt connection upgrades via STARTTLS, 'required' only if upgrading is required, or 'never' to never attempt upgrading. **Default:** 'never'
|
||||
* **connTimeout** - _integer_ - Number of milliseconds to wait for a connection to be established. **Default:** 10000
|
||||
* **authTimeout** - _integer_ - Number of milliseconds to wait to be authenticated after a connection has been established. **Default:** 5000
|
||||
* **socketTimeout** - _integer_ - The timeout set for the socket created when communicating with the IMAP server. If not set, the socket will not have a timeout. **Default:** 0
|
||||
* **keepalive** - _mixed_ - Configures the keepalive mechanism. Set to `true` to enable keepalive with defaults or set to object to enable and configure keepalive behavior: **Default:** true
|
||||
* **interval** - _integer_ - This is the interval (in milliseconds) at which NOOPs are sent and the interval at which `idleInterval` is checked. **Default:** 10000
|
||||
* **idleInterval** - _integer_ - This is the interval (in milliseconds) at which an IDLE command (for servers that support IDLE) is re-sent. **Default:** 300000 (5 mins)
|
||||
* **forceNoop** - _boolean_ - Set to `true` to force use of NOOP keepalive on servers also support IDLE. **Default:** false
|
||||
* **debug** - _function_ - If set, the function will be called with one argument, a string containing some debug info **Default:** (no debug output)
|
||||
|
||||
* **connect**() - _(void)_ - Attempts to connect and authenticate with the IMAP server.
|
||||
|
||||
* **end**() - _(void)_ - Closes the connection to the server after all requests in the queue have been sent.
|
||||
|
||||
* **destroy**() - _(void)_ - Immediately destroys the connection to the server.
|
||||
|
||||
* **openBox**(< _string_ >mailboxName[, < _boolean_ >openReadOnly=false[, < _object_ >modifiers]], < _function_ >callback) - _(void)_ - Opens a specific mailbox that exists on the server. `mailboxName` should include any necessary prefix/path. `modifiers` is used by IMAP extensions. `callback` has 2 parameters: < _Error_ >err, < _Box_ >mailbox.
|
||||
|
||||
* **closeBox**([< _boolean_ >autoExpunge=true, ]< _function_ >callback) - _(void)_ - Closes the currently open mailbox. If `autoExpunge` is true, any messages marked as Deleted in the currently open mailbox will be removed if the mailbox was NOT opened in read-only mode. If `autoExpunge` is false, you disconnect, or you open another mailbox, messages marked as Deleted will **NOT** be removed from the currently open mailbox. `callback` has 1 parameter: < _Error_ >err.
|
||||
|
||||
* **addBox**(< _string_ >mailboxName, < _function_ >callback) - _(void)_ - Creates a new mailbox on the server. `mailboxName` should include any necessary prefix/path. `callback` has 1 parameter: < _Error_ >err.
|
||||
|
||||
* **delBox**(< _string_ >mailboxName, < _function_ >callback) - _(void)_ - Removes a specific mailbox that exists on the server. `mailboxName` should including any necessary prefix/path. `callback` has 1 parameter: < _Error_ >err.
|
||||
|
||||
* **renameBox**(< _string_ >oldMailboxName, < _string_ >newMailboxName, < _function_ >callback) - _(void)_ - Renames a specific mailbox that exists on the server. Both `oldMailboxName` and `newMailboxName` should include any necessary prefix/path. `callback` has 2 parameters: < _Error_ >err, < _Box_ >mailbox. **Note:** Renaming the 'INBOX' mailbox will instead cause all messages in 'INBOX' to be moved to the new mailbox.
|
||||
|
||||
* **subscribeBox**(< _string_ >mailboxName, < _function_ >callback) - _(void)_ - Subscribes to a specific mailbox that exists on the server. `mailboxName` should include any necessary prefix/path. `callback` has 1 parameter: < _Error_ >err.
|
||||
|
||||
* **unsubscribeBox**(< _string_ >mailboxName, < _function_ >callback) - _(void)_ - Unsubscribes from a specific mailbox that exists on the server. `mailboxName` should include any necessary prefix/path. `callback` has 1 parameter: < _Error_ >err.
|
||||
|
||||
* **status**(< _string_ >mailboxName, < _function_ >callback) - _(void)_ - Fetches information about a mailbox other than the one currently open. `callback` has 2 parameters: < _Error_ >err, < _Box_ >mailbox. **Note:** There is no guarantee that this will be a fast operation on the server. Also, do **not** call this on the currently open mailbox.
|
||||
|
||||
* **getBoxes**([< _string_ >nsPrefix, ]< _function_ >callback) - _(void)_ - Obtains the full list of mailboxes. If `nsPrefix` is not specified, the main personal namespace is used. `callback` has 2 parameters: < _Error_ >err, < _object_ >boxes. `boxes` has the following format (with example values):
|
||||
|
||||
```javascript
|
||||
{ INBOX: // mailbox name
|
||||
{ attribs: [], // mailbox attributes. An attribute of 'NOSELECT' indicates the mailbox cannot
|
||||
// be opened
|
||||
delimiter: '/', // hierarchy delimiter for accessing this mailbox's direct children.
|
||||
children: null, // an object containing another structure similar in format to this top level,
|
||||
// otherwise null if no children
|
||||
parent: null // pointer to parent mailbox, null if at the top level
|
||||
},
|
||||
Work:
|
||||
{ attribs: [],
|
||||
delimiter: '/',
|
||||
children: null,
|
||||
parent: null
|
||||
},
|
||||
'[Gmail]':
|
||||
{ attribs: [ '\\NOSELECT' ],
|
||||
delimiter: '/',
|
||||
children:
|
||||
{ 'All Mail':
|
||||
{ attribs: [ '\\All' ],
|
||||
delimiter: '/',
|
||||
children: null,
|
||||
parent: [Circular]
|
||||
},
|
||||
Drafts:
|
||||
{ attribs: [ '\\Drafts' ],
|
||||
delimiter: '/',
|
||||
children: null,
|
||||
parent: [Circular]
|
||||
},
|
||||
Important:
|
||||
{ attribs: [ '\\Important' ],
|
||||
delimiter: '/',
|
||||
children: null,
|
||||
parent: [Circular]
|
||||
},
|
||||
'Sent Mail':
|
||||
{ attribs: [ '\\Sent' ],
|
||||
delimiter: '/',
|
||||
children: null,
|
||||
parent: [Circular]
|
||||
},
|
||||
Spam:
|
||||
{ attribs: [ '\\Junk' ],
|
||||
delimiter: '/',
|
||||
children: null,
|
||||
parent: [Circular]
|
||||
},
|
||||
Starred:
|
||||
{ attribs: [ '\\Flagged' ],
|
||||
delimiter: '/',
|
||||
children: null,
|
||||
parent: [Circular]
|
||||
},
|
||||
Trash:
|
||||
{ attribs: [ '\\Trash' ],
|
||||
delimiter: '/',
|
||||
children: null,
|
||||
parent: [Circular]
|
||||
}
|
||||
},
|
||||
parent: null
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
* **getSubscribedBoxes**([< _string_ >nsPrefix, ]< _function_ >callback) - _(void)_ - Obtains the full list of subscribed mailboxes. If `nsPrefix` is not specified, the main personal namespace is used. `callback` has 2 parameters: < _Error_ >err, < _object_ >boxes. `boxes` has the same format as getBoxes above.
|
||||
|
||||
* **expunge**([< _MessageSource_ >uids, ]< _function_ >callback) - _(void)_ - Permanently removes all messages flagged as Deleted in the currently open mailbox. If the server supports the 'UIDPLUS' capability, `uids` can be supplied to only remove messages that both have their uid in `uids` and have the \Deleted flag set. `callback` has 1 parameter: < _Error_ >err. **Note:** At least on Gmail, performing this operation with any currently open mailbox that is not the Spam or Trash mailbox will merely archive any messages marked as Deleted (by moving them to the 'All Mail' mailbox).
|
||||
|
||||
* **append**(< _mixed_ >msgData, [< _object_ >options, ]< _function_ >callback) - _(void)_ - Appends a message to selected mailbox. `msgData` is a string or Buffer containing an RFC-822 compatible MIME message. Valid `options` properties are:
|
||||
|
||||
* **mailbox** - _string_ - The name of the mailbox to append the message to. **Default:** the currently open mailbox
|
||||
* **flags** - _mixed_ - A single flag (e.g. 'Seen') or an _array_ of flags (e.g. `['Seen', 'Flagged']`) to append to the message. **Default:** (no flags)
|
||||
* **date** - _Date_ - What to use for message arrival date/time. **Default:** (current date/time)
|
||||
|
||||
`callback` has 1 parameter: < _Error_ >err.
|
||||
|
||||
**All functions below have sequence number-based counterparts that can be accessed by using the 'seq' namespace of the imap connection's instance (e.g. conn.seq.search() returns sequence number(s) instead of UIDs, conn.seq.fetch() fetches by sequence number(s) instead of UIDs, etc):**
|
||||
|
||||
* **search**(< _array_ >criteria, < _function_ >callback) - _(void)_ - Searches the currently open mailbox for messages using given criteria. `criteria` is a list describing what you want to find. For criteria types that require arguments, use an _array_ instead of just the string criteria type name (e.g. ['FROM', 'foo@bar.com']). Prefix criteria types with an "!" to negate.
|
||||
|
||||
* The following message flags are valid types that do not have arguments:
|
||||
|
||||
* 'ALL' - All messages.
|
||||
* 'ANSWERED' - Messages with the Answered flag set.
|
||||
* 'DELETED' - Messages with the Deleted flag set.
|
||||
* 'DRAFT' - Messages with the Draft flag set.
|
||||
* 'FLAGGED' - Messages with the Flagged flag set.
|
||||
* 'NEW' - Messages that have the Recent flag set but not the Seen flag.
|
||||
* 'SEEN' - Messages that have the Seen flag set.
|
||||
* 'RECENT' - Messages that have the Recent flag set.
|
||||
* 'OLD' - Messages that do not have the Recent flag set. This is functionally equivalent to "!RECENT" (as opposed to "!NEW").
|
||||
* 'UNANSWERED' - Messages that do not have the Answered flag set.
|
||||
* 'UNDELETED' - Messages that do not have the Deleted flag set.
|
||||
* 'UNDRAFT' - Messages that do not have the Draft flag set.
|
||||
* 'UNFLAGGED' - Messages that do not have the Flagged flag set.
|
||||
* 'UNSEEN' - Messages that do not have the Seen flag set.
|
||||
|
||||
* The following are valid types that require string value(s):
|
||||
|
||||
* 'BCC' - Messages that contain the specified string in the BCC field.
|
||||
* 'CC' - Messages that contain the specified string in the CC field.
|
||||
* 'FROM' - Messages that contain the specified string in the FROM field.
|
||||
* 'SUBJECT' - Messages that contain the specified string in the SUBJECT field.
|
||||
* 'TO' - Messages that contain the specified string in the TO field.
|
||||
* 'BODY' - Messages that contain the specified string in the message body.
|
||||
* 'TEXT' - Messages that contain the specified string in the header OR the message body.
|
||||
* 'KEYWORD' - Messages with the specified keyword set.
|
||||
* 'HEADER' - **Requires two string values, with the first being the header name and the second being the value to search for.** If this second string is empty, all messages that contain the given header name will be returned.
|
||||
|
||||
* The following are valid types that require a string parseable by JavaScript's Date object OR a Date instance:
|
||||
|
||||
* 'BEFORE' - Messages whose internal date (disregarding time and timezone) is earlier than the specified date.
|
||||
* 'ON' - Messages whose internal date (disregarding time and timezone) is within the specified date.
|
||||
* 'SINCE' - Messages whose internal date (disregarding time and timezone) is within or later than the specified date.
|
||||
* 'SENTBEFORE' - Messages whose Date header (disregarding time and timezone) is earlier than the specified date.
|
||||
* 'SENTON' - Messages whose Date header (disregarding time and timezone) is within the specified date.
|
||||
* 'SENTSINCE' - Messages whose Date header (disregarding time and timezone) is within or later than the specified date.
|
||||
|
||||
* The following are valid types that require one Integer value:
|
||||
|
||||
* 'LARGER' - Messages with a size larger than the specified number of bytes.
|
||||
* 'SMALLER' - Messages with a size smaller than the specified number of bytes.
|
||||
|
||||
* The following are valid criterion that require one or more Integer values:
|
||||
|
||||
* 'UID' - Messages with UIDs corresponding to the specified UID set. Ranges are permitted (e.g. '2504:2507' or '\*' or '2504:\*').
|
||||
|
||||
* **Note 1:** For the UID-based search (i.e. "conn.search()"), you can retrieve the UIDs for sequence numbers by just supplying an _array_ of sequence numbers and/or ranges as a criteria (e.g. [ '24:29', 19, '66:*' ]).
|
||||
|
||||
* **Note 2:** By default, all criterion are ANDed together. You can use the special 'OR' on **two** criterion to find messages matching either search criteria (see example below).
|
||||
|
||||
`criteria` examples:
|
||||
|
||||
* Unread messages since April 20, 2010: [ 'UNSEEN', ['SINCE', 'April 20, 2010'] ]
|
||||
* Messages that are EITHER unread OR are dated April 20, 2010 or later, you could use: [ ['OR', 'UNSEEN', ['SINCE', 'April 20, 2010'] ] ]
|
||||
* All messages that have 'node-imap' in the subject header: [ ['HEADER', 'SUBJECT', 'node-imap'] ]
|
||||
* All messages that _do not_ have 'node-imap' in the subject header: [ ['!HEADER', 'SUBJECT', 'node-imap'] ]
|
||||
|
||||
`callback` has 2 parameters: < _Error_ >err, < _array_ >UIDs.
|
||||
|
||||
* **fetch**(< _MessageSource_ >source, [< _object_ >options]) - _ImapFetch_ - Fetches message(s) in the currently open mailbox.
|
||||
|
||||
Valid `options` properties are:
|
||||
|
||||
* **markSeen** - _boolean_ - Mark message(s) as read when fetched. **Default:** false
|
||||
* **struct** - _boolean_ - Fetch the message structure. **Default:** false
|
||||
* **envelope** - _boolean_ - Fetch the message envelope. **Default:** false
|
||||
* **size** - _boolean_ - Fetch the RFC822 size. **Default:** false
|
||||
* **modifiers** - _object_ - Fetch modifiers defined by IMAP extensions. **Default:** (none)
|
||||
* **extensions** - _array_ - Fetch custom fields defined by IMAP extensions, e.g. ['X-MAILBOX', 'X-REAL-UID']. **Default:** (none)
|
||||
* **bodies** - _mixed_ - A string or Array of strings containing the body part section to fetch. **Default:** (none) Example sections:
|
||||
|
||||
* 'HEADER' - The message header
|
||||
* 'HEADER.FIELDS (TO FROM SUBJECT)' - Specific header fields only
|
||||
* 'HEADER.FIELDS.NOT (TO FROM SUBJECT)' - Header fields only that do not match the fields given
|
||||
* 'TEXT' - The message body
|
||||
* '' - The entire message (header + body)
|
||||
* 'MIME' - MIME-related header fields only (e.g. 'Content-Type')
|
||||
|
||||
**Note:** You can also prefix `bodies` strings (i.e. 'TEXT', 'HEADER', 'HEADER.FIELDS', and 'HEADER.FIELDS.NOT' for `message/rfc822` messages and 'MIME' for any kind of message) with part ids. For example: '1.TEXT', '1.2.HEADER', '2.MIME', etc.
|
||||
**Note 2:** 'HEADER*' sections are only valid for parts whose content type is `message/rfc822`, including the root part (no part id).
|
||||
|
||||
* **copy**(< _MessageSource_ >source, < _string_ >mailboxName, < _function_ >callback) - _(void)_ - Copies message(s) in the currently open mailbox to another mailbox. `callback` has 1 parameter: < _Error_ >err.
|
||||
|
||||
* **move**(< _MessageSource_ >source, < _string_ >mailboxName, < _function_ >callback) - _(void)_ - Moves message(s) in the currently open mailbox to another mailbox. `callback` has 1 parameter: < _Error_ >err. **Note:** The message(s) in the destination mailbox will have a new message UID.
|
||||
|
||||
* **addFlags**(< _MessageSource_ >source, < _mixed_ >flags, < _function_ >callback) - _(void)_ - Adds flag(s) to message(s). `callback` has 1 parameter: < _Error_ >err.
|
||||
|
||||
* **delFlags**(< _MessageSource_ >source, < _mixed_ >flags, < _function_ >callback) - _(void)_ - Removes flag(s) from message(s). `callback` has 1 parameter: < _Error_ >err.
|
||||
|
||||
* **setFlags**(< _MessageSource_ >source, < _mixed_ >flags, < _function_ >callback) - _(void)_ - Sets the flag(s) for message(s). `callback` has 1 parameter: < _Error_ >err.
|
||||
|
||||
* **addKeywords**(< _MessageSource_ >source, < _mixed_ >keywords, < _function_ >callback) - _(void)_ - Adds keyword(s) to message(s). `keywords` is either a single keyword or an _array_ of keywords. `callback` has 1 parameter: < _Error_ >err.
|
||||
|
||||
* **delKeywords**(< _MessageSource_ >source, < _mixed_ >keywords, < _function_ >callback) - _(void)_ - Removes keyword(s) from message(s). `keywords` is either a single keyword or an _array_ of keywords. `callback` has 1 parameter: < _Error_ >err.
|
||||
|
||||
* **setKeywords**(< _MessageSource_ >source, < _mixed_ >keywords, < _function_ >callback) - _(void)_ - Sets keyword(s) for message(s). `keywords` is either a single keyword or an _array_ of keywords. `callback` has 1 parameter: < _Error_ >err.
|
||||
|
||||
* **serverSupports**(< _string_ >capability) - _boolean_ - Checks if the server supports the specified capability.
|
||||
|
||||
|
||||
Extensions Supported
|
||||
--------------------
|
||||
|
||||
* **Gmail**
|
||||
|
||||
* Server capability: X-GM-EXT-1
|
||||
|
||||
* search() criteria extensions:
|
||||
|
||||
* **X-GM-RAW** - _string_ - Gmail's custom search syntax. Example: 'has:attachment in:unread'
|
||||
* **X-GM-THRID** - _string_ - Conversation/thread id
|
||||
* **X-GM-MSGID** - _string_ - Account-wide unique id
|
||||
* **X-GM-LABELS** - _string_ - Gmail label
|
||||
|
||||
* fetch() will automatically retrieve the thread id, unique message id, and labels (named 'x-gm-thrid', 'x-gm-msgid', 'x-gm-labels' respectively)
|
||||
|
||||
* Additional Connection instance methods (seqno-based counterparts exist):
|
||||
|
||||
* **setLabels**(< _MessageSource_ >source, < _mixed_ >labels, < _function_ >callback) - _(void)_ - Replaces labels of message(s) with `labels`. `labels` is either a single label or an _array_ of labels. `callback` has 1 parameter: < _Error_ >err.
|
||||
|
||||
* **addLabels**(< _MessageSource_ >source, < _mixed_ >labels, < _function_ >callback) - _(void)_ - Adds `labels` to message(s). `labels` is either a single label or an _array_ of labels. `callback` has 1 parameter: < _Error_ >err.
|
||||
|
||||
* **delLabels**(< _MessageSource_ >source, < _mixed_ >labels, < _function_ >callback) - _(void)_ - Removes `labels` from message(s). `labels` is either a single label or an _array_ of labels. `callback` has 1 parameter: < _Error_ >err.
|
||||
|
||||
* **RFC2087**
|
||||
|
||||
* Server capability: QUOTA
|
||||
|
||||
* Additional Connection instance methods:
|
||||
|
||||
* **setQuota**(< _string_ >quotaRoot, < _object_ >quotas, < _function_ >callback) - _(void)_ - Sets the resource limits for `quotaRoot` using the limits in `quotas`. `callback` has 2 parameters: < _Error_ >err, < _object_ >limits. `limits` has the same format as `limits` passed to getQuota()'s callback. Example `quotas` properties (taken from RFC2087):
|
||||
|
||||
* storage - Sum of messages' (RFC822) size, in kilobytes (integer).
|
||||
* message - Number of messages (integer).
|
||||
|
||||
* **getQuota**(< _string_ >quotaRoot, < _function_ >callback) - _(void)_ - Gets the resource usage and limits for `quotaRoot`. `callback` has 2 parameters: < _Error_ >err, < _object_ >limits. `limits` is keyed on the resource name, where the values are objects with the following properties:
|
||||
|
||||
* usage - _integer_ - Resource usage.
|
||||
* limit - _integer_ - Resource limit.
|
||||
|
||||
* **getQuotaRoot**(< _string_ >mailbox, < _function_ >callback) - _(void)_ - Gets the list of quota roots for `mailbox` and the resource usage and limits for each. `callback` has 2 parameters: < _Error_ >err, < _object_ >info. `info` is keyed on the quota root name, where the values are objects structured like `limits` given by getQuota(). Example `info`:
|
||||
|
||||
```javascript
|
||||
{
|
||||
'': {
|
||||
storage: { usage: 20480, limit: 102400 }
|
||||
},
|
||||
foo: {
|
||||
storage: { usage: 1024, limit: 4096 },
|
||||
message: { usage: 14, limit: 9001 }
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
* **RFC4315**
|
||||
|
||||
* Server capability: UIDPLUS
|
||||
|
||||
* The callback passed to append() will receive an additional argument (the UID of the appended message): < _integer_ >appendedUID.
|
||||
|
||||
* The callback passed to copy(), move(), seq.copy(), seq.move() will receive an additional argument (the UID(s) of the copied message(s) in the destination mailbox): < _mixed_ >newUIDs. `newUIDs` can be an integer if just one message was copied, or a string for multiple messages (e.g. '100:103' or '100,125,130' or '100,200:201').
|
||||
|
||||
* **RFC4551**
|
||||
|
||||
* Server capability: CONDSTORE
|
||||
|
||||
* Connection event 'update' info may contain the additional property:
|
||||
|
||||
* **modseq** - _string_ - The new modification sequence value for the message.
|
||||
|
||||
* search() criteria extensions:
|
||||
|
||||
* **MODSEQ** - _string_ - Modification sequence value. If this criteria is used, the callback parameters are then: < _Error_ >err, < _array_ >UIDs, < _string_ >modseq. The `modseq` callback parameter is the highest modification sequence value of all the messages identified in the search results.
|
||||
|
||||
* fetch() will automatically retrieve the modification sequence value (named 'modseq') for each message.
|
||||
|
||||
* fetch() modifier:
|
||||
|
||||
* **changedsince** - _string_ - Only fetch messages that have changed since the specified modification sequence.
|
||||
|
||||
* The _Box_ type can now have the following property when using openBox() or status():
|
||||
|
||||
* **highestmodseq** - _string_ - The highest modification sequence value of all messages in the mailbox.
|
||||
|
||||
* Additional Connection instance methods (seqno-based counterparts exist):
|
||||
|
||||
* **addFlagsSince**(< _MessageSource_ >source, < _mixed_ >flags, < _string_ >modseq, < _function_ >callback) - _(void)_ - Adds flag(s) to message(s) that have not changed since `modseq`. `flags` is either a single flag or an _array_ of flags. `callback` has 1 parameter: < _Error_ >err.
|
||||
|
||||
* **delFlagsSince**(< _MessageSource_ >source, < _mixed_ >flags, < _string_ >modseq, < _function_ >callback) - _(void)_ - Removes flag(s) from message(s) that have not changed since `modseq`. `flags` is either a single flag or an _array_ of flags. `callback` has 1 parameter: < _Error_ >err.
|
||||
|
||||
* **setFlagsSince**(< _MessageSource_ >source, < _mixed_ >flags, < _string_ >modseq, < _function_ >callback) - _(void)_ - Sets the flag(s) for message(s) that have not changed since `modseq`. `flags` is either a single flag or an _array_ of flags. `callback` has 1 parameter: < _Error_ >err.
|
||||
|
||||
* **addKeywordsSince**(< _MessageSource_ >source, < _mixed_ >keywords, < _string_ >modseq, < _function_ >callback) - _(void)_ - Adds keyword(s) to message(s) that have not changed since `modseq`. `keywords` is either a single keyword or an _array_ of keywords. `callback` has 1 parameter: < _Error_ >err.
|
||||
|
||||
* **delKeywordsSince**(< _MessageSource_ >source, < _mixed_ >keywords, < _string_ >modseq, < _function_ >callback) - _(void)_ - Removes keyword(s) from message(s) that have not changed since `modseq`. `keywords` is either a single keyword or an _array_ of keywords. `callback` has 1 parameter: < _Error_ >err.
|
||||
|
||||
* **setKeywordsSince**(< _MessageSource_ >source, < _mixed_ >keywords, < _string_ >modseq, < _function_ >callback) - _(void)_ - Sets keyword(s) for message(s) that have not changed since `modseq`. `keywords` is either a single keyword or an _array_ of keywords. `callback` has 1 parameter: < _Error_ >err.
|
||||
|
||||
* **RFC4731**
|
||||
|
||||
* Server capability: ESEARCH
|
||||
|
||||
* Additional Connection instance methods (seqno-based counterpart exists):
|
||||
|
||||
* **esearch**(< _array_ >criteria, < _array_ >options, < _function_ >callback) - _(void)_ - A variant of search() that can return metadata about results. `callback` has 2 parameters: < _Error_ >err, < _object_ >info. `info` has possible keys: 'all', 'min', 'max', 'count'. Valid `options`:
|
||||
|
||||
* 'ALL' - Retrieves UIDs in a compact form (e.g. [2, '10:11'] instead of search()'s [2, 10, 11]) that match the criteria.
|
||||
* 'MIN' - Retrieves the lowest UID that satisfies the criteria.
|
||||
* 'MAX' - Retrieves the highest UID that satisfies the criteria.
|
||||
* 'COUNT' - Retrieves the number of messages that satisfy the criteria.
|
||||
|
||||
**Note:** specifying no `options` or [] for `options` is the same as ['ALL']
|
||||
|
||||
* **RFC5256**
|
||||
|
||||
* Server capability: SORT
|
||||
|
||||
* Additional Connection instance methods (seqno-based counterpart exists):
|
||||
|
||||
* **sort**(< _array_ >sortCriteria, < _array_ >searchCriteria, < _function_ >callback) - _(void)_ - Performs a sorted search(). A seqno-based counterpart also exists for this function. `callback` has 2 parameters: < _Error_ >err, < _array_ >UIDs. Valid `sortCriteria` are (reverse sorting of individual criteria is done by prefixing the criteria with '-'):
|
||||
|
||||
* 'ARRIVAL' - Internal date and time of the message. This differs from the ON criteria in search(), which uses just the internal date.
|
||||
* 'CC' - The mailbox of the **first** "cc" address.
|
||||
* 'DATE' - Message sent date and time.
|
||||
* 'FROM' - The mailbox of the **first** "from" address.
|
||||
* 'SIZE' - Size of the message in octets.
|
||||
* 'SUBJECT' - Base subject text.
|
||||
* 'TO' - The mailbox of the **first** "to" address.
|
||||
|
||||
* Server capability: THREAD=REFERENCES, THREAD=ORDEREDSUBJECT
|
||||
|
||||
* Additional Connection instance methods (seqno-based counterpart exists):
|
||||
|
||||
* **thread**(< _string_ >algorithm, < _array_ >searchCriteria, < _function_ >callback) - _(void)_ - Performs a regular search with `searchCriteria` and groups the resulting search results using the given `algorithm` (e.g. 'references', 'orderedsubject'). `callback` has 2 parameters: < _Error_ >err, < _array_ >UIDs. `UIDs` is a nested array.
|
||||
|
||||
Applied Pull Requests
|
||||
=====================
|
||||
|
||||
- [#738](https://github.com/mscdex/node-imap/pull/738) Decode params
|
||||
- [#725](https://github.com/mscdex/node-imap/pull/725) Connection: Set TLS servername default to host
|
||||
- [#721](https://github.com/mscdex/node-imap/pull/721) added displayfrom and displayto search criteria
|
||||
- [#700](https://github.com/mscdex/node-imap/pull/700) Close connection is TLS error occur
|
||||
- [#648](https://github.com/mscdex/node-imap/pull/648) Connection: add leading zero to single digit date
|
||||
- [#641](https://github.com/mscdex/node-imap/pull/641) Convert the body to uppercase before parsing
|
||||
- [#613](https://github.com/mscdex/node-imap/pull/613) Fix regular expression for RE_PRECEDING
|
||||
- [#586](https://github.com/mscdex/node-imap/pull/586) Add utf7 decoding for Gmail labels
|
||||
- [#472](https://github.com/mscdex/node-imap/pull/472) Connection.js: socket needs to be set up in the case of tls
|
||||
- [#466](https://github.com/mscdex/node-imap/pull/466) Adding CRAM-MD5 server authentication
|
||||
- [#439](https://github.com/mscdex/node-imap/pull/439) Remove useless mail event with entire that counts entire box as new after openBox
|
||||
|
||||
|
||||
|
||||
|
||||
TODO
|
||||
----
|
||||
|
||||
Several things not yet implemented in no particular order:
|
||||
|
||||
* Support additional IMAP commands/extensions:
|
||||
* NOTIFY (via NOTIFY extension -- RFC5465)
|
||||
* STATUS addition to LIST (via LIST-STATUS extension -- RFC5819)
|
||||
* QRESYNC (RFC5162)
|
||||
73
test/imaps/node_modules/node-imap/deps/encoding/encoding-indexes.js
generated
vendored
Normal file
73
test/imaps/node_modules/node-imap/deps/encoding/encoding-indexes.js
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
2340
test/imaps/node_modules/node-imap/deps/encoding/encoding.js
generated
vendored
Normal file
2340
test/imaps/node_modules/node-imap/deps/encoding/encoding.js
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1717
test/imaps/node_modules/node-imap/lib/Connection.js
generated
vendored
Normal file
1717
test/imaps/node_modules/node-imap/lib/Connection.js
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1035
test/imaps/node_modules/node-imap/lib/Parser.js
generated
vendored
Normal file
1035
test/imaps/node_modules/node-imap/lib/Parser.js
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
367
test/imaps/node_modules/node-imap/lib/utils.js
generated
vendored
Normal file
367
test/imaps/node_modules/node-imap/lib/utils.js
generated
vendored
Normal file
@@ -0,0 +1,367 @@
|
||||
'use strict'
|
||||
|
||||
const RE_NUM_RANGE = /^(?:[\d]+|\*):(?:[\d]+|\*)$/,
|
||||
RE_BACKSLASH = /\\/g,
|
||||
RE_DBLQUOTE = /"/g,
|
||||
RE_INTEGER = /^\d+$/
|
||||
|
||||
module.exports.RE_NUM_RANGE = RE_NUM_RANGE
|
||||
|
||||
const MONTHS = ['Jan', 'Feb', 'Mar',
|
||||
'Apr', 'May', 'Jun',
|
||||
'Jul', 'Aug', 'Sep',
|
||||
'Oct', 'Nov', 'Dec']
|
||||
|
||||
module.exports.MONTH = MONTHS
|
||||
|
||||
// utilities -------------------------------------------------------------------
|
||||
|
||||
function escape(str) {
|
||||
return str.replace(RE_BACKSLASH, '\\\\').replace(RE_DBLQUOTE, '\\"')
|
||||
}
|
||||
|
||||
module.exports.escape = escape
|
||||
|
||||
function validateUIDList(uids, noThrow) {
|
||||
for (var i = 0, len = uids.length, intval; i < len; ++i) {
|
||||
if (typeof uids[i] === 'string') {
|
||||
if (uids[i] === '*' || uids[i] === '*:*') {
|
||||
if (len > 1)
|
||||
uids = ['*']
|
||||
break
|
||||
} else if (RE_NUM_RANGE.test(uids[i]))
|
||||
continue
|
||||
}
|
||||
intval = parseInt('' + uids[i], 10)
|
||||
if (isNaN(intval)) {
|
||||
const err = new Error('UID/seqno must be an integer, "*", or a range: '
|
||||
+ uids[i])
|
||||
if (noThrow)
|
||||
return err
|
||||
else
|
||||
throw err
|
||||
} else if (intval <= 0) {
|
||||
const err = new Error('UID/seqno must be greater than zero')
|
||||
if (noThrow)
|
||||
return err
|
||||
else
|
||||
throw err
|
||||
} else if (typeof uids[i] !== 'number') {
|
||||
uids[i] = intval
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports.validateUIDList = validateUIDList
|
||||
|
||||
function hasNonASCII(str) {
|
||||
for (var i = 0, len = str.length; i < len; ++i) {
|
||||
if (str.charCodeAt(i) > 0x7F)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
module.exports.hasNonASCII = hasNonASCII
|
||||
|
||||
function buildString(str) {
|
||||
if (typeof str !== 'string')
|
||||
str = '' + str
|
||||
|
||||
if (hasNonASCII(str)) {
|
||||
var buf = Buffer.from(str, 'utf8') //new Buffer(str, 'utf8');
|
||||
return '{' + buf.length + '}\r\n' + buf.toString('binary')
|
||||
} else
|
||||
return '"' + escape(str) + '"'
|
||||
}
|
||||
|
||||
module.exports.buildString = buildString
|
||||
|
||||
function buildSearchQuery(options, extensions, info, isOrChild) {
|
||||
let searchargs = ''
|
||||
// let err
|
||||
let val
|
||||
for (var i = 0, len = options.length; i < len; ++i) {
|
||||
var criteria = (isOrChild ? options : options[i]),
|
||||
args = null,
|
||||
modifier = (isOrChild ? '' : ' ')
|
||||
if (typeof criteria === 'string')
|
||||
criteria = criteria.toUpperCase()
|
||||
else if (Array.isArray(criteria)) {
|
||||
if (criteria.length > 1)
|
||||
args = criteria.slice(1)
|
||||
if (criteria.length > 0)
|
||||
criteria = criteria[0].toUpperCase()
|
||||
} else
|
||||
throw new Error('Unexpected search option data type. '
|
||||
+ 'Expected string or array. Got: ' + typeof criteria)
|
||||
if (criteria === 'OR') {
|
||||
if (args.length !== 2)
|
||||
throw new Error('OR must have exactly two arguments')
|
||||
if (isOrChild)
|
||||
searchargs += 'OR ('
|
||||
else
|
||||
searchargs += ' OR ('
|
||||
searchargs += buildSearchQuery(args[0], extensions, info, true)
|
||||
searchargs += ') ('
|
||||
searchargs += buildSearchQuery(args[1], extensions, info, true)
|
||||
searchargs += ')'
|
||||
} else {
|
||||
if (criteria[0] === '!') {
|
||||
modifier += 'NOT '
|
||||
criteria = criteria.substr(1)
|
||||
}
|
||||
switch (criteria) {
|
||||
// -- Standard criteria --
|
||||
case 'ALL':
|
||||
case 'ANSWERED':
|
||||
case 'DELETED':
|
||||
case 'DRAFT':
|
||||
case 'FLAGGED':
|
||||
case 'NEW':
|
||||
case 'SEEN':
|
||||
case 'RECENT':
|
||||
case 'OLD':
|
||||
case 'UNANSWERED':
|
||||
case 'UNDELETED':
|
||||
case 'UNDRAFT':
|
||||
case 'UNFLAGGED':
|
||||
case 'UNSEEN':
|
||||
searchargs += modifier + criteria
|
||||
break
|
||||
case 'BCC':
|
||||
case 'BODY':
|
||||
case 'CC':
|
||||
case 'FROM':
|
||||
case 'SUBJECT':
|
||||
case 'TEXT':
|
||||
case 'TO':
|
||||
if (!args || args.length !== 1)
|
||||
throw new Error('Incorrect number of arguments for search option: '
|
||||
+ criteria)
|
||||
val = buildString(args[0])
|
||||
if (info && val[0] === '{')
|
||||
info.hasUTF8 = true
|
||||
searchargs += modifier + criteria + ' ' + val
|
||||
break
|
||||
case 'BEFORE':
|
||||
case 'ON':
|
||||
case 'SENTBEFORE':
|
||||
case 'SENTON':
|
||||
case 'SENTSINCE':
|
||||
case 'SINCE':
|
||||
if (!args || args.length !== 1)
|
||||
throw new Error('Incorrect number of arguments for search option: '
|
||||
+ criteria)
|
||||
else if (!(args[0] instanceof Date)) {
|
||||
if ((args[0] = new Date(args[0])).toString() === 'Invalid Date')
|
||||
throw new Error('Search option argument must be a Date object'
|
||||
+ ' or a parseable date string')
|
||||
}
|
||||
searchargs += modifier + criteria + ' ' + args[0].getDate() + '-'
|
||||
+ MONTHS[args[0].getMonth()] + '-'
|
||||
+ args[0].getFullYear()
|
||||
break
|
||||
case 'KEYWORD':
|
||||
case 'UNKEYWORD':
|
||||
if (!args || args.length !== 1)
|
||||
throw new Error('Incorrect number of arguments for search option: '
|
||||
+ criteria)
|
||||
searchargs += modifier + criteria + ' ' + args[0]
|
||||
break
|
||||
case 'LARGER':
|
||||
case 'SMALLER':
|
||||
if (!args || args.length !== 1)
|
||||
throw new Error('Incorrect number of arguments for search option: '
|
||||
+ criteria)
|
||||
var num = parseInt(args[0], 10)
|
||||
if (isNaN(num))
|
||||
throw new Error('Search option argument must be a number')
|
||||
searchargs += modifier + criteria + ' ' + args[0]
|
||||
break
|
||||
case 'HEADER':
|
||||
if (!args || args.length !== 2)
|
||||
throw new Error('Incorrect number of arguments for search option: '
|
||||
+ criteria)
|
||||
val = buildString(args[1])
|
||||
if (info && val[0] === '{')
|
||||
info.hasUTF8 = true
|
||||
searchargs += modifier + criteria + ' "' + escape('' + args[0])
|
||||
+ '" ' + val
|
||||
break
|
||||
case 'UID':
|
||||
if (!args)
|
||||
throw new Error('Incorrect number of arguments for search option: '
|
||||
+ criteria)
|
||||
validateUIDList(args)
|
||||
if (args.length === 0)
|
||||
throw new Error('Empty uid list')
|
||||
searchargs += modifier + criteria + ' ' + args.join(',')
|
||||
break
|
||||
// Extensions ==========================================================
|
||||
case 'X-GM-MSGID': // Gmail unique message ID
|
||||
case 'X-GM-THRID': // Gmail thread ID
|
||||
if (extensions.indexOf('X-GM-EXT-1') === -1)
|
||||
throw new Error('IMAP extension not available for: ' + criteria)
|
||||
if (!args || args.length !== 1)
|
||||
throw new Error('Incorrect number of arguments for search option: '
|
||||
+ criteria)
|
||||
else {
|
||||
val = '' + args[0]
|
||||
if (!(RE_INTEGER.test(args[0])))
|
||||
throw new Error('Invalid value')
|
||||
}
|
||||
searchargs += modifier + criteria + ' ' + val
|
||||
break
|
||||
case 'X-GM-RAW': // Gmail search syntax
|
||||
if (extensions.indexOf('X-GM-EXT-1') === -1)
|
||||
throw new Error('IMAP extension not available for: ' + criteria)
|
||||
if (!args || args.length !== 1)
|
||||
throw new Error('Incorrect number of arguments for search option: '
|
||||
+ criteria)
|
||||
val = buildString(args[0])
|
||||
if (info && val[0] === '{')
|
||||
info.hasUTF8 = true
|
||||
searchargs += modifier + criteria + ' ' + val
|
||||
break
|
||||
case 'X-GM-LABELS': // Gmail labels
|
||||
if (extensions.indexOf('X-GM-EXT-1') === -1)
|
||||
throw new Error('IMAP extension not available for: ' + criteria)
|
||||
if (!args || args.length !== 1)
|
||||
throw new Error('Incorrect number of arguments for search option: '
|
||||
+ criteria)
|
||||
searchargs += modifier + criteria + ' ' + args[0]
|
||||
break
|
||||
case 'MODSEQ':
|
||||
if (extensions.indexOf('CONDSTORE') === -1)
|
||||
throw new Error('IMAP extension not available for: ' + criteria)
|
||||
if (!args || args.length !== 1)
|
||||
throw new Error('Incorrect number of arguments for search option: '
|
||||
+ criteria)
|
||||
searchargs += modifier + criteria + ' ' + args[0]
|
||||
break
|
||||
default:
|
||||
// last hope it's a seqno set
|
||||
// http://tools.ietf.org/html/rfc3501#section-6.4.4
|
||||
var seqnos = (args ? [criteria].concat(args) : [criteria])
|
||||
if (!validateUIDList(seqnos, true)) {
|
||||
if (seqnos.length === 0)
|
||||
throw new Error('Empty sequence number list')
|
||||
searchargs += modifier + seqnos.join(',')
|
||||
} else
|
||||
throw new Error('Unexpected search option: ' + criteria)
|
||||
}
|
||||
}
|
||||
if (isOrChild)
|
||||
break
|
||||
}
|
||||
return searchargs
|
||||
}
|
||||
|
||||
module.exports.buildSearchQuery = buildSearchQuery
|
||||
|
||||
// Pulled from assert.deepEqual:
|
||||
var pSlice = Array.prototype.slice
|
||||
function _deepEqual(actual, expected) {
|
||||
// 7.1. All identical values are equivalent, as determined by ===.
|
||||
if (actual === expected) {
|
||||
return true
|
||||
|
||||
} else if (Buffer.isBuffer(actual) && Buffer.isBuffer(expected)) {
|
||||
if (actual.length !== expected.length) return false
|
||||
|
||||
for (var i = 0; i < actual.length; i++) {
|
||||
if (actual[i] !== expected[i]) return false
|
||||
}
|
||||
|
||||
return true
|
||||
|
||||
// 7.2. If the expected value is a Date object, the actual value is
|
||||
// equivalent if it is also a Date object that refers to the same time.
|
||||
} else if (actual instanceof Date && expected instanceof Date) {
|
||||
return actual.getTime() === expected.getTime()
|
||||
|
||||
// 7.3 If the expected value is a RegExp object, the actual value is
|
||||
// equivalent if it is also a RegExp object with the same source and
|
||||
// properties (`global`, `multiline`, `lastIndex`, `ignoreCase`).
|
||||
} else if (actual instanceof RegExp && expected instanceof RegExp) {
|
||||
return actual.source === expected.source &&
|
||||
actual.global === expected.global &&
|
||||
actual.multiline === expected.multiline &&
|
||||
actual.lastIndex === expected.lastIndex &&
|
||||
actual.ignoreCase === expected.ignoreCase
|
||||
|
||||
// 7.4. Other pairs that do not both pass typeof value == 'object',
|
||||
// equivalence is determined by ==.
|
||||
} else if (typeof actual !== 'object' && typeof expected !== 'object') {
|
||||
return actual == expected
|
||||
|
||||
// 7.5 For all other Object pairs, including Array objects, equivalence is
|
||||
// determined by having the same number of owned properties (as verified
|
||||
// with Object.prototype.hasOwnProperty.call), the same set of keys
|
||||
// (although not necessarily the same order), equivalent values for every
|
||||
// corresponding key, and an identical 'prototype' property. Note: this
|
||||
// accounts for both named and indexed properties on Arrays.
|
||||
} else {
|
||||
return objEquiv(actual, expected)
|
||||
}
|
||||
}
|
||||
|
||||
module.exports._deepEqual = _deepEqual
|
||||
|
||||
function isUndefinedOrNull(value) {
|
||||
return value === null || value === undefined
|
||||
}
|
||||
|
||||
module.exports.isUndefinedOrNull = isUndefinedOrNull
|
||||
|
||||
function isArguments(object) {
|
||||
return Object.prototype.toString.call(object) === '[object Arguments]'
|
||||
}
|
||||
|
||||
module.exports.isArguments = isArguments
|
||||
|
||||
function objEquiv(a, b) {
|
||||
var ka, kb, key, i
|
||||
if (isUndefinedOrNull(a) || isUndefinedOrNull(b))
|
||||
return false
|
||||
// an identical 'prototype' property.
|
||||
if (a.prototype !== b.prototype) return false
|
||||
//~~~I've managed to break Object.keys through screwy arguments passing.
|
||||
// Converting to array solves the problem.
|
||||
if (isArguments(a)) {
|
||||
if (!isArguments(b)) {
|
||||
return false
|
||||
}
|
||||
a = pSlice.call(a)
|
||||
b = pSlice.call(b)
|
||||
return _deepEqual(a, b)
|
||||
}
|
||||
try {
|
||||
ka = Object.keys(a)
|
||||
kb = Object.keys(b)
|
||||
} catch (e) {//happens when one is a string literal and the other isn't
|
||||
return false
|
||||
}
|
||||
// having the same number of owned properties (keys incorporates
|
||||
// hasOwnProperty)
|
||||
if (ka.length !== kb.length)
|
||||
return false
|
||||
//the same set of keys (although not necessarily the same order),
|
||||
ka.sort()
|
||||
kb.sort()
|
||||
//~~~cheap key test
|
||||
for (i = ka.length - 1; i >= 0; i--) {
|
||||
if (ka[i] != kb[i])
|
||||
return false
|
||||
}
|
||||
//equivalent values for every corresponding key, and
|
||||
//~~~possibly expensive deep test
|
||||
for (i = ka.length - 1; i >= 0; i--) {
|
||||
key = ka[i]
|
||||
if (!_deepEqual(a[key], b[key])) return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
module.exports.objEquiv = objEquiv
|
||||
44
test/imaps/node_modules/node-imap/package.json
generated
vendored
Normal file
44
test/imaps/node_modules/node-imap/package.json
generated
vendored
Normal file
@@ -0,0 +1,44 @@
|
||||
{
|
||||
"name": "node-imap",
|
||||
"version": "0.9.6",
|
||||
"author": "Brian White <mscdex@mscdex.net>",
|
||||
"contributors": [
|
||||
{
|
||||
"email": "michael.bevz@gmail.com",
|
||||
"name": "Michael Bevz"
|
||||
}
|
||||
],
|
||||
"description": "A fork of the famous and outdated IMAP module for node.js that makes communicating with IMAP servers easy",
|
||||
"main": "./lib/Connection",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"utf7": "^1.0.2",
|
||||
"readable-stream": "^3.6.0"
|
||||
},
|
||||
"scripts": {
|
||||
"test": "node test/test.js"
|
||||
},
|
||||
"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": "https://github.com/mikebevz/node-imap"
|
||||
},
|
||||
"devDependencies": {
|
||||
"eslint": "^7.1.0"
|
||||
}
|
||||
}
|
||||
92
test/imaps/node_modules/node-imap/test/test-connection-fetch-dup.js
generated
vendored
Normal file
92
test/imaps/node_modules/node-imap/test/test-connection-fetch-dup.js
generated
vendored
Normal file
@@ -0,0 +1,92 @@
|
||||
var assert = require('assert'),
|
||||
net = require('net'),
|
||||
Imap = require('../lib/Connection'),
|
||||
result
|
||||
|
||||
var CRLF = '\r\n'
|
||||
|
||||
var RESPONSES = [
|
||||
['* CAPABILITY IMAP4rev1 UNSELECT IDLE NAMESPACE QUOTA CHILDREN',
|
||||
'A0 OK Thats all she wrote!',
|
||||
''
|
||||
].join(CRLF),
|
||||
['* CAPABILITY IMAP4rev1 UNSELECT IDLE NAMESPACE QUOTA CHILDREN UIDPLUS MOVE',
|
||||
'A1 OK authenticated (Success)',
|
||||
''
|
||||
].join(CRLF),
|
||||
['* NAMESPACE (("" "/")) NIL NIL',
|
||||
'A2 OK Success',
|
||||
''
|
||||
].join(CRLF),
|
||||
['* LIST (\\Noselect) "/" "/"',
|
||||
'A3 OK Success',
|
||||
''
|
||||
].join(CRLF),
|
||||
['* FLAGS (\\Answered \\Flagged \\Draft \\Deleted \\Seen)',
|
||||
'* OK [PERMANENTFLAGS ()] Flags permitted.',
|
||||
'* OK [UIDVALIDITY 2] UIDs valid.',
|
||||
'* 685 EXISTS',
|
||||
'* 0 RECENT',
|
||||
'* OK [UIDNEXT 4422] Predicted next UID.',
|
||||
'A4 OK [READ-ONLY] INBOX selected. (Success)',
|
||||
''
|
||||
].join(CRLF),
|
||||
['* 1 FETCH (UID 1)',
|
||||
'* 1 FETCH (INTERNALDATE "05-Sep-2004 00:38:03 +0000" UID 1000)',
|
||||
'* 1 FETCH (FLAGS (\\Seen))',
|
||||
'A5 OK Success',
|
||||
''
|
||||
].join(CRLF),
|
||||
['* BYE LOGOUT Requested',
|
||||
'A6 OK good day (Success)',
|
||||
''
|
||||
].join(CRLF)
|
||||
]
|
||||
|
||||
const srv = net.createServer(function (sock) {
|
||||
sock.write('* OK asdf\r\n')
|
||||
var buf = '', lines
|
||||
sock.on('data', function (data) {
|
||||
buf += data.toString('utf8')
|
||||
if (buf.indexOf(CRLF) > -1) {
|
||||
lines = buf.split(CRLF)
|
||||
buf = lines.pop()
|
||||
lines.forEach(function () {
|
||||
sock.write(RESPONSES.shift())
|
||||
})
|
||||
}
|
||||
})
|
||||
})
|
||||
srv.listen(0, '127.0.0.1', function () {
|
||||
var port = srv.address().port
|
||||
var imap = new Imap({
|
||||
user: 'foo',
|
||||
password: 'bar',
|
||||
host: '127.0.0.1',
|
||||
port: port,
|
||||
keepalive: false
|
||||
})
|
||||
imap.on('ready', function () {
|
||||
imap.openBox('INBOX', true, function () {
|
||||
var f = imap.seq.fetch(1)
|
||||
f.on('message', function (m) {
|
||||
m.once('attributes', function (attrs) {
|
||||
result = attrs
|
||||
})
|
||||
})
|
||||
f.on('end', function () {
|
||||
srv.close()
|
||||
imap.end()
|
||||
})
|
||||
})
|
||||
})
|
||||
imap.connect()
|
||||
})
|
||||
|
||||
process.once('exit', function () {
|
||||
assert.deepEqual(result, {
|
||||
uid: 1,
|
||||
date: new Date('05-Sep-2004 00:38:03 +0000'),
|
||||
flags: ['\\Seen']
|
||||
})
|
||||
})
|
||||
92
test/imaps/node_modules/node-imap/test/test-connection-fetch-frag.js
generated
vendored
Normal file
92
test/imaps/node_modules/node-imap/test/test-connection-fetch-frag.js
generated
vendored
Normal file
@@ -0,0 +1,92 @@
|
||||
var assert = require('assert'),
|
||||
net = require('net'),
|
||||
Imap = require('../lib/Connection'),
|
||||
result;
|
||||
|
||||
var CRLF = '\r\n';
|
||||
|
||||
var RESPONSES = [
|
||||
['* CAPABILITY IMAP4rev1 UNSELECT IDLE NAMESPACE QUOTA CHILDREN',
|
||||
'A0 OK Thats all she wrote!',
|
||||
''
|
||||
].join(CRLF),
|
||||
['* CAPABILITY IMAP4rev1 UNSELECT IDLE NAMESPACE QUOTA CHILDREN UIDPLUS MOVE',
|
||||
'A1 OK authenticated (Success)',
|
||||
''
|
||||
].join(CRLF),
|
||||
['* NAMESPACE (("" "/")) NIL NIL',
|
||||
'A2 OK Success',
|
||||
''
|
||||
].join(CRLF),
|
||||
['* LIST (\\Noselect) "/" "/"',
|
||||
'A3 OK Success',
|
||||
''
|
||||
].join(CRLF),
|
||||
['* FLAGS (\\Answered \\Flagged \\Draft \\Deleted \\Seen)',
|
||||
'* OK [PERMANENTFLAGS ()] Flags permitted.',
|
||||
'* OK [UIDVALIDITY 2] UIDs valid.',
|
||||
'* 685 EXISTS',
|
||||
'* 0 RECENT',
|
||||
'* OK [UIDNEXT 4422] Predicted next UID.',
|
||||
'A4 OK [READ-ONLY] INBOX selected. (Success)',
|
||||
''
|
||||
].join(CRLF),
|
||||
['* 1 FETCH (UID 1)',
|
||||
'* 1 FETCH (INTERNALDATE "05-Sep-2004 00:38:03 +0000")',
|
||||
'* 1 FETCH (FLAGS (\\Seen))',
|
||||
'A5 OK Success',
|
||||
''
|
||||
].join(CRLF),
|
||||
['* BYE LOGOUT Requested',
|
||||
'A6 OK good day (Success)',
|
||||
''
|
||||
].join(CRLF)
|
||||
];
|
||||
|
||||
var srv = net.createServer(function(sock) {
|
||||
sock.write('* OK asdf\r\n');
|
||||
var buf = '', lines;
|
||||
sock.on('data', function(data) {
|
||||
buf += data.toString('utf8');
|
||||
if (buf.indexOf(CRLF) > -1) {
|
||||
lines = buf.split(CRLF);
|
||||
buf = lines.pop();
|
||||
lines.forEach(function() {
|
||||
sock.write(RESPONSES.shift());
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
srv.listen(0, '127.0.0.1', function() {
|
||||
var port = srv.address().port;
|
||||
var imap = new Imap({
|
||||
user: 'foo',
|
||||
password: 'bar',
|
||||
host: '127.0.0.1',
|
||||
port: port,
|
||||
keepalive: false
|
||||
});
|
||||
imap.on('ready', function() {
|
||||
imap.openBox('INBOX', true, function() {
|
||||
var f = imap.seq.fetch(1);
|
||||
f.on('message', function(m) {
|
||||
m.once('attributes', function(attrs) {
|
||||
result = attrs;
|
||||
});
|
||||
});
|
||||
f.on('end', function() {
|
||||
srv.close();
|
||||
imap.end();
|
||||
});
|
||||
});
|
||||
});
|
||||
imap.connect();
|
||||
});
|
||||
|
||||
process.once('exit', function() {
|
||||
assert.deepEqual(result, {
|
||||
uid: 1,
|
||||
date: new Date('05-Sep-2004 00:38:03 +0000'),
|
||||
flags: [ '\\Seen' ]
|
||||
});
|
||||
});
|
||||
176
test/imaps/node_modules/node-imap/test/test-connection-fetch-spillover.js
generated
vendored
Normal file
176
test/imaps/node_modules/node-imap/test/test-connection-fetch-spillover.js
generated
vendored
Normal file
@@ -0,0 +1,176 @@
|
||||
// Test for _at least_ GH Issues #345, #379, #392, #411
|
||||
|
||||
var assert = require('assert'),
|
||||
net = require('net'),
|
||||
crypto = require('crypto'),
|
||||
Imap = require('../lib/Connection');
|
||||
|
||||
var result = [],
|
||||
body = [],
|
||||
bodyInfo = [];
|
||||
|
||||
var CRLF = '\r\n';
|
||||
|
||||
// generate data larger than highWaterMark
|
||||
var bytes = crypto.pseudoRandomBytes(10240).toString('hex');
|
||||
|
||||
var RESPONSES = [
|
||||
['* CAPABILITY IMAP4rev1 UNSELECT IDLE NAMESPACE QUOTA CHILDREN',
|
||||
'A0 OK Thats all she wrote!',
|
||||
''
|
||||
].join(CRLF),
|
||||
['* CAPABILITY IMAP4rev1 UNSELECT IDLE NAMESPACE QUOTA CHILDREN UIDPLUS MOVE',
|
||||
'A1 OK authenticated (Success)',
|
||||
''
|
||||
].join(CRLF),
|
||||
['* NAMESPACE (("" "/")) NIL NIL',
|
||||
'A2 OK Success',
|
||||
''
|
||||
].join(CRLF),
|
||||
['* LIST (\\Noselect) "/" "/"',
|
||||
'A3 OK Success',
|
||||
''
|
||||
].join(CRLF),
|
||||
['* FLAGS (\\Answered \\Flagged \\Draft \\Deleted \\Seen)',
|
||||
'* OK [PERMANENTFLAGS ()] Flags permitted.',
|
||||
'* OK [UIDVALIDITY 2] UIDs valid.',
|
||||
'* 685 EXISTS',
|
||||
'* 0 RECENT',
|
||||
'* OK [UIDNEXT 4422] Predicted next UID.',
|
||||
'A4 OK [READ-ONLY] INBOX selected. (Success)',
|
||||
''
|
||||
].join(CRLF),
|
||||
'* 1 FETCH (UID 1000 FLAGS (\\Seen) INTERNALDATE "05-Sep-2004 00:38:03 +0000" BODY[TEXT] {'
|
||||
+ bytes.length
|
||||
+ '}'
|
||||
+ CRLF
|
||||
+ bytes.substring(0, 20000),
|
||||
['* BYE LOGOUT Requested',
|
||||
'A6 OK good day (Success)',
|
||||
''
|
||||
].join(CRLF)
|
||||
];
|
||||
var EXPECTED = [
|
||||
'A0 CAPABILITY',
|
||||
'A1 LOGIN "foo" "bar"',
|
||||
'A2 NAMESPACE',
|
||||
'A3 LIST "" ""',
|
||||
'A4 EXAMINE "INBOX"',
|
||||
'A5 FETCH 1,2 (UID FLAGS INTERNALDATE BODY.PEEK[TEXT])',
|
||||
'A6 LOGOUT'
|
||||
];
|
||||
|
||||
var exp = -1,
|
||||
res = -1;
|
||||
|
||||
var srv = net.createServer(function(sock) {
|
||||
sock.write('* OK asdf\r\n');
|
||||
var buf = '', lines;
|
||||
sock.on('data', function(data) {
|
||||
buf += data.toString('utf8');
|
||||
if (buf.indexOf(CRLF) > -1) {
|
||||
lines = buf.split(CRLF);
|
||||
buf = lines.pop();
|
||||
lines.forEach(function(l) {
|
||||
assert(l === EXPECTED[++exp], 'Unexpected client request: ' + l);
|
||||
assert(RESPONSES[++res], 'No response for client request: ' + l);
|
||||
sock.write(RESPONSES[res]);
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
srv.listen(0, '127.0.0.1', function() {
|
||||
var port = srv.address().port;
|
||||
var imap = new Imap({
|
||||
user: 'foo',
|
||||
password: 'bar',
|
||||
host: '127.0.0.1',
|
||||
port: port,
|
||||
keepalive: false
|
||||
});
|
||||
imap.on('ready', function() {
|
||||
srv.close();
|
||||
imap.openBox('INBOX', true, function() {
|
||||
var f = imap.seq.fetch([1,2], { bodies: ['TEXT'] });
|
||||
var nbody = -1;
|
||||
f.on('message', function(m) {
|
||||
m.on('body', function(stream, info) {
|
||||
++nbody;
|
||||
bodyInfo.push(info);
|
||||
body[nbody] = '';
|
||||
if (nbody === 0) {
|
||||
// first allow body.push() to return false in parser.js
|
||||
setTimeout(function() {
|
||||
stream.on('data', function(chunk) {
|
||||
body[nbody] += chunk.toString('binary');
|
||||
});
|
||||
setTimeout(function() {
|
||||
var oldRead = stream._read,
|
||||
readCalled = false;
|
||||
stream._read = function(n) {
|
||||
readCalled = true;
|
||||
stream._read = oldRead;
|
||||
imap._sock.push(bytes.substring(100, 200)
|
||||
+ ')'
|
||||
+ CRLF
|
||||
+ 'A5 OK Success'
|
||||
+ CRLF);
|
||||
imap._parser._tryread();
|
||||
};
|
||||
imap._sock.push(bytes.substring(20000)
|
||||
+ ')'
|
||||
+ CRLF
|
||||
+ '* 2 FETCH (UID 1001 FLAGS (\\Seen) INTERNALDATE "05-Sep-2004 00:38:13 +0000" BODY[TEXT] {200}'
|
||||
+ CRLF
|
||||
+ bytes.substring(0, 100));
|
||||
|
||||
// if we got this far, then we didn't get an exception and we
|
||||
// are running with the bug fix in place
|
||||
if (!readCalled) {
|
||||
imap._sock.push(bytes.substring(100, 200)
|
||||
+ ')'
|
||||
+ CRLF
|
||||
+ 'A5 OK Success'
|
||||
+ CRLF);
|
||||
}
|
||||
}, 100);
|
||||
}, 100);
|
||||
} else {
|
||||
stream.on('data', function(chunk) {
|
||||
body[nbody] += chunk.toString('binary');
|
||||
});
|
||||
}
|
||||
});
|
||||
m.on('attributes', function(attrs) {
|
||||
result.push(attrs);
|
||||
});
|
||||
});
|
||||
f.on('end', function() {
|
||||
imap.end();
|
||||
});
|
||||
});
|
||||
});
|
||||
imap.connect();
|
||||
});
|
||||
|
||||
process.once('exit', function() {
|
||||
assert.deepEqual(result, [{
|
||||
uid: 1000,
|
||||
date: new Date('05-Sep-2004 00:38:03 +0000'),
|
||||
flags: [ '\\Seen' ]
|
||||
}, {
|
||||
uid: 1001,
|
||||
date: new Date('05-Sep-2004 00:38:13 +0000'),
|
||||
flags: [ '\\Seen' ]
|
||||
}]);
|
||||
assert.deepEqual(body, [bytes, bytes.substring(0, 200)]);
|
||||
assert.deepEqual(bodyInfo, [{
|
||||
seqno: 1,
|
||||
which: 'TEXT',
|
||||
size: bytes.length
|
||||
}, {
|
||||
seqno: 2,
|
||||
which: 'TEXT',
|
||||
size: 200
|
||||
}]);
|
||||
});
|
||||
104
test/imaps/node_modules/node-imap/test/test-connection-fetch-stringbody.js
generated
vendored
Normal file
104
test/imaps/node_modules/node-imap/test/test-connection-fetch-stringbody.js
generated
vendored
Normal file
@@ -0,0 +1,104 @@
|
||||
var assert = require('assert'),
|
||||
net = require('net'),
|
||||
Imap = require('../lib/Connection');
|
||||
|
||||
var result, body = '', bodyInfo;
|
||||
|
||||
var CRLF = '\r\n';
|
||||
|
||||
var RESPONSES = [
|
||||
['* CAPABILITY IMAP4rev1 UNSELECT IDLE NAMESPACE QUOTA CHILDREN',
|
||||
'A0 OK Thats all she wrote!',
|
||||
''
|
||||
].join(CRLF),
|
||||
['* CAPABILITY IMAP4rev1 UNSELECT IDLE NAMESPACE QUOTA CHILDREN UIDPLUS MOVE',
|
||||
'A1 OK authenticated (Success)',
|
||||
''
|
||||
].join(CRLF),
|
||||
['* NAMESPACE (("" "/")) NIL NIL',
|
||||
'A2 OK Success',
|
||||
''
|
||||
].join(CRLF),
|
||||
['* LIST (\\Noselect) "/" "/"',
|
||||
'A3 OK Success',
|
||||
''
|
||||
].join(CRLF),
|
||||
['* FLAGS (\\Answered \\Flagged \\Draft \\Deleted \\Seen)',
|
||||
'* OK [PERMANENTFLAGS ()] Flags permitted.',
|
||||
'* OK [UIDVALIDITY 2] UIDs valid.',
|
||||
'* 685 EXISTS',
|
||||
'* 0 RECENT',
|
||||
'* OK [UIDNEXT 4422] Predicted next UID.',
|
||||
'A4 OK [READ-ONLY] INBOX selected. (Success)',
|
||||
''
|
||||
].join(CRLF),
|
||||
['* 1 FETCH (UID 1)',
|
||||
'* 1 FETCH (INTERNALDATE "05-Sep-2004 00:38:03 +0000" UID 1000)',
|
||||
'* 1 FETCH (BODY[TEXT] "IMAP is terrible")',
|
||||
'* 1 FETCH (FLAGS (\\Seen))',
|
||||
'A5 OK Success',
|
||||
''
|
||||
].join(CRLF),
|
||||
['* BYE LOGOUT Requested',
|
||||
'A6 OK good day (Success)',
|
||||
''
|
||||
].join(CRLF)
|
||||
];
|
||||
|
||||
var srv = net.createServer(function(sock) {
|
||||
sock.write('* OK asdf\r\n');
|
||||
var buf = '', lines;
|
||||
sock.on('data', function(data) {
|
||||
buf += data.toString('utf8');
|
||||
if (buf.indexOf(CRLF) > -1) {
|
||||
lines = buf.split(CRLF);
|
||||
buf = lines.pop();
|
||||
lines.forEach(function() {
|
||||
sock.write(RESPONSES.shift());
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
srv.listen(0, '127.0.0.1', function() {
|
||||
var port = srv.address().port;
|
||||
var imap = new Imap({
|
||||
user: 'foo',
|
||||
password: 'bar',
|
||||
host: '127.0.0.1',
|
||||
port: port,
|
||||
keepalive: false
|
||||
});
|
||||
imap.on('ready', function() {
|
||||
imap.openBox('INBOX', true, function() {
|
||||
var f = imap.seq.fetch(1, { bodies: ['TEXT'] });
|
||||
f.on('message', function(m) {
|
||||
m.on('body', function(stream, info) {
|
||||
bodyInfo = info;
|
||||
stream.on('data', function(chunk) { body += chunk.toString('utf8'); });
|
||||
});
|
||||
m.on('attributes', function(attrs) {
|
||||
result = attrs;
|
||||
});
|
||||
});
|
||||
f.on('end', function() {
|
||||
srv.close();
|
||||
imap.end();
|
||||
});
|
||||
});
|
||||
});
|
||||
imap.connect();
|
||||
});
|
||||
|
||||
process.once('exit', function() {
|
||||
assert.deepEqual(result, {
|
||||
uid: 1,
|
||||
date: new Date('05-Sep-2004 00:38:03 +0000'),
|
||||
flags: [ '\\Seen' ]
|
||||
});
|
||||
assert.equal(body, 'IMAP is terrible');
|
||||
assert.deepEqual(bodyInfo, {
|
||||
seqno: 1,
|
||||
which: 'TEXT',
|
||||
size: 16
|
||||
});
|
||||
});
|
||||
144
test/imaps/node_modules/node-imap/test/test-connection-idle-normal.js
generated
vendored
Normal file
144
test/imaps/node_modules/node-imap/test/test-connection-idle-normal.js
generated
vendored
Normal file
@@ -0,0 +1,144 @@
|
||||
var assert = require('assert'),
|
||||
net = require('net'),
|
||||
Imap = require('../lib/Connection');
|
||||
|
||||
var result, body = '', bodyInfo;
|
||||
|
||||
var CRLF = '\r\n';
|
||||
|
||||
var RESPONSES = [
|
||||
['* CAPABILITY IMAP4rev1 UNSELECT IDLE NAMESPACE QUOTA CHILDREN',
|
||||
'A0 OK Thats all she wrote!',
|
||||
''
|
||||
].join(CRLF),
|
||||
['* CAPABILITY IMAP4rev1 UNSELECT IDLE NAMESPACE QUOTA CHILDREN UIDPLUS MOVE',
|
||||
'A1 OK authenticated (Success)',
|
||||
''
|
||||
].join(CRLF),
|
||||
['* NAMESPACE (("" "/")) NIL NIL',
|
||||
'A2 OK Success',
|
||||
''
|
||||
].join(CRLF),
|
||||
['* LIST (\\Noselect) "/" "/"',
|
||||
'A3 OK Success',
|
||||
''
|
||||
].join(CRLF),
|
||||
['* FLAGS (\\Answered \\Flagged \\Draft \\Deleted \\Seen)',
|
||||
'* OK [PERMANENTFLAGS ()] Flags permitted.',
|
||||
'* OK [UIDVALIDITY 2] UIDs valid.',
|
||||
'* 685 EXISTS',
|
||||
'* 0 RECENT',
|
||||
'* OK [UIDNEXT 4422] Predicted next UID.',
|
||||
'A4 OK [READ-ONLY] INBOX selected. (Success)',
|
||||
''
|
||||
].join(CRLF),
|
||||
['* 1 FETCH (UID 1)',
|
||||
'* 1 FETCH (INTERNALDATE "05-Sep-2004 00:38:03 +0000" UID 1000)',
|
||||
'* 1 FETCH (BODY[TEXT] "IMAP is terrible")',
|
||||
'* 1 FETCH (FLAGS (\\Seen))',
|
||||
'A5 OK Success',
|
||||
''
|
||||
].join(CRLF),
|
||||
['* STATUS test (MESSAGES 231 RECENT 0 UNSEEN 0 UIDVALIDITY 123 UIDNEXT 442)',
|
||||
'A6 OK STATUS completed',
|
||||
''
|
||||
].join(CRLF),
|
||||
['* BYE LOGOUT Requested',
|
||||
'A7 OK good day (Success)',
|
||||
''
|
||||
].join(CRLF)
|
||||
];
|
||||
var EXPECTED = [
|
||||
'A0 CAPABILITY',
|
||||
'A1 LOGIN "foo" "bar"',
|
||||
'A2 NAMESPACE',
|
||||
'A3 LIST "" ""',
|
||||
'A4 EXAMINE "INBOX"',
|
||||
'A5 FETCH 1 (UID FLAGS INTERNALDATE BODY.PEEK[TEXT])',
|
||||
'IDLE IDLE',
|
||||
'DONE',
|
||||
'A6 STATUS "test" (MESSAGES RECENT UNSEEN UIDVALIDITY UIDNEXT)',
|
||||
'A7 LOGOUT'
|
||||
];
|
||||
|
||||
var exp = -1,
|
||||
res = -1,
|
||||
sentCont = false;
|
||||
|
||||
var srv = net.createServer(function(sock) {
|
||||
sock.write('* OK asdf\r\n');
|
||||
var buf = '', lines;
|
||||
sock.on('data', function(data) {
|
||||
buf += data.toString('utf8');
|
||||
if (buf.indexOf(CRLF) > -1) {
|
||||
lines = buf.split(CRLF);
|
||||
buf = lines.pop();
|
||||
lines.forEach(function(l) {
|
||||
assert(l === EXPECTED[++exp], 'Unexpected client request: ' + l);
|
||||
if (l === 'DONE') {
|
||||
assert(sentCont, 'DONE seen before continuation sent');
|
||||
sock.write('IDLE ok\r\n');
|
||||
} else if (l === 'IDLE IDLE') {
|
||||
setTimeout(function() {
|
||||
sentCont = true;
|
||||
sock.write('+ idling\r\n');
|
||||
}, 100);
|
||||
} else {
|
||||
assert(RESPONSES[++res], 'No response for client request: ' + l);
|
||||
sock.write(RESPONSES[res]);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
srv.listen(0, '127.0.0.1', function() {
|
||||
var port = srv.address().port;
|
||||
var imap = new Imap({
|
||||
user: 'foo',
|
||||
password: 'bar',
|
||||
host: '127.0.0.1',
|
||||
port: port,
|
||||
keepalive: true
|
||||
});
|
||||
imap.on('ready', function() {
|
||||
srv.close();
|
||||
imap.openBox('INBOX', true, function() {
|
||||
var f = imap.seq.fetch(1, { bodies: ['TEXT'] });
|
||||
f.on('message', function(m) {
|
||||
m.on('body', function(stream, info) {
|
||||
bodyInfo = info;
|
||||
stream.on('data', function(chunk) { body += chunk.toString('utf8'); });
|
||||
});
|
||||
m.on('attributes', function(attrs) {
|
||||
result = attrs;
|
||||
});
|
||||
});
|
||||
f.on('end', function() {
|
||||
setTimeout(function() {
|
||||
var timeout = setTimeout(function() {
|
||||
assert(false, 'Timed out waiting for STATUS');
|
||||
}, 500);
|
||||
imap.status('test', function(err, status) {
|
||||
clearTimeout(timeout);
|
||||
imap.end();
|
||||
});
|
||||
}, 500);
|
||||
});
|
||||
});
|
||||
});
|
||||
imap.connect();
|
||||
});
|
||||
|
||||
process.once('exit', function() {
|
||||
assert.deepEqual(result, {
|
||||
uid: 1,
|
||||
date: new Date('05-Sep-2004 00:38:03 +0000'),
|
||||
flags: [ '\\Seen' ]
|
||||
});
|
||||
assert.equal(body, 'IMAP is terrible');
|
||||
assert.deepEqual(bodyInfo, {
|
||||
seqno: 1,
|
||||
which: 'TEXT',
|
||||
size: 16
|
||||
});
|
||||
});
|
||||
138
test/imaps/node_modules/node-imap/test/test-connection-idle-order.js
generated
vendored
Normal file
138
test/imaps/node_modules/node-imap/test/test-connection-idle-order.js
generated
vendored
Normal file
@@ -0,0 +1,138 @@
|
||||
var assert = require('assert'),
|
||||
net = require('net'),
|
||||
Imap = require('../lib/Connection');
|
||||
|
||||
var result, body = '', bodyInfo;
|
||||
|
||||
var CRLF = '\r\n';
|
||||
|
||||
var RESPONSES = [
|
||||
['* CAPABILITY IMAP4rev1 UNSELECT IDLE NAMESPACE QUOTA CHILDREN',
|
||||
'A0 OK Thats all she wrote!',
|
||||
''
|
||||
].join(CRLF),
|
||||
['* CAPABILITY IMAP4rev1 UNSELECT IDLE NAMESPACE QUOTA CHILDREN UIDPLUS MOVE',
|
||||
'A1 OK authenticated (Success)',
|
||||
''
|
||||
].join(CRLF),
|
||||
['* NAMESPACE (("" "/")) NIL NIL',
|
||||
'A2 OK Success',
|
||||
''
|
||||
].join(CRLF),
|
||||
['* LIST (\\Noselect) "/" "/"',
|
||||
'A3 OK Success',
|
||||
''
|
||||
].join(CRLF),
|
||||
['* FLAGS (\\Answered \\Flagged \\Draft \\Deleted \\Seen)',
|
||||
'* OK [PERMANENTFLAGS ()] Flags permitted.',
|
||||
'* OK [UIDVALIDITY 2] UIDs valid.',
|
||||
'* 685 EXISTS',
|
||||
'* 0 RECENT',
|
||||
'* OK [UIDNEXT 4422] Predicted next UID.',
|
||||
'A4 OK [READ-ONLY] INBOX selected. (Success)',
|
||||
''
|
||||
].join(CRLF),
|
||||
['* 1 FETCH (UID 1)',
|
||||
'* 1 FETCH (INTERNALDATE "05-Sep-2004 00:38:03 +0000" UID 1000)',
|
||||
'* 1 FETCH (BODY[TEXT] "IMAP is terrible")',
|
||||
'* 1 FETCH (FLAGS (\\Seen))',
|
||||
'A5 OK Success',
|
||||
''
|
||||
].join(CRLF),
|
||||
['* STATUS test (MESSAGES 231 RECENT 0 UNSEEN 0 UIDVALIDITY 123 UIDNEXT 442)',
|
||||
'A6 OK STATUS completed',
|
||||
''
|
||||
].join(CRLF),
|
||||
['* BYE LOGOUT Requested',
|
||||
'A7 OK good day (Success)',
|
||||
''
|
||||
].join(CRLF)
|
||||
];
|
||||
var EXPECTED = [
|
||||
'A0 CAPABILITY',
|
||||
'A1 LOGIN "foo" "bar"',
|
||||
'A2 NAMESPACE',
|
||||
'A3 LIST "" ""',
|
||||
'A4 EXAMINE "INBOX"',
|
||||
'A5 FETCH 1 (UID FLAGS INTERNALDATE BODY.PEEK[TEXT])',
|
||||
'IDLE IDLE',
|
||||
'DONE',
|
||||
'A6 STATUS "test" (MESSAGES RECENT UNSEEN UIDVALIDITY UIDNEXT)',
|
||||
'A7 LOGOUT'
|
||||
];
|
||||
|
||||
var exp = -1,
|
||||
res = -1,
|
||||
sentCont = false;
|
||||
|
||||
var srv = net.createServer(function(sock) {
|
||||
sock.write('* OK asdf\r\n');
|
||||
var buf = '', lines;
|
||||
sock.on('data', function(data) {
|
||||
buf += data.toString('utf8');
|
||||
if (buf.indexOf(CRLF) > -1) {
|
||||
lines = buf.split(CRLF);
|
||||
buf = lines.pop();
|
||||
lines.forEach(function(l) {
|
||||
assert(l === EXPECTED[++exp], 'Unexpected client request: ' + l);
|
||||
if (l === 'DONE') {
|
||||
assert(sentCont, 'DONE seen before continuation sent');
|
||||
sock.write('IDLE ok\r\n');
|
||||
} else if (l === 'IDLE IDLE') {
|
||||
setTimeout(function() {
|
||||
sentCont = true;
|
||||
sock.write('+ idling\r\n');
|
||||
}, 100);
|
||||
} else {
|
||||
assert(RESPONSES[++res], 'No response for client request: ' + l);
|
||||
sock.write(RESPONSES[res]);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
srv.listen(0, '127.0.0.1', function() {
|
||||
var port = srv.address().port;
|
||||
var imap = new Imap({
|
||||
user: 'foo',
|
||||
password: 'bar',
|
||||
host: '127.0.0.1',
|
||||
port: port,
|
||||
keepalive: true
|
||||
});
|
||||
imap.on('ready', function() {
|
||||
srv.close();
|
||||
imap.openBox('INBOX', true, function() {
|
||||
var f = imap.seq.fetch(1, { bodies: ['TEXT'] });
|
||||
f.on('message', function(m) {
|
||||
m.on('body', function(stream, info) {
|
||||
bodyInfo = info;
|
||||
stream.on('data', function(chunk) { body += chunk.toString('utf8'); });
|
||||
});
|
||||
m.on('attributes', function(attrs) {
|
||||
result = attrs;
|
||||
});
|
||||
});
|
||||
f.on('end', function() {
|
||||
imap.status('test', function(err, status) {
|
||||
imap.end();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
imap.connect();
|
||||
});
|
||||
|
||||
process.once('exit', function() {
|
||||
assert.deepEqual(result, {
|
||||
uid: 1,
|
||||
date: new Date('05-Sep-2004 00:38:03 +0000'),
|
||||
flags: [ '\\Seen' ]
|
||||
});
|
||||
assert.equal(body, 'IMAP is terrible');
|
||||
assert.deepEqual(bodyInfo, {
|
||||
seqno: 1,
|
||||
which: 'TEXT',
|
||||
size: 16
|
||||
});
|
||||
});
|
||||
106
test/imaps/node_modules/node-imap/test/test-connection-no-webalert.js
generated
vendored
Normal file
106
test/imaps/node_modules/node-imap/test/test-connection-no-webalert.js
generated
vendored
Normal file
@@ -0,0 +1,106 @@
|
||||
var assert = require('assert'),
|
||||
net = require('net'),
|
||||
Imap = require('../lib/Connection');
|
||||
|
||||
let result, body = '', bodyInfo;
|
||||
|
||||
const CRLF = '\r\n';
|
||||
|
||||
const RESPONSES = [
|
||||
// ['* OK Gimap ready for requests from 34.223.41.17 h98mb854172451pjb',
|
||||
// ''
|
||||
// ].join(CRLF),
|
||||
['* CAPABILITY IMAP4rev1 UNSELECT IDLE NAMESPACE QUOTA ID XLIST CHILDREN X-GM-EXT-1 XYZZY SASL-IR AUTH=XOAUTH2 AUTH=PLAIN AUTH=PLAIN-CLIENTTOKEN AUTH=OAUTHBEARER AUTH=XOAUTH',
|
||||
'A0 OK Thats all she wrote! h98mb854172451pjb',
|
||||
''
|
||||
].join(CRLF),
|
||||
['* NO [WEBALERT https://accounts.google.com/signin/continue?sarp=1&scc=1&plt=AKgnsbtti_XzDRUj8UQA070yD4HsFYGWI5l13l92X9_49kVYnLBKFB4aJ_nccAO29gqYqzWJO6GdJnZVGKVgKED4OUN6Y2wqoU2tZSs1zMix9Lo7oxUOhpTgDV64TJEPUoE8XvVzA0Zm] Web login required.',
|
||||
'A1 NO [ALERT] Please log in via your web browser: https://support.google.com/mail/accounts/answer/78754 (Failure)',
|
||||
''
|
||||
].join(CRLF),
|
||||
];
|
||||
const EXPECTED = [
|
||||
'A0 CAPABILITY',
|
||||
'A1 LOGIN "foo" "bar"',
|
||||
];
|
||||
|
||||
let exp = -1,
|
||||
res = -1,
|
||||
sentCont = false;
|
||||
|
||||
const srv = net.createServer(function(sock) {
|
||||
sock.write('* OK asdf\r\n');
|
||||
let buf = '', lines;
|
||||
|
||||
sock.on('error', function(err) {
|
||||
console.log('Got error: ', err);
|
||||
});
|
||||
|
||||
sock.on('data', function(data) {
|
||||
// console.log('Got data from IMAP Client:', data.toString());
|
||||
buf += data.toString('utf8');
|
||||
if (buf.indexOf(CRLF) > -1) {
|
||||
lines = buf.split(CRLF);
|
||||
buf = lines.pop();
|
||||
lines.forEach(function(l) {
|
||||
assert(l === EXPECTED[++exp], 'Unexpected client request: ' + l);
|
||||
assert(RESPONSES[++res], 'No response for client request: ' + l);
|
||||
// console.log('IMAP Server Returned: ', RESPONSES[res]);
|
||||
sock.write(RESPONSES[res]);
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
srv.addListener('error', (err) => {
|
||||
console.log('Got error', err);
|
||||
})
|
||||
|
||||
srv.listen(0, '127.0.0.1', function() {
|
||||
var port = srv.address().port;
|
||||
|
||||
try {
|
||||
const imap = new Imap({
|
||||
user: 'foo',
|
||||
password: 'bar',
|
||||
host: '127.0.0.1',
|
||||
port: port,
|
||||
keepalive: true
|
||||
});
|
||||
|
||||
imap.on('error', function(err) {
|
||||
// console.log('Got error', err);
|
||||
imap.end();
|
||||
srv.close();
|
||||
})
|
||||
|
||||
imap.on('ready', function() {
|
||||
srv.close();
|
||||
console.log('On Ready');
|
||||
});
|
||||
|
||||
imap.on('webalert', (text) => {
|
||||
// console.log('Got WebAlert: ', text);
|
||||
result = text;
|
||||
})
|
||||
|
||||
imap.connect();
|
||||
} catch (e) {
|
||||
console.log('Got Error: ', e);
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
process.once('exit', function() {
|
||||
// console.log('Result', {result, body, bodyInfo});
|
||||
assert.deepEqual(result, {
|
||||
message: 'Web login required.',
|
||||
url: 'https://accounts.google.com/signin/continue?sarp=1&scc=1&plt=AKgnsbtti_XzDRUj8UQA070yD4HsFYGWI5l13l92X9_49kVYnLBKFB4aJ_nccAO29gqYqzWJO6GdJnZVGKVgKED4OUN6Y2wqoU2tZSs1zMix9Lo7oxUOhpTgDV64TJEPUoE8XvVzA0Zm'
|
||||
});
|
||||
// assert.equal(body, 'IMAP is terrible');
|
||||
// assert.deepEqual(bodyInfo, {
|
||||
// seqno: 1,
|
||||
// which: 'TEXT',
|
||||
// size: 16
|
||||
// });
|
||||
});
|
||||
83
test/imaps/node_modules/node-imap/test/test-parse-bodystructure.js
generated
vendored
Normal file
83
test/imaps/node_modules/node-imap/test/test-parse-bodystructure.js
generated
vendored
Normal file
@@ -0,0 +1,83 @@
|
||||
var parseBodyStructure = require('../lib/Parser').parseBodyStructure;
|
||||
|
||||
var assert = require('assert'),
|
||||
inspect = require('util').inspect;
|
||||
|
||||
[
|
||||
{ source: '("TEXT" "PLAIN" ("CHARSET" "US-ASCII") NIL NIL "7BIT" 1152 23)'
|
||||
+ '("TEXT" "PLAIN" ("CHARSET" "US-ASCII" "NAME" "cc.diff")'
|
||||
+ ' "<960723163407.20117h@cac.washington.edu>" "Compiler diff"'
|
||||
+ ' "BASE64" 4554 73)'
|
||||
+ '"MIXED"',
|
||||
expected: [ { type: 'mixed' },
|
||||
[ { partID: '1',
|
||||
type: 'text',
|
||||
subtype: 'plain',
|
||||
params: { charset: 'US-ASCII' },
|
||||
id: null,
|
||||
description: null,
|
||||
encoding: '7BIT',
|
||||
size: 1152,
|
||||
lines: 23
|
||||
}
|
||||
],
|
||||
[ { partID: '2',
|
||||
type: 'text',
|
||||
subtype: 'plain',
|
||||
params: { charset: 'US-ASCII', name: 'cc.diff' },
|
||||
id: '<960723163407.20117h@cac.washington.edu>',
|
||||
description: 'Compiler diff',
|
||||
encoding: 'BASE64',
|
||||
size: 4554,
|
||||
lines: 73
|
||||
}
|
||||
]
|
||||
],
|
||||
what: 'RFC3501 example #1'
|
||||
},
|
||||
{ source: 'NIL NIL ("CHARSET" "GB2312") NIL NIL NIL 176 NIL NIL NIL',
|
||||
expected: [ { type: null,
|
||||
params: null,
|
||||
disposition: null,
|
||||
language: [ 'CHARSET', 'GB2312' ],
|
||||
location: null,
|
||||
extensions: null
|
||||
}
|
||||
],
|
||||
what: 'Issue 477'
|
||||
},
|
||||
{ source: '"TEXT" "PLAIN" ("CHARSET" "US-ASCII") NIL NIL "7BIT" 3028 92',
|
||||
expected: [ { partID: '1',
|
||||
type: 'text',
|
||||
subtype: 'plain',
|
||||
params: { charset: 'US-ASCII' },
|
||||
id: null,
|
||||
description: null,
|
||||
encoding: '7BIT',
|
||||
size: 3028,
|
||||
lines: 92
|
||||
}
|
||||
],
|
||||
what: 'RFC3501 example #2'
|
||||
},
|
||||
].forEach(function(v) {
|
||||
var result;
|
||||
try {
|
||||
result = parseBodyStructure(v.source);
|
||||
} catch (e) {
|
||||
console.log(makeMsg(v.what, 'JS Exception: ' + e.stack));
|
||||
return;
|
||||
}
|
||||
assert.deepEqual(result,
|
||||
v.expected,
|
||||
makeMsg(v.what,
|
||||
'Result mismatch:'
|
||||
+ '\nParsed: ' + inspect(result, false, 10)
|
||||
+ '\nExpected: ' + inspect(v.expected, false, 10)
|
||||
)
|
||||
);
|
||||
});
|
||||
|
||||
function makeMsg(what, msg) {
|
||||
return '[' + what + ']: ' + msg;
|
||||
}
|
||||
117
test/imaps/node_modules/node-imap/test/test-parse-envelope-addrs.js
generated
vendored
Normal file
117
test/imaps/node_modules/node-imap/test/test-parse-envelope-addrs.js
generated
vendored
Normal file
@@ -0,0 +1,117 @@
|
||||
var parseExpr = require('../lib/Parser').parseExpr,
|
||||
parseEnvelopeAddresses = require('../lib/Parser').parseEnvelopeAddresses;
|
||||
|
||||
var assert = require('assert'),
|
||||
inspect = require('util').inspect;
|
||||
|
||||
[
|
||||
{ source: '("Terry Gray" NIL "gray" "cac.washington.edu")',
|
||||
expected: [ { name: 'Terry Gray',
|
||||
mailbox: 'gray',
|
||||
host: 'cac.washington.edu'
|
||||
}
|
||||
],
|
||||
what: 'RFC3501 example #1'
|
||||
},
|
||||
{ source: '(NIL NIL "imap" "cac.washington.edu")',
|
||||
expected: [ { name: null,
|
||||
mailbox: 'imap',
|
||||
host: 'cac.washington.edu'
|
||||
}
|
||||
],
|
||||
what: 'RFC3501 example #2'
|
||||
},
|
||||
{ source: '("=?utf-8?Q?=C2=A9=C2=AEAZ=C2=A5?=" NIL "crazy" "example.org")',
|
||||
expected: [ { name: '©®AZ¥',
|
||||
mailbox: 'crazy',
|
||||
host: 'example.org'
|
||||
}
|
||||
],
|
||||
what: 'Name with encoded word(s)'
|
||||
},
|
||||
{ source: '(NIL NIL "imap" NIL)'
|
||||
+ '(NIL NIL NIL NIL)',
|
||||
expected: [ { group: 'imap',
|
||||
addresses: []
|
||||
}
|
||||
],
|
||||
what: 'Zero-length group'
|
||||
},
|
||||
{ source: '(NIL NIL "imap" NIL)'
|
||||
+ '("Terry Gray" NIL "gray" "cac.washington.edu")'
|
||||
+ '(NIL NIL NIL NIL)',
|
||||
expected: [ { group: 'imap',
|
||||
addresses: [
|
||||
{ name: 'Terry Gray',
|
||||
mailbox: 'gray',
|
||||
host: 'cac.washington.edu'
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
what: 'One-length group'
|
||||
},
|
||||
{ source: '(NIL NIL "imap" NIL)'
|
||||
+ '("Terry Gray" NIL "gray" "cac.washington.edu")'
|
||||
+ '(NIL NIL NIL NIL)'
|
||||
+ '(NIL NIL "imap" "cac.washington.edu")',
|
||||
expected: [ { group: 'imap',
|
||||
addresses: [
|
||||
{ name: 'Terry Gray',
|
||||
mailbox: 'gray',
|
||||
host: 'cac.washington.edu'
|
||||
}
|
||||
]
|
||||
},
|
||||
{ name: null,
|
||||
mailbox: 'imap',
|
||||
host: 'cac.washington.edu'
|
||||
}
|
||||
],
|
||||
what: 'One-length group and address'
|
||||
},
|
||||
{ source: '(NIL NIL "imap" NIL)'
|
||||
+ '("Terry Gray" NIL "gray" "cac.washington.edu")',
|
||||
expected: [ { group: 'imap',
|
||||
addresses: [
|
||||
{ name: 'Terry Gray',
|
||||
mailbox: 'gray',
|
||||
host: 'cac.washington.edu'
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
what: 'Implicit group end'
|
||||
},
|
||||
{ source: '("Terry Gray" NIL "gray" "cac.washington.edu")'
|
||||
+ '(NIL NIL NIL NIL)',
|
||||
expected: [ { name: 'Terry Gray',
|
||||
mailbox: 'gray',
|
||||
host: 'cac.washington.edu'
|
||||
}
|
||||
],
|
||||
what: 'Group end without start'
|
||||
},
|
||||
].forEach(function(v) {
|
||||
var result;
|
||||
|
||||
try {
|
||||
result = parseEnvelopeAddresses(parseExpr(v.source));
|
||||
} catch (e) {
|
||||
console.log(makeMsg(v.what, 'JS Exception: ' + e.stack));
|
||||
return;
|
||||
}
|
||||
|
||||
assert.deepEqual(result,
|
||||
v.expected,
|
||||
makeMsg(v.what,
|
||||
'Result mismatch:'
|
||||
+ '\nParsed: ' + inspect(result, false, 10)
|
||||
+ '\nExpected: ' + inspect(v.expected, false, 10)
|
||||
)
|
||||
);
|
||||
});
|
||||
|
||||
function makeMsg(what, msg) {
|
||||
return '[' + what + ']: ' + msg;
|
||||
}
|
||||
92
test/imaps/node_modules/node-imap/test/test-parse-expr.js
generated
vendored
Normal file
92
test/imaps/node_modules/node-imap/test/test-parse-expr.js
generated
vendored
Normal file
@@ -0,0 +1,92 @@
|
||||
var parseExpr = require('../lib/Parser').parseExpr;
|
||||
|
||||
var assert = require('assert'),
|
||||
inspect = require('util').inspect;
|
||||
|
||||
[
|
||||
{ source: '',
|
||||
expected: [],
|
||||
what: 'Empty value'
|
||||
},
|
||||
{ source: '""',
|
||||
expected: [''],
|
||||
what: 'Empty quoted string'
|
||||
},
|
||||
{ source: 'FLAGS NIL RFC822.SIZE 44827',
|
||||
expected: ['FLAGS', null, 'RFC822.SIZE', 44827],
|
||||
what: 'Simple, two key-value pairs with nil'
|
||||
},
|
||||
{ source: 'FLAGS (\\Seen) RFC822.SIZE 44827',
|
||||
expected: ['FLAGS', ['\\Seen'], 'RFC822.SIZE', 44827],
|
||||
what: 'Simple, two key-value pairs with list'
|
||||
},
|
||||
{ source: 'RFC822.SIZE 9007199254740993',
|
||||
expected: ['RFC822.SIZE', '9007199254740993'],
|
||||
what: 'Integer exceeding JavaScript max int size'
|
||||
},
|
||||
{ source: 'FLAGS (\\Seen) INTERNALDATE "17-Jul-1996 02:44:25 -0700"',
|
||||
expected: ['FLAGS', ['\\Seen'], 'INTERNALDATE', '17-Jul-1996 02:44:25 -0700'],
|
||||
what: 'Quoted string'
|
||||
},
|
||||
{ source: '("Foo")("Bar") ("Baz")',
|
||||
expected: [['Foo'], ['Bar'], ['Baz']],
|
||||
what: 'Lists with varying spacing'
|
||||
},
|
||||
{ source: '"\\"IMAP\\" is terrible :\\\\"',
|
||||
expected: ['"IMAP" is terrible :\\'],
|
||||
what: 'Quoted string with escaped chars'
|
||||
},
|
||||
{ source: '"\\\\"IMAP\\" is terrible :\\\\"',
|
||||
expected: ['\\"IMAP" is terrible :\\'],
|
||||
what: 'Quoted string with escaped chars #2'
|
||||
},
|
||||
{ source: '"Who does not think \\"IMAP\\" is terrible\\\\bad?"',
|
||||
expected: ['Who does not think "IMAP" is terrible\\bad?'],
|
||||
what: 'Quoted string with escaped chars #3'
|
||||
},
|
||||
{ source: '"Who does not think \\\\"IMAP\\" is terrible\\\\bad?"',
|
||||
expected: ['Who does not think \\"IMAP" is terrible\\bad?'],
|
||||
what: 'Quoted string with escaped chars #4'
|
||||
},
|
||||
{ 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>")',
|
||||
expected: [
|
||||
'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)', null, 'account', 'test.com' ] ],
|
||||
[ [ 'Test Account (Rltvty L)', null, 'account', 'test.com' ] ],
|
||||
[ [ null, null, 'account', 'test.com' ] ],
|
||||
[ [ null, null, 'one.two', 'test.fr' ],
|
||||
[ null, null, 'two.three', 'test.fr' ]
|
||||
],
|
||||
null,
|
||||
null,
|
||||
null,
|
||||
'<message@test.eu>'
|
||||
]
|
||||
],
|
||||
what: 'Triple backslash in quoted string (GH Issue #345)'
|
||||
},
|
||||
].forEach(function(v) {
|
||||
var result;
|
||||
|
||||
try {
|
||||
result = parseExpr(v.source);
|
||||
} catch (e) {
|
||||
console.log(makeMsg(v.what, 'JS Exception: ' + e.stack));
|
||||
return;
|
||||
}
|
||||
|
||||
assert.deepEqual(result,
|
||||
v.expected,
|
||||
makeMsg(v.what,
|
||||
'Result mismatch:'
|
||||
+ '\nParsed: ' + inspect(result, false, 10)
|
||||
+ '\nExpected: ' + inspect(v.expected, false, 10)
|
||||
)
|
||||
);
|
||||
});
|
||||
|
||||
function makeMsg(what, msg) {
|
||||
return '[' + what + ']: ' + msg;
|
||||
}
|
||||
109
test/imaps/node_modules/node-imap/test/test-parse-header.js
generated
vendored
Normal file
109
test/imaps/node_modules/node-imap/test/test-parse-header.js
generated
vendored
Normal file
@@ -0,0 +1,109 @@
|
||||
var parseHeader = require('../lib/Parser').parseHeader;
|
||||
|
||||
var assert = require('assert'),
|
||||
inspect = require('util').inspect;
|
||||
|
||||
var CRLF = '\r\n';
|
||||
|
||||
[
|
||||
{ source: ['To: Foo', CRLF,
|
||||
' Bar Baz', CRLF],
|
||||
expected: { to: [ 'Foo Bar Baz' ] },
|
||||
what: 'Folded header value (plain -- space)'
|
||||
},
|
||||
{ source: ['To: Foo', CRLF,
|
||||
'\tBar\tBaz', CRLF],
|
||||
expected: { to: [ 'Foo\tBar\tBaz' ] },
|
||||
what: 'Folded header value (plain -- tab)'
|
||||
},
|
||||
{ source: ['Subject: =?iso-8859-1?Q?=A1Hola,_se=F1or!?=', CRLF],
|
||||
expected: { subject: [ '¡Hola, señor!' ] },
|
||||
what: 'MIME encoded-word in value'
|
||||
},
|
||||
{ source: ['Subject: =?iso-8859-1*es?Q?=A1Hola,_se=F1or!?=', CRLF],
|
||||
expected: { subject: [ '¡Hola, señor!' ] },
|
||||
what: 'MIME encoded-word in value with language set (RFC2231)'
|
||||
},
|
||||
{ source: ['Subject: =?iso-8859-1*?Q?=A1Hola,_se=F1or!?=', CRLF],
|
||||
expected: { subject: [ '¡Hola, señor!' ] },
|
||||
what: 'MIME encoded-word in value with empty language set'
|
||||
},
|
||||
{ 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,
|
||||
' =?GB2312?Q?345678901234567890123456789012345678901234567890123456789012?=', CRLF,
|
||||
' =?GB2312?Q?345678901234567890?=', CRLF],
|
||||
expected: { subject: [ '测试题目与中国信 long subjects are not OK 12345678901234567890123456789012345678901234567890123456789012345678901234567890' ] },
|
||||
what: 'Folded header value (adjacent MIME encoded-words)'
|
||||
},
|
||||
{ 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,
|
||||
' 3=?GB2312?Q?45678901234567890123456789012345678901234567890123456789012?=', CRLF,
|
||||
' 3=?GB2312?Q?45678901234567890?=', CRLF],
|
||||
expected: { subject: [ '测试题目与中国信 long subjects are not OK 12 345678901234567890123456789012345678901234567890123456789012 345678901234567890' ] },
|
||||
what: 'Folded header value (non-adjacent MIME encoded-words)'
|
||||
},
|
||||
{ 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,
|
||||
' 3=?GB2312?Q?45678901234567890123456789012345678901234567890123456789012?=', CRLF,
|
||||
' =?GB2312?Q?345678901234567890?=', CRLF],
|
||||
expected: { subject: [ '测试题目与中国信 long subjects are not OK 12 345678901234567890123456789012345678901234567890123456789012345678901234567890' ] },
|
||||
what: 'Folded header value (one adjacent, one non-adjacent MIME encoded-words)'
|
||||
},
|
||||
{ source: ['Subject: =?UTF-8?Q?=E0=B9=84=E0=B8=97=E0=B8=A2_=E0=B9=84?=', CRLF,
|
||||
' ', CRLF,
|
||||
' =?UTF-8?Q?=E0=B8=97=E0=B8=A2_=E0=B9=84=E0=B8=97?= =?UTF-8?Q?=E0=B8=A2?=', CRLF],
|
||||
expected: { subject: [ 'ไทย ไทย ไทย' ] },
|
||||
what: 'Folded header value (adjacent MIME encoded-words seperated by linear whitespace)'
|
||||
},
|
||||
{ source: ['Subject: =?utf-8?Q?abcdefghij_=E0=B9=83=E0=B8=99_klmnopqr_=E0=B9=84=E0=B8=A1=E0=B9?=', CRLF,
|
||||
' =?utf-8?Q?=88=E0=B8=82=E0=B8=B6=E0=B9=89=E0=B8=99?=', CRLF],
|
||||
expected: { subject: [ 'abcdefghij ใน klmnopqr ไม่ขึ้น' ] },
|
||||
what: 'Folded header value (incomplete multi-byte character split)'
|
||||
},
|
||||
{ source: ['Subject: =?utf-8?B?Rlc6IOC4quC4tOC5iOC4h+C4oeC4tQ==?=', CRLF,
|
||||
' =?utf-8?B?4LiK4Li14Lin4Li04LiV4Lir4LiZ4LmJ4Liy4LiV?=', CRLF,
|
||||
' =?utf-8?B?4Liy4LmB4Lib4Lil4LiBIOC5hiDguKPguK3=?=', CRLF,
|
||||
' =?utf-8?Q?=E0=B8=9A=E0=B9=82=E0=B8=A5=E0=B8=81?=', CRLF],
|
||||
expected: { subject: [ 'FW: สิ่งมีชีวิตหน้าตาแปลก ๆ รอบโลก' ] },
|
||||
what: 'Folded header value (consecutive complete base64-encoded words)'
|
||||
},
|
||||
{ source: ['Subject: =?utf-8?B?4Lij4Li54Lib4Lig4Liy4Lie4LiX4Li14LmIIGVtYmVkIOC5g+C4meC5gOC4?=', CRLF,
|
||||
' =?utf-8?B?meC4t+C5ieC4reC5gOC4oeC4peC4peC5jOC5hOC4oeC5iOC5geC4quC4lOC4?=', CRLF,
|
||||
' =?utf-8?B?hw==?=', CRLF],
|
||||
expected: { subject: [ 'รูปภาพที่ embed ในเนื้อเมลล์ไม่แสดง' ] },
|
||||
what: 'Folded header value (consecutive partial base64-encoded words)'
|
||||
},
|
||||
{ source: [' ', CRLF,
|
||||
'To: Foo', CRLF],
|
||||
expected: { to: [ 'Foo' ] },
|
||||
what: 'Invalid first line'
|
||||
},
|
||||
// header with body
|
||||
{ source: ['Subject: test subject', CRLF,
|
||||
'X-Another-Header: test', CRLF,
|
||||
CRLF,
|
||||
'This is body: Not a header', CRLF],
|
||||
expected: { subject: [ 'test subject' ], 'x-another-header': [ 'test' ] },
|
||||
what: 'Header with the body'
|
||||
},
|
||||
|
||||
].forEach(function(v) {
|
||||
var result;
|
||||
|
||||
try {
|
||||
result = parseHeader(v.source.join(''));
|
||||
} catch (e) {
|
||||
console.log(makeMsg(v.what, 'JS Exception: ' + e.stack));
|
||||
return;
|
||||
}
|
||||
|
||||
assert.deepEqual(result,
|
||||
v.expected,
|
||||
makeMsg(v.what,
|
||||
'Result mismatch:'
|
||||
+ '\nParsed: ' + inspect(result, false, 10)
|
||||
+ '\nExpected: ' + inspect(v.expected, false, 10)
|
||||
)
|
||||
);
|
||||
});
|
||||
|
||||
function makeMsg(what, msg) {
|
||||
return '[' + what + ']: ' + msg;
|
||||
}
|
||||
651
test/imaps/node_modules/node-imap/test/test-parser.js
generated
vendored
Normal file
651
test/imaps/node_modules/node-imap/test/test-parser.js
generated
vendored
Normal file
@@ -0,0 +1,651 @@
|
||||
const Parser = require('../lib/Parser').Parser
|
||||
|
||||
const assert = require('assert'),
|
||||
crypto = require('crypto'),
|
||||
inspect = require('util').inspect
|
||||
|
||||
const CR = '\r', LF = '\n', CRLF = CR + LF;
|
||||
|
||||
[
|
||||
{
|
||||
source: ['A1 OK LOGIN completed', CRLF],
|
||||
expected: [{
|
||||
type: 'ok',
|
||||
tagnum: 1,
|
||||
textCode: undefined,
|
||||
text: 'LOGIN completed'
|
||||
}
|
||||
],
|
||||
what: 'Tagged OK'
|
||||
},
|
||||
{
|
||||
source: ['IDLE OK IDLE terminated', CRLF],
|
||||
expected: ['IDLE OK IDLE terminated'],
|
||||
what: 'Unknown line'
|
||||
},
|
||||
{
|
||||
source: ['IDLE OK Idle completed (0.002 + 1.783 + 1.783 secs).', CRLF],
|
||||
expected: ['IDLE OK Idle completed (0.002 + 1.783 + 1.783 secs).'],
|
||||
what: 'Unknown line with + char'
|
||||
},
|
||||
{
|
||||
source: ['+ idling', CRLF],
|
||||
expected: [{
|
||||
textCode: undefined,
|
||||
text: 'idling'
|
||||
}
|
||||
],
|
||||
what: 'Continuation'
|
||||
},
|
||||
{
|
||||
source: ['+ [ALERT] idling', CRLF],
|
||||
expected: [{
|
||||
textCode: 'ALERT',
|
||||
text: 'idling'
|
||||
}
|
||||
],
|
||||
what: 'Continuation with text code'
|
||||
},
|
||||
{
|
||||
source: ['A1 NO [ALERT] Please log in via your web browser: https://support.google.com/mail/accounts/answer/78754 (Failure)', CRLF],
|
||||
expected: [{
|
||||
type: 'no',
|
||||
tagnum: 1,
|
||||
textCode: 'ALERT',
|
||||
text: 'Please log in via your web browser: https://support.google.com/mail/accounts/answer/78754 (Failure)'
|
||||
}
|
||||
],
|
||||
what: 'Continuation with text code'
|
||||
},
|
||||
|
||||
{
|
||||
source: ['* NO [WEBALERT https://someurl.com/continue?sarp=1&scc=1] Web login required.', CRLF],
|
||||
expected: [{
|
||||
type: 'no',
|
||||
num: undefined,
|
||||
textCode: {
|
||||
key: 'WEBALERT',
|
||||
val: 'https://someurl.com/continue?sarp=1&scc=1'
|
||||
},
|
||||
text: 'Web login required.'
|
||||
}
|
||||
],
|
||||
what: 'Handling of Webalert'
|
||||
},
|
||||
{
|
||||
source: ['+', CRLF],
|
||||
expected: [{
|
||||
textCode: undefined,
|
||||
text: undefined
|
||||
}
|
||||
],
|
||||
what: 'Continuation (broken -- RFC violation) sent by AOL IMAP'
|
||||
},
|
||||
{
|
||||
source: ['* NAMESPACE ',
|
||||
'(("" "/")) ',
|
||||
'(("~" "/")) ',
|
||||
'(("#shared/" "/")("#public/" "/")("#ftp/" "/")("#news." "."))',
|
||||
CRLF],
|
||||
expected: [{
|
||||
type: 'namespace',
|
||||
num: undefined,
|
||||
textCode: undefined,
|
||||
text: {
|
||||
personal: [
|
||||
{
|
||||
prefix: '',
|
||||
delimiter: '/',
|
||||
extensions: undefined
|
||||
}
|
||||
],
|
||||
other: [
|
||||
{
|
||||
prefix: '~',
|
||||
delimiter: '/',
|
||||
extensions: undefined
|
||||
}
|
||||
],
|
||||
shared: [
|
||||
{
|
||||
prefix: '#shared/',
|
||||
delimiter: '/',
|
||||
extensions: undefined
|
||||
},
|
||||
{
|
||||
prefix: '#public/',
|
||||
delimiter: '/',
|
||||
extensions: undefined
|
||||
},
|
||||
{
|
||||
prefix: '#ftp/',
|
||||
delimiter: '/',
|
||||
extensions: undefined
|
||||
},
|
||||
{
|
||||
prefix: '#news.',
|
||||
delimiter: '.',
|
||||
extensions: undefined
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
],
|
||||
what: 'Multiple namespaces'
|
||||
},
|
||||
{
|
||||
source: ['* NAMESPACE ',
|
||||
'(("" "/" "X-PARAM" ("FLAG1" "FLAG2"))) ',
|
||||
'NIL ',
|
||||
'NIL',
|
||||
CRLF],
|
||||
expected: [{
|
||||
type: 'namespace',
|
||||
num: undefined,
|
||||
textCode: undefined,
|
||||
text: {
|
||||
personal: [
|
||||
{
|
||||
prefix: '',
|
||||
delimiter: '/',
|
||||
extensions: {
|
||||
'X-PARAM': ['FLAG1', 'FLAG2']
|
||||
}
|
||||
}
|
||||
],
|
||||
other: null,
|
||||
shared: null
|
||||
}
|
||||
}
|
||||
],
|
||||
what: 'Multiple namespaces'
|
||||
},
|
||||
{
|
||||
source: ['* FLAGS (\\Answered \\Flagged \\Deleted \\Seen \\Draft)', CRLF],
|
||||
expected: [{
|
||||
type: 'flags',
|
||||
num: undefined,
|
||||
textCode: undefined,
|
||||
text: [
|
||||
'\\Answered',
|
||||
'\\Flagged',
|
||||
'\\Deleted',
|
||||
'\\Seen',
|
||||
'\\Draft'
|
||||
]
|
||||
}
|
||||
],
|
||||
what: 'Flags'
|
||||
},
|
||||
{
|
||||
source: ['* SEARCH 2 3 6', CRLF],
|
||||
expected: [{
|
||||
type: 'search',
|
||||
num: undefined,
|
||||
textCode: undefined,
|
||||
text: [2, 3, 6]
|
||||
}
|
||||
],
|
||||
what: 'Search'
|
||||
},
|
||||
{
|
||||
source: ['* XLIST (\\Noselect) "/" ~/Mail/foo', CRLF],
|
||||
expected: [{
|
||||
type: 'xlist',
|
||||
num: undefined,
|
||||
textCode: undefined,
|
||||
text: {
|
||||
flags: ['\\Noselect'],
|
||||
delimiter: '/',
|
||||
name: '~/Mail/foo'
|
||||
}
|
||||
}
|
||||
],
|
||||
what: 'XList'
|
||||
},
|
||||
{
|
||||
source: ['* LIST (\\Noselect) "/" ~/Mail/foo', CRLF],
|
||||
expected: [{
|
||||
type: 'list',
|
||||
num: undefined,
|
||||
textCode: undefined,
|
||||
text: {
|
||||
flags: ['\\Noselect'],
|
||||
delimiter: '/',
|
||||
name: '~/Mail/foo'
|
||||
}
|
||||
}
|
||||
],
|
||||
what: 'List'
|
||||
},
|
||||
{
|
||||
source: ['* STATUS blurdybloop (MESSAGES 231 UIDNEXT 44292)', CRLF],
|
||||
expected: [{
|
||||
type: 'status',
|
||||
num: undefined,
|
||||
textCode: undefined,
|
||||
text: {
|
||||
name: 'blurdybloop',
|
||||
attrs: { messages: 231, uidnext: 44292 }
|
||||
}
|
||||
}
|
||||
],
|
||||
what: 'Status'
|
||||
},
|
||||
{
|
||||
source: ['* OK [UNSEEN 17] Message 17 is the first unseen message', CRLF],
|
||||
expected: [{
|
||||
type: 'ok',
|
||||
num: undefined,
|
||||
textCode: {
|
||||
key: 'UNSEEN',
|
||||
val: 17
|
||||
},
|
||||
text: 'Message 17 is the first unseen message'
|
||||
}
|
||||
],
|
||||
what: 'Untagged OK (with text code, with text)'
|
||||
},
|
||||
{
|
||||
source: ['* OK [PERMANENTFLAGS (\\Deleted \\Seen \\*)] Limited', CRLF],
|
||||
expected: [{
|
||||
type: 'ok',
|
||||
num: undefined,
|
||||
textCode: {
|
||||
key: 'PERMANENTFLAGS',
|
||||
val: ['\\Deleted', '\\Seen', '\\*']
|
||||
},
|
||||
text: 'Limited'
|
||||
}
|
||||
],
|
||||
what: 'Untagged OK (with text code, with text)'
|
||||
},
|
||||
{
|
||||
source: ['* OK [UNSEEN 17]', CRLF],
|
||||
expected: [{
|
||||
type: 'ok',
|
||||
num: undefined,
|
||||
textCode: {
|
||||
key: 'UNSEEN',
|
||||
val: 17
|
||||
},
|
||||
text: undefined
|
||||
}
|
||||
],
|
||||
what: 'Untagged OK (no text code, with text) (RFC violation)'
|
||||
},
|
||||
{
|
||||
source: ['* OK IMAP4rev1 Service Ready', CRLF],
|
||||
expected: [{
|
||||
type: 'ok',
|
||||
num: undefined,
|
||||
textCode: undefined,
|
||||
text: 'IMAP4rev1 Service Ready'
|
||||
}
|
||||
],
|
||||
what: 'Untagged OK (no text code, with text)'
|
||||
},
|
||||
{
|
||||
source: ['* OK', CRLF], // I have seen servers that send stuff like this ..
|
||||
expected: [{
|
||||
type: 'ok',
|
||||
num: undefined,
|
||||
textCode: undefined,
|
||||
text: undefined
|
||||
}
|
||||
],
|
||||
what: 'Untagged OK (no text code, no text) (RFC violation)'
|
||||
},
|
||||
{
|
||||
source: ['* 18 EXISTS', CRLF],
|
||||
expected: [{
|
||||
type: 'exists',
|
||||
num: 18,
|
||||
textCode: undefined,
|
||||
text: undefined
|
||||
}
|
||||
],
|
||||
what: 'Untagged EXISTS'
|
||||
},
|
||||
{
|
||||
source: ['* 2 RECENT', CRLF],
|
||||
expected: [{
|
||||
type: 'recent',
|
||||
num: 2,
|
||||
textCode: undefined,
|
||||
text: undefined
|
||||
}
|
||||
],
|
||||
what: 'Untagged RECENT'
|
||||
},
|
||||
{
|
||||
source: ['* 12 FETCH (BODY[HEADER] {342}', CRLF,
|
||||
'Date: Wed, 17 Jul 1996 02:23:25 -0700 (PDT)', CRLF,
|
||||
'From: Terry Gray <gray@cac.washington.edu>', CRLF,
|
||||
'Subject: IMAP4rev1 WG mtg summary and minutes', CRLF,
|
||||
'To: imap@cac.washington.edu', CRLF,
|
||||
'cc: minutes@CNRI.Reston.VA.US, John Klensin <KLENSIN@MIT.EDU>', CRLF,
|
||||
'Message-Id: <B27397-0100000@cac.washington.edu>', CRLF,
|
||||
'MIME-Version: 1.0', CRLF,
|
||||
'Content-Type: TEXT/PLAIN; CHARSET=US-ASCII', CRLF, CRLF,
|
||||
')', CRLF],
|
||||
expected: [{
|
||||
seqno: 12,
|
||||
which: 'HEADER',
|
||||
size: 342
|
||||
},
|
||||
{
|
||||
type: 'fetch',
|
||||
num: 12,
|
||||
textCode: undefined,
|
||||
text: {}
|
||||
}
|
||||
],
|
||||
bodySHA1s: ['1f96faf50f6410f99237791f9e3b89454bf93fa7'],
|
||||
what: 'Untagged FETCH (body)'
|
||||
},
|
||||
{
|
||||
source: ['* 12 FETCH (BODY[TEXT] "IMAP is terrible")', CRLF],
|
||||
expected: [{
|
||||
seqno: 12,
|
||||
which: 'TEXT',
|
||||
size: 16
|
||||
},
|
||||
{
|
||||
type: 'fetch',
|
||||
num: 12,
|
||||
textCode: undefined,
|
||||
text: {}
|
||||
}
|
||||
],
|
||||
bodySHA1s: ['bac8a1528c133787a6969a10a1ff453ebb9adfc8'],
|
||||
what: 'Untagged FETCH (quoted body)'
|
||||
},
|
||||
{
|
||||
source: ['* 12 FETCH (BODY[TEXT] "\\"IMAP\\" is terrible :\\\\")', CRLF],
|
||||
expected: [{
|
||||
seqno: 12,
|
||||
which: 'TEXT',
|
||||
size: 21
|
||||
},
|
||||
{
|
||||
type: 'fetch',
|
||||
num: 12,
|
||||
textCode: undefined,
|
||||
text: {}
|
||||
}
|
||||
],
|
||||
bodySHA1s: ['7570c08150050a404603f63f60b65b42378d7d42'],
|
||||
what: 'Untagged FETCH (quoted body with escaped chars)'
|
||||
},
|
||||
{
|
||||
source: ['* 12 FETCH (INTERNALDATE {26}', CRLF,
|
||||
'17-Jul-1996 02:44:25 -0700)' + CRLF],
|
||||
expected: [{
|
||||
type: 'fetch',
|
||||
num: 12,
|
||||
textCode: undefined,
|
||||
text: {
|
||||
internaldate: new Date('17-Jul-1996 02:44:25 -0700')
|
||||
}
|
||||
}
|
||||
],
|
||||
what: 'Untagged FETCH with non-body literal'
|
||||
},
|
||||
{
|
||||
source: ['* 12 FETCH (INTERNALDATE {2',
|
||||
'6}' + CRLF + '17-Jul-1996 02:44:25 -0700)' + CRLF],
|
||||
expected: [{
|
||||
type: 'fetch',
|
||||
num: 12,
|
||||
textCode: undefined,
|
||||
text: {
|
||||
internaldate: new Date('17-Jul-1996 02:44:25 -0700')
|
||||
}
|
||||
}
|
||||
],
|
||||
what: 'Untagged FETCH with non-body literal (length split)'
|
||||
},
|
||||
{
|
||||
source: ['* 12 FETCH (INTERNALDATE {26}', CRLF,
|
||||
'17-Jul-1996 02:44:25 -0700)' + CR,
|
||||
LF],
|
||||
expected: [{
|
||||
type: 'fetch',
|
||||
num: 12,
|
||||
textCode: undefined,
|
||||
text: {
|
||||
internaldate: new Date('17-Jul-1996 02:44:25 -0700')
|
||||
}
|
||||
}
|
||||
],
|
||||
what: 'Untagged FETCH with non-body literal (split CRLF)'
|
||||
},
|
||||
{
|
||||
source: ['* 12 FETCH (FLAGS (\\Seen)',
|
||||
' INTERNALDATE "17-Jul-1996 02:44:25 -0700"',
|
||||
' RFC822.SIZE 4286',
|
||||
' ENVELOPE ("Wed, 17 Jul 1996 02:23:25 -0700 (PDT)"',
|
||||
' "IMAP4rev1 WG mtg summary and minutes"',
|
||||
' (("Terry Gray" NIL "gray" "cac.washington.edu"))',
|
||||
' (("Terry Gray" NIL "gray" "cac.washington.edu"))',
|
||||
' (("Terry Gray" NIL "gray" "cac.washington.edu"))',
|
||||
' ((NIL NIL "imap" "cac.washington.edu"))',
|
||||
' ((NIL NIL "minutes" "CNRI.Reston.VA.US")',
|
||||
'("John Klensin" NIL "KLENSIN" "MIT.EDU")) NIL NIL',
|
||||
' "<B27397-0100000@cac.washington.edu>")',
|
||||
' BODY ("TEXT" "PLAIN" ("CHARSET" "US-ASCII") NIL NIL "7BIT" 3028',
|
||||
' 92))',
|
||||
CRLF],
|
||||
expected: [{
|
||||
type: 'fetch',
|
||||
num: 12,
|
||||
textCode: undefined,
|
||||
text: {
|
||||
flags: ['\\Seen'],
|
||||
internaldate: new Date('17-Jul-1996 02:44:25 -0700'),
|
||||
'rfc822.size': 4286,
|
||||
envelope: {
|
||||
date: new Date('Wed, 17 Jul 1996 02:23:25 -0700 (PDT)'),
|
||||
subject: 'IMAP4rev1 WG mtg summary and minutes',
|
||||
from: [
|
||||
{
|
||||
name: 'Terry Gray',
|
||||
mailbox: 'gray',
|
||||
host: 'cac.washington.edu'
|
||||
}
|
||||
],
|
||||
sender: [
|
||||
{
|
||||
name: 'Terry Gray',
|
||||
mailbox: 'gray',
|
||||
host: 'cac.washington.edu'
|
||||
}
|
||||
],
|
||||
replyTo: [
|
||||
{
|
||||
name: 'Terry Gray',
|
||||
mailbox: 'gray',
|
||||
host: 'cac.washington.edu'
|
||||
}
|
||||
],
|
||||
to: [
|
||||
{
|
||||
name: null,
|
||||
mailbox: 'imap',
|
||||
host: 'cac.washington.edu'
|
||||
}
|
||||
],
|
||||
cc: [
|
||||
{
|
||||
name: null,
|
||||
mailbox: 'minutes',
|
||||
host: 'CNRI.Reston.VA.US'
|
||||
},
|
||||
{
|
||||
name: 'John Klensin',
|
||||
mailbox: 'KLENSIN',
|
||||
host: 'MIT.EDU'
|
||||
}
|
||||
],
|
||||
bcc: null,
|
||||
inReplyTo: null,
|
||||
messageId: '<B27397-0100000@cac.washington.edu>'
|
||||
},
|
||||
body: [
|
||||
{
|
||||
partID: '1',
|
||||
type: 'text',
|
||||
subtype: 'plain',
|
||||
params: { charset: 'US-ASCII' },
|
||||
id: null,
|
||||
description: null,
|
||||
encoding: '7BIT',
|
||||
size: 3028,
|
||||
lines: 92
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
],
|
||||
what: 'Untagged FETCH (flags, date, size, envelope, body[structure])'
|
||||
},
|
||||
// EXTENSIONS ================================================================
|
||||
{
|
||||
source: ['* ESEARCH (TAG "A285") UID MIN 7 MAX 3800', CRLF],
|
||||
expected: [{
|
||||
type: 'esearch',
|
||||
num: undefined,
|
||||
textCode: undefined,
|
||||
text: { min: 7, max: 3800 }
|
||||
}
|
||||
],
|
||||
what: 'ESearch UID, 2 items'
|
||||
},
|
||||
{
|
||||
source: ['* ESEARCH (TAG "A284") MIN 4', CRLF],
|
||||
expected: [{
|
||||
type: 'esearch',
|
||||
num: undefined,
|
||||
textCode: undefined,
|
||||
text: { min: 4 }
|
||||
}
|
||||
],
|
||||
what: 'ESearch 1 item'
|
||||
},
|
||||
{
|
||||
source: ['* ESEARCH (TAG "A283") ALL 2,10:11', CRLF],
|
||||
expected: [{
|
||||
type: 'esearch',
|
||||
num: undefined,
|
||||
textCode: undefined,
|
||||
text: { all: ['2', '10:11'] }
|
||||
}
|
||||
],
|
||||
what: 'ESearch ALL list'
|
||||
},
|
||||
{
|
||||
source: ['* QUOTA "" (STORAGE 10 512)', CRLF],
|
||||
expected: [{
|
||||
type: 'quota',
|
||||
num: undefined,
|
||||
textCode: undefined,
|
||||
text: {
|
||||
root: '',
|
||||
resources: {
|
||||
storage: { usage: 10, limit: 512 }
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
what: 'Quota'
|
||||
},
|
||||
{
|
||||
source: ['* QUOTAROOT INBOX ""', CRLF],
|
||||
expected: [{
|
||||
type: 'quotaroot',
|
||||
num: undefined,
|
||||
textCode: undefined,
|
||||
text: {
|
||||
roots: [''],
|
||||
mailbox: 'INBOX'
|
||||
}
|
||||
}
|
||||
],
|
||||
what: 'QuotaRoot'
|
||||
},
|
||||
{
|
||||
source: ['A1 OK', CRLF], // some servers like ppops.net sends such response
|
||||
expected: [{
|
||||
type: 'ok',
|
||||
tagnum: 1,
|
||||
textCode: undefined,
|
||||
text: ''
|
||||
}
|
||||
],
|
||||
what: 'Tagged OK (no text code, no text)'
|
||||
},
|
||||
].forEach(function (v) {
|
||||
const ss = new require('stream').Readable(), result = []
|
||||
let p
|
||||
ss._read = function () { }
|
||||
|
||||
p = new Parser(ss)
|
||||
p.on('tagged', function (info) {
|
||||
result.push(info)
|
||||
})
|
||||
p.on('untagged', function (info) {
|
||||
result.push(info)
|
||||
})
|
||||
p.on('continue', function (info) {
|
||||
result.push(info)
|
||||
})
|
||||
p.on('other', function (line) {
|
||||
result.push(line)
|
||||
})
|
||||
p.on('body', function (stream, info) {
|
||||
result.push(info)
|
||||
if (Array.isArray(v.bodySHA1s)) {
|
||||
const hash = crypto.createHash('sha1')
|
||||
stream.on('data', function (d) {
|
||||
hash.update(d)
|
||||
})
|
||||
stream.on('end', function () {
|
||||
const calculated = hash.digest('hex'),
|
||||
expected = v.bodySHA1s.shift()
|
||||
assert.equal(calculated,
|
||||
expected,
|
||||
makeMsg(v.what,
|
||||
'Body SHA1 mismatch:'
|
||||
+ '\nCalculated: ' + calculated
|
||||
+ '\nExpected: ' + expected
|
||||
)
|
||||
)
|
||||
})
|
||||
} else
|
||||
stream.resume()
|
||||
})
|
||||
|
||||
try {
|
||||
v.source.forEach(function (chunk) {
|
||||
ss.push(chunk)
|
||||
})
|
||||
} catch (e) {
|
||||
console.log(makeMsg(v.what, 'JS Exception: ' + e.stack))
|
||||
return
|
||||
}
|
||||
setImmediate(function () {
|
||||
assert.deepEqual(result,
|
||||
v.expected,
|
||||
makeMsg(v.what,
|
||||
'Result mismatch:'
|
||||
+ '\nParsed: ' + inspect(result, false, 10)
|
||||
+ '\nExpected: ' + inspect(v.expected, false, 10)
|
||||
)
|
||||
)
|
||||
})
|
||||
})
|
||||
|
||||
function makeMsg(what, msg) {
|
||||
return '[' + what + ']: ' + msg
|
||||
}
|
||||
4
test/imaps/node_modules/node-imap/test/test.js
generated
vendored
Normal file
4
test/imaps/node_modules/node-imap/test/test.js
generated
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
require('fs').readdirSync(__dirname).forEach(function(f) {
|
||||
if (f.substr(0, 5).toLowerCase() === 'test-')
|
||||
require('./' + f);
|
||||
});
|
||||
Reference in New Issue
Block a user