Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

browserbox

Package Overview
Dependencies
Maintainers
3
Versions
20
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

browserbox - npm Package Compare versions

Comparing version 0.5.2 to 0.6.0

2

package.json
{
"name": "browserbox",
"version": "0.5.2",
"version": "0.6.0",
"homepage": "https://github.com/whiteout-io/browserbox",

@@ -5,0 +5,0 @@ "description": "IMAP client for browsers.",

@@ -277,2 +277,22 @@ # browserbox

## Create mailbox
Create a folder with the given path, automatically handling utf-7 encoding. You
currently need to manually build the path string yourself. (There is potential
for future enhancement to provide assistance.)
If the server indicates a failure but that the folder already exists with the
ALREADYEXISTS response code, the request will be treated as a success.
Example
```javascript
// On a server with a personal namesapce of INBOX and a delimiter of '/',
// create folder Foo. Note that folders using a non-empty personal namespace
// may automatically assume the personal namespace.
client.createMailbox('INBOX/Foo', function callback(err, alreadyExists) {});
// Do the same on a server where the personal namespace is ''
client.createMailbox('Foo', function callback(err, alreadyExists) {});
```
## Select mailbox

@@ -710,2 +730,52 @@

## State-dependend calls
Calls to Browserbox are queued in FIFO order until they are ready for execution. This may be problematic for calls that depend on a selected mailbox, e.g. `#search` or `#setFlags`. These call can be issued with a `precheck` callback that is invoked **before** the IMAP command is sent to the server.
Example:
```javascript
// search depends on a selected mailbox, e.g. inbox
imap.search({
header: ['subject', 'hello 3']
}, {
// add precheck(ctx, next) to the query options
precheck: function(ctx, next) {
// make sure inbox is selected before the search command is run
imap.selectMailbox('inbox', {
ctx: ctx // pass the context parameter received in the precheck callback as a query option to bypass the command queue
}, next); // next should invoked when you're done
},
byUid: true
}, function(error, result) {
...
});
```
A `precheck` callback receives two arguments:
* **ctx** is a context parameter, i.e. a pointer to the current position in the command queue
* **next** callback to be invoked when the precheck is done
Calls issued in a `precheck` callback will be executed *before* the parent call, if you pass the `ctx` parameter received as a argument of the `precheck` callback to the query options. This bypasses the internal FIFO queue and executes the call on the spot! *If the context parameter is left blank, the calls will be queued as usual*.
Invoke `next` once you're done with the `precheck` callback to resume normal operation.
If you want to *remove* a call from the FIFO queue, e.g. because a message is no longer available in a mailbox, pass in an error to the `next` callback. The parent call will not be executed and you will receive the error passed to next in the callback of the parent call.
Example:
```javascript
imap.setFlags('1', ['\\Seen', '$MyFlag'], {
precheck: function(ctx, next) {
next(new Error('Foo')); // this removes the setFlags query from the queue
}
}, function(err, result) {
// err.message -> 'Foo'
...
});
```
**NB!** `precheck` callbacks can be also nested! For details, have a look at the integration test that covers this portion of the code.
## Get your hands dirty

@@ -712,0 +782,0 @@

@@ -646,3 +646,13 @@ // Copyright (c) 2014 Andris Reinman

this._clientQueue.push(data);
// if we're in priority mode (i.e. we ran commands in a precheck),
// queue any commands BEFORE the command that contianed the precheck,
// otherwise just queue command as usual
var index = data.ctx ? this._clientQueue.indexOf(data.ctx) : -1;
if (index >= 0) {
data.tag += '.p';
data.request.tag += '.p';
this._clientQueue.splice(index, 0, data);
} else {
this._clientQueue.push(data);
}

@@ -655,3 +665,3 @@ if (this._canSend) {

/**
* Sends a command from command queue to the server.
* Sends a command from client queue to the server.
*/

@@ -664,2 +674,44 @@ ImapClient.prototype._sendRequest = function() {

// an operation was made in the precheck, no need to restart the queue manually
this._restartQueue = false;
var command = this._clientQueue[0];
if (typeof command.precheck === 'function') {
// remember the context
var context = command;
var precheck = context.precheck;
delete context.precheck;
// we need to restart the queue handling if no operation was made in the precheck
this._restartQueue = true;
// invoke the precheck command with a callback to signal that you're
// done with precheck and ready to resume normal operation
precheck(context, function(err) {
// we're done with the precheck
if (!err) {
if (this._restartQueue) {
// we need to restart the queue handling
this._sendRequest();
}
return;
}
// precheck callback failed, so we remove the initial command
// from the queue, invoke its callback and resume normal operation
var cmd, index = this._clientQueue.indexOf(context);
if (index >= 0) {
cmd = this._clientQueue.splice(index, 1)[0];
}
if (cmd && cmd.callback) {
cmd.callback(err, function() {
this._canSend = true;
this._sendRequest();
setTimeout(this._processServerQueue.bind(this), 0);
}.bind(this));
}
}.bind(this));
return;
}
this._canSend = false;

@@ -677,2 +729,3 @@ this._currentCommand = this._clientQueue.shift();

var data = this._currentCommand.data.shift();
this.send(data + (!this._currentCommand.data.length ? '\r\n' : ''));

@@ -679,0 +732,0 @@ return this.waitDrain;

@@ -46,2 +46,5 @@ 'use strict';

raw: "Subject: hello 6\r\n\r\nWorld 6!"
}, {
raw: "Subject: hello 7\r\n\r\nWorld 7!",
uid: 600
}]

@@ -95,5 +98,2 @@ },

beforeEach(function(done) {
// don't log in the tests
axe.removeAppender(axe.defaultAppender);
// start imap test server

@@ -462,2 +462,158 @@ var options = {

describe('precheck', function() {
var callCtr;
beforeEach(function() {
callCtr = 0;
});
it('should use nested precheck calls to cycle through mailboxes, delete mail, move stuff around etc', function(done) {
/*
* start out in [Gmail]/Drafts
*
* execution path #1:
* folder? -> [Gmail]/Spam -> inbox
* set flags on a message (in the inbox)
*
* execution path #2:
* folder? -> inbox
* move 600 to [Gmail]/Drafts
* folder? -> [Gmail]/Drafts
* list messages, make sure uid 1 is there
* delete uid 1 from [Gmail]/Drafts
*
* execution path #3:
* folder? -> inbox
* search for subject 'hello 3', make sure it's there
*/
imap.selectMailbox('[Gmail]/Drafts', function(err) {
expect(err).to.not.exist;
imap.setFlags('1', ['\\Seen', '$MyFlag'], {
precheck: function(ctx, next) {
imap.selectMailbox('[Gmail]/Spam', {
ctx: ctx
}, function(err) {
expect(err).to.not.exist;
imap.selectMailbox('inbox', {
ctx: ctx
}, next);
});
}
}, function(err, result) {
expect(err).to.not.exist;
expect(result).to.deep.equal([{
'#': 1,
'flags': ['\\Seen', '$MyFlag']
}]);
proceed();
});
imap.moveMessages(600, '[Gmail]/Drafts', {
byUid: true,
precheck: function(ctx, next) {
imap.selectMailbox('inbox', {
ctx: ctx
}, next);
}
}, function(err, result) {
expect(err).to.not.exist;
expect(result).to.be.true;
imap.deleteMessages(1, {
byUid: true,
precheck: function(ctx1, next1) {
imap.listMessages("1:*", ["uid", "flags", "envelope", "bodystructure", "body.peek[]"], {
ctx: ctx1,
precheck: function(ctx2, next2) {
imap.selectMailbox('[Gmail]/Drafts', {
ctx: ctx2,
precheck: function(ctx, next3) {
next3();
}
}, next2);
}
}, function(err, messages) {
expect(err).to.not.exist;
expect(messages[0].uid).to.equal(1);
next1();
});
}
}, function(err, result) {
expect(err).to.not.exist;
expect(result).to.be.true;
proceed();
});
});
imap.search({
header: ['subject', 'hello 3']
}, {
precheck: function(ctx, next) {
imap.selectMailbox('inbox', {
ctx: ctx
}, next);
},
byUid: true
}, function(err, result) {
expect(err).to.not.exist;
expect(result).to.deep.equal([555]);
proceed();
});
});
function proceed() {
++callCtr === 3 && done();
}
});
it('should error in precheck', function(done) {
/*
* start out in [Gmail]/Drafts
* execution path #1:
* setFlags precheck() should error and never be executed
*
* execution path #2:
* folder? -> inbox
* search for subject 'hello 3', make sure it's there
*/
imap.selectMailbox('[Gmail]/Drafts', function(err) {
expect(err).to.not.exist;
imap.setFlags('1', ['\\Seen', '$MyFlag'], {
precheck: function(ctx, next) {
next(new Error());
}
}, function(err, result) {
expect(err).to.exist;
expect(result).to.not.exist;
proceed();
});
imap.search({
header: ['subject', 'hello 3']
}, {
precheck: function(ctx, next) {
imap.selectMailbox('inbox', {
ctx: ctx
}, next);
},
byUid: true
}, function(err, result) {
expect(err).to.not.exist;
expect(result).to.deep.equal([555]);
proceed();
});
});
function proceed() {
++callCtr === 2 && done();
}
});
});
});

@@ -464,0 +620,0 @@

@@ -610,2 +610,31 @@ 'use strict';

});
it('should run precheck', function(done) {
sinon.stub(client, '_clearIdle');
client._canSend = true;
client._clientQueue = [{
request: {
tag: 'W101',
command: 'TEST',
attributes: [{
type: 'LITERAL',
value: 'abc'
}]
},
precheck: function(ctx) {
expect(ctx).to.exist;
expect(client._canSend).to.be.true;
client._sendRequest = function() {
expect(client._clientQueue.length).to.equal(2);
expect(client._clientQueue[0].tag).to.include('.p');
expect(client._clientQueue[0].request.tag).to.include('.p');
client._clearIdle.restore();
done();
};
client._addToClientQueue({}, undefined, {ctx: ctx});
}
}];
client._sendRequest();
});
});

@@ -612,0 +641,0 @@

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc