New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

imap-client

Package Overview
Dependencies
Maintainers
3
Versions
26
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

imap-client - npm Package Compare versions

Comparing version 0.11.1 to 0.12.0

2

package.json
{
"name": "imap-client",
"version": "0.11.1",
"version": "0.12.0",
"scripts": {

@@ -5,0 +5,0 @@ "pretest": "dir=$(pwd) && cd node_modules/browserbox/node_modules/tcp-socket/node_modules/node-forge/ && npm install && npm run minify && cd $dir",

@@ -5,2 +5,4 @@ # imap-client

Needs ES6 Promises, [supply polyfills where necessary](https://github.com/jakearchibald/es6-promise).
## API

@@ -26,3 +28,3 @@

### #login(callback) and #logout(callback)
### #login() and #logout()

@@ -32,12 +34,12 @@ Log in to an IMAP Session. No-op if already logged in.

```
imap.login(function() {
imap.login().then(function() {
// yay, we’re logged in
})
imap.logout(function() {
// yay, we’re logged out
});
imap.logout().then(function() {
// yay, we’re logged out
});
```
### #listenForChanges(callback) and #stopListeningForChanges(callback)
### #listenForChanges() and #stopListeningForChanges()

@@ -49,15 +51,28 @@ Set up a connection dedicated to listening for changes published by the IMAP server on one specific inbox.

path: ‘mailboxpath’
}, function() {
}).then(function() {
// the audience is listening
...
})
imap.stopListeningForChanges(function() {
// we’re not listening anymore
});
imap.stopListeningForChanges().then(function() {
// we’re not listening anymore
})
```
### #listWellKnownFolders(callback)
### #listWellKnownFolders()
Lists folders, grouped to folders that are in the following categories: Inbox, Drafts, All, Flagged, Sent, Trash, Junk, Archive, Other.
### #createFolder(path)
Creates a folder...
```
imap.createFolder({
path: ['foo', 'bar']
}).then(function() {
// folder created
})
```
### #search(options, callback)

@@ -69,7 +84,7 @@

imap.search({
answered: true,
unread: true,
header: ['X-Foobar', '123qweasdzxc']
}, function(error, uids) {
console.log(‘uids: ‘ + uids.join(‘, ‘))
answered: true,
unread: true,
header: ['X-Foobar', '123qweasdzxc']
}).then(function(uids) {
console.log(‘uids: ‘ + uids.join(‘, ‘))
});

@@ -84,6 +99,6 @@ ```

imap.listMessages({
path: ‘path’, the folder's path
firstUid: 15, (optional) the uid of the first messagem defaults to 1
lastUid: 30 (optional) the uid of the last message, defaults to ‘*’
}, function(error, messages) {})
path: ‘path’, the folder's path
firstUid: 15, (optional) the uid of the first messagem defaults to 1
lastUid: 30 (optional) the uid of the last message, defaults to ‘*’
}).then(function(messages) {})
```

@@ -111,6 +126,6 @@

imap.getBodyParts({
path: 'foo/bar',
uid: someMessage.uid,
bodyParts: someMessage.bodyParts
}, function(err) {
path: 'foo/bar',
uid: someMessage.uid,
bodyParts: someMessage.bodyParts
}).then(function() {
// all done, bodyparts can now be fed to the mailreader

@@ -130,3 +145,3 @@ })

answered: true/false/undefined // (optional) Marks the message as answered, no action if omitted
}, function (error) {
}).then(function(
// all done

@@ -145,3 +160,3 @@ });

destination: 'bla/bli' // the destination folder
}, function (error) {
}).then(function(
// all done

@@ -159,3 +174,3 @@ });

message: '...' // RFC-2822 compliant string
}, function (error) {
}).then(function(
// all done

@@ -173,3 +188,3 @@ });

uid: someMessage.uid, // the message's uid
}, function (error) {
}).then(function(
// all done

@@ -190,16 +205,16 @@ });

imap.onSyncUpdate = function(options) {
var updatedMesages = options.list,
updatesMailbox = options.path
var updatedMesages = options.list,
updatesMailbox = options.path
if (options.type === SYNC_TYPE_NEW) {
// new messages available on imap
// updatedMesages is an array of the newly available UIDs
// updatedMesages is an array of the newly available UIDs
} else if (options.type === SYNC_TYPE_DELETED) {
// messages have been deleted
// updatedMesages is an array of the deleted UIDs
// updatedMesages is an array of the deleted UIDs
} else if (options.type === SYNC_TYPE_MSGS) {
// NB! several possible reasons why this could be called.
// updatedMesages is an array of objects
// updatedMesages is an array of objects
// if an object in the array has uid value and flags array, it had a possible flag update
}
}
};

@@ -206,0 +221,0 @@ ```

@@ -521,8 +521,2 @@ (function(factory) {

if (!self._loggedIn) {
return new Promise(function() {
throw new Error('Can not list well known folders, cause: Not logged in!');
});
}
var wellKnownFolders = {

@@ -542,6 +536,9 @@ Inbox: [],

return self._client.listMailboxes().then(function(mailbox) {
return self._checkOnline().then(function() {
return self._client.listMailboxes();
}).then(function(mailbox) {
axe.debug(DEBUG_TAG, 'folder list received!');
walkMailbox(mailbox);
return wellKnownFolders;
}).catch(function(error) {

@@ -564,2 +561,3 @@ axe.error(DEBUG_TAG, 'error listing folders: ' + error + '\n' + error.stack);

folder.type = 'Inbox';
self._delimiter = mailbox.delimiter;
wellKnownFolders.Inbox.push(folder);

@@ -601,2 +599,79 @@ } else if (mailbox.specialUse === '\\Drafts') {

/**
* Creates a folder with the provided path under the personal namespace
*
* @param {String or Array} options.path
* The folder's path. If path is a hierarchy as an array (e.g. ['foo', 'bar', 'baz'] to create foo/bar/bar),
* will create a hierarchy with all intermediate folders if needed.
* @returns {Promise<Array>} Array of uids for messages matching the search terms
*/
ImapClient.prototype.createFolder = function(options) {
var self = this,
path = options.path;
if (!Array.isArray(path)) {
path = [path];
}
return self._checkOnline().then(function() {
// spare the check
if (typeof self._delimiter !== 'undefined' && typeof self._prefix !== 'undefined') {
return;
}
// try to get the namespace prefix and delimiter
return self._client.listNamespaces().then(function(namespaces) {
if (namespaces && namespaces.personal && namespaces.personal[0]) {
// personal namespace is available
self._delimiter = namespaces.personal[0].delimiter;
self._prefix = namespaces.personal[0].prefix.split(self._delimiter).shift();
return;
}
// no namespaces, falling back to empty prefix
self._prefix = "";
// if we already have the delimiter, there's no need to retrieve the lengthy folder list
if (self._delimiter) {
return;
}
// find the delimiter by listing the folders
return self._client.listMailboxes().then(function(response) {
findDelimiter(response);
});
});
}).then(function() {
if (!self._delimiter) {
throw new Error('Could not determine delimiter for mailbox hierarchy');
}
if (self._prefix) {
path.unshift(self._prefix);
}
// create path [prefix/]foo/bar/baz
return self._client.createMailbox(path.join(self._delimiter));
}).catch(function(error) {
axe.error(DEBUG_TAG, 'error creating folder ' + options.path + ': ' + error + '\n' + error.stack);
throw error;
});
// Helper function to find the hierarchy delimiter from a client.listMailboxes() response
function findDelimiter(mailbox) {
if ((mailbox.path || '').toUpperCase() === 'INBOX') {
// found the INBOX, use its hierarchy delimiter, we're done.
self._delimiter = mailbox.delimiter;
return;
}
if (mailbox.children) {
// walk the child mailboxes recursively
mailbox.children.forEach(findDelimiter);
}
}
};
/**
* Returns the uids of messages containing the search terms in the options

@@ -614,8 +689,2 @@ * @param {String} options.path The folder's path

if (!self._loggedIn) {
return new Promise(function() {
throw new Error('Can not search messages, cause: Not logged in!');
});
}
var query = {},

@@ -651,3 +720,5 @@ queryOptions = {

axe.debug(DEBUG_TAG, 'searching in ' + options.path + ' for ' + Object.keys(query).join(','));
return client.search(query, queryOptions).then(function(uids) {
return self._checkOnline().then(function() {
return client.search(query, queryOptions);
}).then(function(uids) {
axe.debug(DEBUG_TAG, 'searched in ' + options.path + ' for ' + Object.keys(query).join(',') + ': ' + uids);

@@ -672,8 +743,2 @@ return uids;

if (!self._loggedIn) {
return new Promise(function() {
throw new Error('Can not list messages, cause: Not logged in!');
});
}
var interval = (options.firstUid || 1) + ':' + (options.lastUid || '*'),

@@ -692,3 +757,5 @@ query = ['uid', 'bodystructure', 'flags', 'envelope', 'body.peek[header.fields (references)]'],

axe.debug(DEBUG_TAG, 'listing messages in ' + options.path + ' for interval ' + interval);
return self._client.listMessages(interval, query, queryOptions).then(function(messages) {
return self._checkOnline().then(function() {
return self._client.listMessages(interval, query, queryOptions);
}).then(function(messages) {
// a message without uid will be ignored as malformed

@@ -763,8 +830,2 @@ messages = messages.filter(function(message) {

if (!self._loggedIn) {
return new Promise(function() {
throw new Error('Can not get bodyParts for uid ' + options.uid + ' in folder ' + options.path + ', cause: Not logged in!');
});
}
// formulate a query for each text part. for part 2.1 to be parsed, we need 2.1.MIME and 2.1

@@ -791,3 +852,5 @@ bodyParts.forEach(function(bodyPart) {

axe.debug(DEBUG_TAG, 'retrieving body parts for uid ' + options.uid + ' in folder ' + options.path + ': ' + query);
return self._client.listMessages(interval, query, queryOptions).then(function(messages) {
return self._checkOnline().then(function() {
return self._client.listMessages(interval, query, queryOptions);
}).then(function(messages) {
axe.debug(DEBUG_TAG, 'successfully retrieved body parts for uid ' + options.uid + ' in folder ' + options.path + ': ' + query);

@@ -847,8 +910,2 @@

if (!self._loggedIn) {
return new Promise(function() {
throw new Error('Can not update flags, cause: Not logged in!');
});
}
if (options.unread === true) {

@@ -886,8 +943,10 @@ remove.push(READ_FLAG);

axe.debug(DEBUG_TAG, 'updating flags for uid ' + options.uid + ' in folder ' + options.path + ': ' + (remove.length > 0 ? (' removing ' + remove) : '') + (add.length > 0 ? (' adding ' + add) : ''));
return new Promise(function(resolve) {
if (add.length > 0) {
resolve(self._client.setFlags(interval, queryAdd, queryOptions));
} else {
resolve();
}
return self._checkOnline().then(function() {
return new Promise(function(resolve) {
if (add.length > 0) {
resolve(self._client.setFlags(interval, queryAdd, queryOptions));
} else {
resolve();
}
});
}).then(function() {

@@ -921,10 +980,6 @@ if (remove.length > 0) {

if (!self._loggedIn) {
return new Promise(function() {
throw new Error('Cannot move message, cause: Not logged in!');
});
}
axe.debug(DEBUG_TAG, 'moving uid ' + options.uid + ' from ' + options.path + ' to ' + options.destination);
return self._client.moveMessages(interval, options.destination, queryOptions).then(function() {
return self._checkOnline().then(function() {
return self._client.moveMessages(interval, options.destination, queryOptions);
}).then(function() {
axe.debug(DEBUG_TAG, 'successfully moved uid ' + options.uid + ' from ' + options.path + ' to ' + options.destination);

@@ -947,10 +1002,6 @@ }).catch(function(error) {

if (!self._loggedIn) {
return new Promise(function() {
throw new Error('Cannot move message, cause: Not logged in!');
});
}
axe.debug(DEBUG_TAG, 'uploading a message of ' + options.message.length + ' bytes to ' + options.path);
return self._client.upload(options.path, options.message).then(function() {
return self._checkOnline().then(function() {
return self._client.upload(options.path, options.message);
}).then(function() {
axe.debug(DEBUG_TAG, 'successfully uploaded message to ' + options.path);

@@ -978,10 +1029,6 @@ }).catch(function(error) {

if (!self._loggedIn) {
return new Promise(function() {
throw new Error('Cannot delete message, cause: Not logged in!');
});
}
axe.debug(DEBUG_TAG, 'deleting uid ' + options.uid + ' from ' + options.path);
return self._client.deleteMessages(interval, queryOptions).then(function() {
return self._checkOnline().then(function() {
return self._client.deleteMessages(interval, queryOptions);
}).then(function() {
axe.debug(DEBUG_TAG, 'successfully deleted uid ' + options.uid + ' from ' + options.path);

@@ -1019,2 +1066,14 @@ }).catch(function(error) {

ImapClient.prototype._checkOnline = function() {
var self = this;
return new Promise(function(resolve) {
if (!self._loggedIn) {
throw new Error('Not logged in!');
}
resolve();
});
};
/*

@@ -1021,0 +1080,0 @@ * Mime Tree Handling

@@ -94,3 +94,20 @@ (function(factory) {

it('should create folder hierarchy', function(done) {
ic.createFolder({
path: ['bar', 'baz']
}).then(function() {
return ic.listWellKnownFolders();
}).then(function(folders) {
var hasFoo = false;
folders.Other.forEach(function(folder) {
hasFoo = hasFoo || folder.path === 'INBOX.bar.baz';
});
expect(hasFoo).to.be.true;
expect(ic._delimiter).to.exist;
expect(ic._prefix).to.exist;
expect(hasFoo).to.be.true;
}).then(done);
});
it('should upload Message', function(done) {

@@ -97,0 +114,0 @@ var msg = 'MIME-Version: 1.0\r\nDate: Wed, 9 Jul 2014 15:07:47 +0200\r\nDelivered-To: test@test.com\r\nMessage-ID: <CAHftYYQo=5fqbtnv-DazXhL2j5AxVP1nWarjkztn-N9SV91Z2w@mail.gmail.com>\r\nSubject: integration test\r\nFrom: Test Test <test@test.com>\r\nTo: Test Test <test@test.com>\r\nContent-Type: text/plain; charset=UTF-8\r\n\r\nintegration test',

@@ -97,3 +97,2 @@ 'use strict';

var invocations = 0; // counts the message updates
ic._maxUpdateSize = 1;

@@ -103,8 +102,5 @@ ic.onSyncUpdate = function(options) {

expect(options.list.length).to.equal(1);
expect(options.list.length).to.equal(6);
expect(options.type).to.equal('new');
if (invocations === 6) {
done();
}
done();
};

@@ -151,2 +147,36 @@

it('should create folder', function(done) {
ic.createFolder({
path: 'foo'
}).then(function() {
return ic.listWellKnownFolders();
}).then(function(folders) {
var hasFoo = false;
folders.Other.forEach(function(folder) {
hasFoo = hasFoo || folder.path === 'foo';
});
expect(hasFoo).to.be.true;
expect(ic._delimiter).to.exist;
expect(ic._prefix).to.exist;
}).then(done);
});
it('should create folder hierarchy', function(done) {
ic.createFolder({
path: ['bar', 'baz']
}).then(function() {
return ic.listWellKnownFolders();
}).then(function(folders) {
var hasFoo = false;
folders.Other.forEach(function(folder) {
hasFoo = hasFoo || folder.path === 'bar/baz';
});
expect(hasFoo).to.be.true;
}).then(done);
});
it('should search messages for header', function(done) {

@@ -153,0 +183,0 @@ ic.search({

@@ -28,3 +28,2 @@ (function(factory) {

expect(imap._client).to.equal(bboxMock);
expect(imap._maxUpdateSize).to.equal(0);

@@ -187,2 +186,99 @@ imap._loggedIn = true;

describe('#createFolder', function() {
it('should create folder with namespaces', function(done) {
bboxMock.listNamespaces.returns(resolves({
"personal": [{
"prefix": "BLA/",
"delimiter": "/"
}],
"users": false,
"shared": false
}));
bboxMock.createMailbox.withArgs('BLA/foo').returns(resolves());
imap.createFolder({
path: 'foo'
}).then(function() {
expect(bboxMock.listNamespaces.calledOnce).to.be.true;
expect(bboxMock.createMailbox.calledOnce).to.be.true;
expect(imap._delimiter).to.exist;
expect(imap._prefix).to.exist;
done();
});
});
it('should create folder without namespaces', function(done) {
bboxMock.listNamespaces.returns(resolves());
bboxMock.listMailboxes.returns(resolves({
"root": true,
"children": [{
"name": "INBOX",
"delimiter": "/",
"path": "INBOX"
}]
}));
bboxMock.createMailbox.withArgs('foo').returns(resolves());
imap.createFolder({
path: 'foo'
}).then(function() {
expect(bboxMock.listNamespaces.calledOnce).to.be.true;
expect(bboxMock.createMailbox.calledOnce).to.be.true;
expect(imap._delimiter).to.exist;
expect(imap._prefix).to.exist;
done();
});
});
it('should create folder hierarchy with namespaces', function(done) {
bboxMock.listNamespaces.returns(resolves({
"personal": [{
"prefix": "BLA/",
"delimiter": "/"
}],
"users": false,
"shared": false
}));
bboxMock.createMailbox.withArgs('foo/bar').returns(resolves());
bboxMock.createMailbox.withArgs('foo/baz').returns(resolves());
imap.createFolder({
path: ['foo', 'bar']
}).then(function() {
return imap.createFolder({
path: ['foo', 'baz']
});
}).then(function() {
expect(bboxMock.listNamespaces.calledOnce).to.be.true;
expect(bboxMock.createMailbox.calledTwice).to.be.true;
expect(imap._delimiter).to.exist;
expect(imap._prefix).to.exist;
done();
});
});
it('should create folder hierarchy without namespaces', function(done) {
bboxMock.listNamespaces.returns(resolves());
bboxMock.listMailboxes.returns(resolves({
"root": true,
"children": [{
"name": "INBOX",
"delimiter": "/",
"path": "INBOX"
}]
}));
bboxMock.createMailbox.withArgs('foo').returns(resolves());
imap.createFolder({
path: ['foo', 'bar']
}).then(function() {
expect(bboxMock.listNamespaces.calledOnce).to.be.true;
expect(bboxMock.createMailbox.calledOnce).to.be.true;
expect(imap._delimiter).to.exist;
expect(imap._prefix).to.exist;
done();
});
});
});
describe('#search', function() {

@@ -442,3 +538,8 @@ it('should search answered', function(done) {

path: 'foobar',
uid: 123
uid: 123,
bodyParts: [{
partNumber: '1'
}, {
partNumber: '2'
}]
}).catch(function() {

@@ -455,3 +556,3 @@ done();

}).returns(resolves());
bboxMock.setFlags.withArgs('123:123', {

@@ -657,3 +758,5 @@ remove: ['\\Seen']

it('should switch mailboxes', function(done) {
bboxMock.selectMailbox.withArgs('qweasdzxc', {ctx: ctx}).yields();
bboxMock.selectMailbox.withArgs('qweasdzxc', {
ctx: ctx
}).yields();
imap._ensurePath('qweasdzxc')(ctx, function(err) {

@@ -667,3 +770,5 @@ expect(err).to.not.exist;

it('should error during switching mailboxes', function(done) {
bboxMock.selectMailbox.withArgs('qweasdzxc', {ctx: ctx}).yields(new Error());
bboxMock.selectMailbox.withArgs('qweasdzxc', {
ctx: ctx
}).yields(new Error());
imap._ensurePath('qweasdzxc')(ctx, function(err) {

@@ -670,0 +775,0 @@ expect(err).to.exist;

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