smtp-server
Advanced tools
Comparing version 3.4.2 to 3.4.4
120
CHANGELOG.md
# Changelog | ||
## v3.4.4 2018-05-04 | ||
* Enclose punycode calls in try..catch | ||
## v3.4.2 2018-03-16 | ||
* handle missing address in listener handler | ||
* handle missing address in listener handler | ||
## v3.4.0 2017-12-01 | ||
* Added new property `secured` to indicate an TLS server where TLS is handled upstream | ||
* Allow handling TLS after PROXY header | ||
* Added new property `secured` to indicate an TLS server where TLS is handled upstream | ||
* Allow handling TLS after PROXY header | ||
## v3.3.1 2017-11-28 | ||
* Do not choke on overly long reverse DNS call | ||
* Do not choke on overly long reverse DNS call | ||
## v3.3.0 2017-10-05 | ||
* Added new method updateSecureContext({key, cert}) to update TLS options live | ||
* Added new method updateSecureContext({key, cert}) to update TLS options live | ||
## v3.2.0 2017-10-01 | ||
* Return net.listen() value | ||
* Return net.listen() value | ||
## v3.1.0 2017-08-16 | ||
* Added new server option `needsUpgrade` to upgrade sockets to TLS immediately after connection is established. Works with secure: true | ||
* Added new server option `needsUpgrade` to upgrade sockets to TLS immediately after connection is established. Works with secure: true | ||
## v3.0.0 2017-04-06 | ||
* Reverted license back to MIT | ||
* Reverted license back to MIT | ||
## v2.0.3 2017-02-17 | ||
* Expose `secure` state in session | ||
* Expose `secure` state in session | ||
## v2.0.2 2017-02-17 | ||
* Fixad a bug where `server.onConnect(err)` did not close the connection | ||
* Fixad a bug where `server.onConnect(err)` did not close the connection | ||
## v2.0.1 2017-02-04 | ||
* Fixad a bug where `server.on('connect', data)` had missing `data` | ||
* Fixad a bug where `server.on('connect', data)` had missing `data` | ||
## v2.0.0 2017-02-04 | ||
* Changed license from MIT to EUPL-v1.1 | ||
* Rewrite to use ES6, this means at least Node.js v6.0.0 is required to use smtp-server | ||
* Changed license from MIT to EUPL-v1.1 | ||
* Rewrite to use ES6, this means at least Node.js v6.0.0 is required to use smtp-server | ||
## v1.16.1 2016-10-17 | ||
* Allowed rewriting `connect` method | ||
* Allowed rewriting `connect` method | ||
## v1.16.0 2016-10-17 | ||
* Added new method `connect` to pass already established sockets to the server | ||
* Added new method `connect` to pass already established sockets to the server | ||
## v1.15.0 2016-09-23 | ||
* Added new connection property `remotePort` | ||
* Emit 'connect' event when all handshakes (including PROXY) have been completed | ||
* Added new connection property `remotePort` | ||
* Emit 'connect' event when all handshakes (including PROXY) have been completed | ||
## v1.14.2 2016-09-02 | ||
* Fix issue with invalidly resolved IPv4 addresses on IPv6 interface | ||
* Fix issue with invalidly resolved IPv4 addresses on IPv6 interface | ||
## v1.14.1 2016-08-16 | ||
* Ignore connection errors outside transaction | ||
* Ignore connection errors outside transaction | ||
## v1.14.0 2016-08-09 | ||
* Expose connection TLS cipher in the `tlsOptions` property | ||
* Expose connection TLS cipher in the `tlsOptions` property | ||
## v1.13.1 2016-07-29 | ||
* Fixed remoteHostname resolving bug | ||
* Fixed remoteHostname resolving bug | ||
## v1.13.0 2016-07-29 | ||
* Added new option `disableReverseLookup` to skip reverse resolving client hostname on connection | ||
* Added new option `disableReverseLookup` to skip reverse resolving client hostname on connection | ||
## v1.12.0 2016-07-25 | ||
* Added new property for session: `session.transmissionType` that identifies the current transmission (SMTP, ESMTP, ESMTPA etc.) | ||
* Added new property for session: `session.transmissionType` that identifies the current transmission (SMTP, ESMTP, ESMTPA etc.) | ||
## v1.11.2 2016-07-15 | ||
* Do not strip last linebreak | ||
* Do not strip last linebreak | ||
## v1.11.1 2016-07-12 | ||
* this.server.options bug fix #58 (xpepermint) | ||
* this.server.options bug fix #58 (xpepermint) | ||
## v1.11.0 2016-07-07 | ||
* Added support for LMTP protocol. Set `lmtp` option to `true` in order to use it | ||
* Added support for LMTP protocol. Set `lmtp` option to `true` in order to use it | ||
## v1.10.0 2016-07-06 | ||
* Added options `hidePIPELINING`, `hide8BITMIME` and `hideSMTPUTF8` | ||
* Added options `hidePIPELINING`, `hide8BITMIME` and `hideSMTPUTF8` | ||
## v1.9.1 2016-04-26 | ||
* Check that `connection._parser` exists before trying to use it in the DATA handler | ||
* Check that `connection._parser` exists before trying to use it in the DATA handler | ||
## v1.9.0 2016-02-20 | ||
* Added new connection method `onClose` | ||
* Preserve session object, do not re-create it for every transaction | ||
* Added new server option `allowInsecureAuth` | ||
* Added new connection method `onClose` | ||
* Preserve session object, do not re-create it for every transaction | ||
* Added new server option `allowInsecureAuth` | ||
## v1.8.0-beta.0 2016-01-26 | ||
* Fixed a bug with XCLIENT ADDR validation | ||
* Added support for XFORWARD command | ||
* Expose XCLIENT and XFORWARD data for the session object (session.xClient, session.xForward - both are Map objects where uppercase argument name is the key, | ||
eg. session.xClient.get('ADDR') to see the IP address of XCLIENT) | ||
* Fixed a bug with XCLIENT ADDR validation | ||
* Added support for XFORWARD command | ||
* Expose XCLIENT and XFORWARD data for the session object (session.xClient, session.xForward - both are Map objects where uppercase argument name is the key, | ||
eg. session.xClient.get('ADDR') to see the IP address of XCLIENT) | ||
## v1.7.1 2015-10-27 | ||
* Fixed an issue with empty NAME for XCLIENT | ||
* Fixed an issue with empty NAME for XCLIENT | ||
## v1.7.0 2015-10-27 | ||
* Added support for XCLIENT with `useXClient` option | ||
* Fixed an issue with an empty space after EHLO (67acb1534 by AtlasDev) | ||
* Added dummy handlers for KILL, WIZ, SHELL | ||
* Added support for XCLIENT with `useXClient` option | ||
* Fixed an issue with an empty space after EHLO (67acb1534 by AtlasDev) | ||
* Added dummy handlers for KILL, WIZ, SHELL | ||
## v1.6.0 2015-09-29 | ||
* Catch errors thrown by dns.reverse on invalid remoteAddress values | ||
* Added onConnect handler to block unwanted connections (66784aea by jleal52) | ||
* Catch errors thrown by dns.reverse on invalid remoteAddress values | ||
* Added onConnect handler to block unwanted connections (66784aea by jleal52) | ||
## v1.5.2 2015-09-18 | ||
* Fixed regression with node v0.12 where STARTTLS connections were kept hanging around after close | ||
* Fixed regression with node v0.12 where STARTTLS connections were kept hanging around after close | ||
## v1.5.1 2015-09-18 | ||
* Fixed an issue where STARTTLS threw an error | ||
* Fixed an issue where using unknown auth schemes threw an error (a13f0bc8 by farmdog) | ||
* Fixed an issue where STARTTLS threw an error | ||
* Fixed an issue where using unknown auth schemes threw an error (a13f0bc8 by farmdog) | ||
## v1.5.0 2015-08-21 | ||
* Added support for PROXY protocol with `useProxy` option | ||
* Added support for PROXY protocol with `useProxy` option | ||
## v1.4.0 2015-04-30 | ||
* Added support for RFC1870 SIZE extension | ||
* Added support for RFC1870 SIZE extension | ||
## v1.3.1 2015-04-21 | ||
* Added integration tests for CRAM-MD5 authentication | ||
* Exposed SNI support with `sniOptions` optional server option | ||
* Define used protocol for NPN as 'smtp' | ||
* Added integration tests for CRAM-MD5 authentication | ||
* Exposed SNI support with `sniOptions` optional server option | ||
* Define used protocol for NPN as 'smtp' | ||
## v1.3.0 2015-04-21 | ||
* Added CRAM-MD5 authentication support | ||
* Added CRAM-MD5 authentication support | ||
## v1.2.0 2015-03-11 | ||
* Do not allow HTTP requests. If the client tries to send a command that looks like a HTTP request, then disconnect | ||
* Close connection after 10 unrecognized commands | ||
* Close connection after 10 unauthenticated commands | ||
* Close all pending connections after `server.close()` has been called. Default delay to wait is 30 sec. Can be changed with `closeTimeout` option | ||
* Do not allow HTTP requests. If the client tries to send a command that looks like a HTTP request, then disconnect | ||
* Close connection after 10 unrecognized commands | ||
* Close connection after 10 unauthenticated commands | ||
* Close all pending connections after `server.close()` has been called. Default delay to wait is 30 sec. Can be changed with `closeTimeout` option | ||
## v1.1.1 2015-03-11 | ||
* Fixed an issue with parsing MAIL FROM and RCPT TO commands, if there was a space before or after the first colon | ||
* Fixed an issue with parsing MAIL FROM and RCPT TO commands, if there was a space before or after the first colon | ||
## v1.1.0 2015-03-09 | ||
* Added support for `hideSTARTTLS` option that hides STARTTLS while still allowing to use it (useful for integration test scenarios but not for production use) | ||
* Changed `logger` option behavior - if the value is `false` then no logging is used. If the value is missing, then output is logged to console | ||
* Fixed broken examples in the README | ||
* Added support for `hideSTARTTLS` option that hides STARTTLS while still allowing to use it (useful for integration test scenarios but not for production use) | ||
* Changed `logger` option behavior - if the value is `false` then no logging is used. If the value is missing, then output is logged to console | ||
* Fixed broken examples in the README |
@@ -60,3 +60,5 @@ 'use strict'; | ||
'<%s%s@%s>', | ||
String(Math.random()).replace(/^[0.]+/, '').substr(0, 8), // random numbers | ||
String(Math.random()) | ||
.replace(/^[0.]+/, '') | ||
.substr(0, 8), // random numbers | ||
Math.floor(Date.now() / 1000), // timestamp | ||
@@ -67,3 +69,3 @@ this.name // hostname | ||
this._nextHandler = SASL['CRAM-MD5_token'].bind(this, true, challenge); | ||
this.send(334, new Buffer(challenge).toString('base64')); | ||
this.send(334, Buffer.from(challenge).toString('base64')); | ||
return callback(); | ||
@@ -80,3 +82,5 @@ }, | ||
let data = new Buffer(token, 'base64').toString().split('\x00'); | ||
let data = Buffer.from(token, 'base64') | ||
.toString() | ||
.split('\x00'); | ||
@@ -161,3 +165,3 @@ if (data.length !== 3) { | ||
username = new Buffer(username, 'base64').toString(); | ||
username = Buffer.from(username, 'base64').toString(); | ||
@@ -182,3 +186,3 @@ if (!username) { | ||
password = new Buffer(password, 'base64').toString(); | ||
password = Buffer.from(password, 'base64').toString(); | ||
@@ -259,16 +263,19 @@ this._server.onAuth( | ||
// Find username and access token from the input | ||
new Buffer(token, 'base64').toString().split('\x01').forEach(part => { | ||
part = part.split('='); | ||
let key = part.shift().toLowerCase(); | ||
let value = part.join('=').trim(); | ||
Buffer.from(token, 'base64') | ||
.toString() | ||
.split('\x01') | ||
.forEach(part => { | ||
part = part.split('='); | ||
let key = part.shift().toLowerCase(); | ||
let value = part.join('=').trim(); | ||
if (key === 'user') { | ||
username = value; | ||
} else if (key === 'auth') { | ||
value = value.split(/\s+/); | ||
if (value.shift().toLowerCase() === 'bearer') { | ||
accessToken = value.join(' '); | ||
if (key === 'user') { | ||
username = value; | ||
} else if (key === 'auth') { | ||
value = value.split(/\s+/); | ||
if (value.shift().toLowerCase() === 'bearer') { | ||
accessToken = value.join(' '); | ||
} | ||
} | ||
} | ||
}); | ||
}); | ||
@@ -319,3 +326,3 @@ if (!username || !accessToken) { | ||
this._nextHandler = SASL.XOAUTH2_error.bind(this); | ||
this.send(response.responseCode || 334, new Buffer(JSON.stringify(response.data || {})).toString('base64')); | ||
this.send(response.responseCode || 334, Buffer.from(JSON.stringify(response.data || {})).toString('base64')); | ||
return callback(); | ||
@@ -357,3 +364,5 @@ } | ||
let tokenParts = new Buffer(token, 'base64').toString().split(' '); | ||
let tokenParts = Buffer.from(token, 'base64') | ||
.toString() | ||
.split(' '); | ||
let username = tokenParts.shift(); | ||
@@ -368,3 +377,8 @@ let challengeResponse = (tokenParts.shift() || '').toLowerCase(); | ||
let hmac = crypto.createHmac('md5', password); | ||
return hmac.update(challenge).digest('hex').toLowerCase() === challengeResponse; | ||
return ( | ||
hmac | ||
.update(challenge) | ||
.digest('hex') | ||
.toLowerCase() === challengeResponse | ||
); | ||
} | ||
@@ -371,0 +385,0 @@ }, |
@@ -70,3 +70,5 @@ 'use strict'; | ||
// Store remote address for later usage | ||
// Store local and remote addresses for later usage | ||
this.localAddress = (options.localAddress || this._socket.localAddress || '').replace(/^::ffff:/, ''); | ||
this.localPort = Number(options.localPort || this._socket.localPort) || 0; | ||
this.remoteAddress = (options.remoteAddress || this._socket.remoteAddress || '').replace(/^::ffff:/, ''); | ||
@@ -76,2 +78,5 @@ this.remotePort = Number(options.remotePort || this._socket.remotePort) || 0; | ||
// normalize IPv6 addresses | ||
if (this.localAddress && net.isIPv6(this.localAddress)) { | ||
this.localAddress = ipv6normalize(this.localAddress); | ||
} | ||
if (this.remoteAddress && net.isIPv6(this.remoteAddress)) { | ||
@@ -530,3 +535,17 @@ this.remoteAddress = ipv6normalize(this.remoteAddress); | ||
} else { | ||
address = [address[0] || '', '@', punycode.toUnicode(address[1] || '')].join(''); | ||
try { | ||
address = [address[0] || '', '@', punycode.toUnicode(address[1] || '')].join(''); | ||
} catch (E) { | ||
this._server.logger.error( | ||
{ | ||
tnx: 'punycode', | ||
cid: this.id, | ||
user: this.session.user && this.session.user.username | ||
}, | ||
'Failed to process punycode domain "%s". error=%s', | ||
address[1], | ||
E.message | ||
); | ||
address = [address[0] || '', '@', address[1] || ''].join(''); | ||
} | ||
} | ||
@@ -538,5 +557,5 @@ } | ||
: { | ||
address, | ||
args | ||
}; | ||
address, | ||
args | ||
}; | ||
} | ||
@@ -552,2 +571,4 @@ | ||
// reset data that might be overwritten | ||
session.localAddress = this.localAddress; | ||
session.localPort = this.localPort; | ||
session.remoteAddress = this.remoteAddress; | ||
@@ -602,2 +623,4 @@ session.remotePort = this.remotePort; | ||
this.emit('connect', { | ||
localAddress: this.localAddress, | ||
localPort: this.localPort, | ||
remoteAddress: this.remoteAddress, | ||
@@ -1323,3 +1346,3 @@ remotePort: this.remotePort, | ||
if (!this.session.isWizard) { | ||
this.send(500, 'Mere mortals musn\'t mutter that mantra'); | ||
this.send(500, 'Mere mortals must not mutter that mantra'); | ||
return callback(); | ||
@@ -1345,3 +1368,3 @@ } | ||
this.send(500, 'Can\'t kill Mom'); | ||
this.send(500, 'Can not kill Mom'); | ||
callback(); | ||
@@ -1348,0 +1371,0 @@ } |
@@ -285,8 +285,8 @@ 'use strict'; | ||
let address = this.server.address(); | ||
// address will be null if listener is using Unix socket | ||
if (address === null) { | ||
address = {address: null, port: null, family: null}; | ||
address = { address: null, port: null, family: null }; | ||
} | ||
this.logger.info( | ||
@@ -431,3 +431,16 @@ // | ||
_normalizeHostname(hostname) { | ||
return punycode.toUnicode((hostname || '').toString().trim()).toLowerCase(); | ||
try { | ||
hostname = punycode.toUnicode((hostname || '').toString().trim()).toLowerCase(); | ||
} catch (E) { | ||
this.logger.error( | ||
{ | ||
tnx: 'punycode' | ||
}, | ||
'Failed to process punycode domain "%s". error=%s', | ||
hostname, | ||
E.message | ||
); | ||
} | ||
return hostname; | ||
} | ||
@@ -434,0 +447,0 @@ |
@@ -111,3 +111,3 @@ 'use strict'; | ||
if (this._dataMode) { | ||
buf = new Buffer(data.substr(pos), 'binary'); | ||
buf = Buffer.from(data.substr(pos), 'binary'); | ||
this._remainder = ''; | ||
@@ -128,3 +128,3 @@ return this._write(buf, 'buffer', done); | ||
this.oncommand(new Buffer(line, 'binary'), readLine); | ||
this.oncommand(Buffer.from(line, 'binary'), readLine); | ||
}; | ||
@@ -144,3 +144,3 @@ | ||
let i; | ||
let endseq = new Buffer('\r\n.\r\n'); | ||
let endseq = Buffer.from('\r\n.\r\n'); | ||
let len; | ||
@@ -158,3 +158,3 @@ let handled; | ||
// check if the data does not start with the end terminator | ||
if (!this.dataBytes && len >= 3 && Buffer.compare(chunk.slice(0, 3), new Buffer('.\r\n')) === 0) { | ||
if (!this.dataBytes && len >= 3 && Buffer.compare(chunk.slice(0, 3), Buffer.from('.\r\n')) === 0) { | ||
this._endDataMode(false, chunk.slice(3), done); | ||
@@ -241,3 +241,3 @@ return; | ||
this._remainder = ''; | ||
this.oncommand(new Buffer(line, 'binary')); | ||
this.oncommand(Buffer.from(line, 'binary')); | ||
} | ||
@@ -244,0 +244,0 @@ } |
{ | ||
"name": "smtp-server", | ||
"version": "3.4.2", | ||
"version": "3.4.4", | ||
"description": "Create custom SMTP servers on the fly", | ||
@@ -12,5 +12,5 @@ "main": "lib/smtp-server.js", | ||
"dependencies": { | ||
"base32.js": "^0.1.0", | ||
"ipv6-normalize": "^1.0.1", | ||
"nodemailer": "^4.6.3" | ||
"base32.js": "0.1.0", | ||
"ipv6-normalize": "1.0.1", | ||
"nodemailer": "4.6.4" | ||
}, | ||
@@ -24,4 +24,4 @@ "devDependencies": { | ||
"grunt-mocha-test": "^0.13.3", | ||
"mocha": "^5.0.4", | ||
"pem": "^1.12.3" | ||
"mocha": "^5.1.1", | ||
"pem": "^1.12.5" | ||
}, | ||
@@ -35,5 +35,3 @@ "repository": { | ||
}, | ||
"keywords": [ | ||
"SMTP" | ||
], | ||
"keywords": ["SMTP"], | ||
"engines": { | ||
@@ -40,0 +38,0 @@ "node": ">=6.0.0" |
@@ -16,3 +16,3 @@ /* eslint no-unused-expressions:0, prefer-arrow-callback: 0 */ | ||
let expecting = [new Buffer([0x43, 0x4d, 0x44, 0x31]), new Buffer([0x43, 0x4d, 0x44, 0x32]), new Buffer([0x43, 0x4d, 0x44, 0x33])]; | ||
let expecting = [Buffer.from([0x43, 0x4d, 0x44, 0x31]), Buffer.from([0x43, 0x4d, 0x44, 0x32]), Buffer.from([0x43, 0x4d, 0x44, 0x33])]; | ||
@@ -19,0 +19,0 @@ stream.oncommand = function(cmd, cb) { |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
156621
3825
+ Addednodemailer@4.6.4(transitive)
- Removednodemailer@4.7.0(transitive)
Updatedbase32.js@0.1.0
Updatedipv6-normalize@1.0.1
Updatednodemailer@4.6.4