|
|
@ -1,4 +1,5 @@
|
|
|
|
var assert = require('assert'),
|
|
|
|
var assert = require('assert'),
|
|
|
|
|
|
|
|
tls = require('tls'),
|
|
|
|
isDate = require('util').isDate,
|
|
|
|
isDate = require('util').isDate,
|
|
|
|
inspect = require('util').inspect,
|
|
|
|
inspect = require('util').inspect,
|
|
|
|
inherits = require('util').inherits,
|
|
|
|
inherits = require('util').inherits,
|
|
|
@ -118,26 +119,22 @@ ImapConnection.prototype.connect = function(loginCb) {
|
|
|
|
requests = state.requests,
|
|
|
|
requests = state.requests,
|
|
|
|
indata = state.indata;
|
|
|
|
indata = state.indata;
|
|
|
|
|
|
|
|
|
|
|
|
state.conn = new Socket();
|
|
|
|
var socket = state.conn = new Socket();
|
|
|
|
state.conn.setKeepAlive(true);
|
|
|
|
socket.setKeepAlive(true);
|
|
|
|
|
|
|
|
socket.setTimeout(0);
|
|
|
|
|
|
|
|
|
|
|
|
if (this._options.secure) {
|
|
|
|
if (this._options.secure)
|
|
|
|
// TODO: support STARTTLS
|
|
|
|
socket = tls.connect({ socket: state.conn }, onconnect);
|
|
|
|
state.conn.cleartext = utils.setSecure(state.conn);
|
|
|
|
else
|
|
|
|
state.conn.on('secure', function() {
|
|
|
|
state.conn.once('connect', onconnect);
|
|
|
|
state.connected = true;
|
|
|
|
|
|
|
|
self.debug&&self.debug('[connection] Secure connection made.');
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
} else
|
|
|
|
|
|
|
|
state.conn.cleartext = state.conn;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
state.conn.on('connect', function() {
|
|
|
|
function onconnect() {
|
|
|
|
|
|
|
|
state.conn = socket; // re-assign for secure connections
|
|
|
|
state.connected = true;
|
|
|
|
state.connected = true;
|
|
|
|
state.authenticated = false;
|
|
|
|
state.authenticated = false;
|
|
|
|
self.debug&&self.debug('[connection] Connected to host.');
|
|
|
|
self.debug&&self.debug('[connection] Connected to host.');
|
|
|
|
state.conn.cleartext.write('');
|
|
|
|
|
|
|
|
state.status = STATES.NOAUTH;
|
|
|
|
state.status = STATES.NOAUTH;
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
state.conn.on('end', function() {
|
|
|
|
state.conn.on('end', function() {
|
|
|
|
state.connected = false;
|
|
|
|
state.connected = false;
|
|
|
@ -146,16 +143,6 @@ ImapConnection.prototype.connect = function(loginCb) {
|
|
|
|
self.emit('end');
|
|
|
|
self.emit('end');
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
function errorHandler(err) {
|
|
|
|
|
|
|
|
clearTimeout(state.tmrConn);
|
|
|
|
|
|
|
|
if (state.status === STATES.NOCONNECT)
|
|
|
|
|
|
|
|
loginCb(new Error('Unable to connect. Reason: ' + err));
|
|
|
|
|
|
|
|
self.emit('error', err);
|
|
|
|
|
|
|
|
self.debug&&self.debug('[connection] Error occurred: ' + err);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
state.conn.cleartext.on('error', errorHandler);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
state.conn.on('close', function(had_error) {
|
|
|
|
state.conn.on('close', function(had_error) {
|
|
|
|
self._reset();
|
|
|
|
self._reset();
|
|
|
|
requests = state.requests;
|
|
|
|
requests = state.requests;
|
|
|
@ -165,7 +152,15 @@ ImapConnection.prototype.connect = function(loginCb) {
|
|
|
|
self.emit('close', had_error);
|
|
|
|
self.emit('close', had_error);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
state.conn.on('ready', function() {
|
|
|
|
state.conn.on('error', function(err) {
|
|
|
|
|
|
|
|
clearTimeout(state.tmrConn);
|
|
|
|
|
|
|
|
if (state.status === STATES.NOCONNECT)
|
|
|
|
|
|
|
|
loginCb(new Error('Unable to connect. Reason: ' + err));
|
|
|
|
|
|
|
|
self.emit('error', err);
|
|
|
|
|
|
|
|
self.debug&&self.debug('[connection] Error occurred: ' + err);
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
socket.on('ready', function() {
|
|
|
|
var checkedNS = false;
|
|
|
|
var checkedNS = false;
|
|
|
|
var reentry = function(err) {
|
|
|
|
var reentry = function(err) {
|
|
|
|
if (err) {
|
|
|
|
if (err) {
|
|
|
@ -236,6 +231,8 @@ ImapConnection.prototype.connect = function(loginCb) {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
socket.on('data', ondata);
|
|
|
|
|
|
|
|
|
|
|
|
function ondata(b) {
|
|
|
|
function ondata(b) {
|
|
|
|
b.p || (b.p = 0);
|
|
|
|
b.p || (b.p = 0);
|
|
|
|
if (b.length === 0 || b.p >= b.length) return;
|
|
|
|
if (b.length === 0 || b.p >= b.length) return;
|
|
|
@ -705,24 +702,23 @@ ImapConnection.prototype.connect = function(loginCb) {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
state.conn.cleartext.on('data', ondata);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
state.conn.connect(this._options.port, this._options.host);
|
|
|
|
state.conn.connect(this._options.port, this._options.host);
|
|
|
|
|
|
|
|
|
|
|
|
state.tmrConn = setTimeout(function() {
|
|
|
|
state.tmrConn = setTimeout(function() {
|
|
|
|
state.conn.destroy();
|
|
|
|
state.conn.destroy();
|
|
|
|
|
|
|
|
state.conn = undefined;
|
|
|
|
loginCb(new Error('Connection timed out'));
|
|
|
|
loginCb(new Error('Connection timed out'));
|
|
|
|
}, this._options.connTimeout);
|
|
|
|
}, this._options.connTimeout);
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
ImapConnection.prototype.isAuthenticated = function() {
|
|
|
|
|
|
|
|
return this.authenticated;
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ImapConnection.prototype.logout = function(cb) {
|
|
|
|
ImapConnection.prototype.logout = function(cb) {
|
|
|
|
|
|
|
|
var self = this;
|
|
|
|
if (this._state.status >= STATES.NOAUTH) {
|
|
|
|
if (this._state.status >= STATES.NOAUTH) {
|
|
|
|
this._send('LOGOUT', cb);
|
|
|
|
this._send('LOGOUT', function(err) {
|
|
|
|
this._state.conn.end();
|
|
|
|
self._state.conn.end();
|
|
|
|
|
|
|
|
if (typeof cb === 'function')
|
|
|
|
|
|
|
|
cb(err);
|
|
|
|
|
|
|
|
});
|
|
|
|
if (cb === true)
|
|
|
|
if (cb === true)
|
|
|
|
this._state.conn.removeAllListeners();
|
|
|
|
this._state.conn.removeAllListeners();
|
|
|
|
} else
|
|
|
|
} else
|
|
|
@ -851,8 +847,8 @@ ImapConnection.prototype.append = function(data, options, cb) {
|
|
|
|
this._send(cmd, function(err) {
|
|
|
|
this._send(cmd, function(err) {
|
|
|
|
if (err || step++ === 2)
|
|
|
|
if (err || step++ === 2)
|
|
|
|
return cb(err);
|
|
|
|
return cb(err);
|
|
|
|
self._state.conn.cleartext.write(data);
|
|
|
|
self._state.conn.write(data);
|
|
|
|
self._state.conn.cleartext.write(CRLF);
|
|
|
|
self._state.conn.write(CRLF);
|
|
|
|
self.debug&&self.debug('\n==> ' + inspect(data.toString()) + '\n');
|
|
|
|
self.debug&&self.debug('\n==> ' + inspect(data.toString()) + '\n');
|
|
|
|
});
|
|
|
|
});
|
|
|
|
};
|
|
|
|
};
|
|
|
@ -1484,9 +1480,9 @@ ImapConnection.prototype._send = function(cmdstr, cb, bypass) {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (cmd !== 'IDLE' && cmd !== 'DONE')
|
|
|
|
if (cmd !== 'IDLE' && cmd !== 'DONE')
|
|
|
|
prefix = 'A' + (++this._state.curId) + ' ';
|
|
|
|
prefix = 'A' + (++this._state.curId) + ' ';
|
|
|
|
this._state.conn.cleartext.write(prefix);
|
|
|
|
this._state.conn.write(prefix);
|
|
|
|
this._state.conn.cleartext.write(cmd);
|
|
|
|
this._state.conn.write(cmd);
|
|
|
|
this._state.conn.cleartext.write(CRLF);
|
|
|
|
this._state.conn.write(CRLF);
|
|
|
|
this.debug&&this.debug('\n==> ' + prefix + cmd + '\n');
|
|
|
|
this.debug&&this.debug('\n==> ' + prefix + cmd + '\n');
|
|
|
|
if (this._state.requests[0]
|
|
|
|
if (this._state.requests[0]
|
|
|
|
&& (this._state.requests[0].cmd === 'EXAMINE'
|
|
|
|
&& (this._state.requests[0].cmd === 'EXAMINE'
|
|
|
|