Socket
Socket
Sign inDemoInstall

smtp-server

Package Overview
Dependencies
0
Maintainers
1
Versions
65
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 1.2.0 to 1.3.0

23

examples/server.js

@@ -26,12 +26,25 @@ 'use strict';

// By default only PLAIN and LOGIN are enabled
authMethods: ['PLAIN', 'LOGIN', 'CRAM-MD5'],
// Setup authentication
// Allow only users with username 'testuser' and password 'testpass'
onAuth: function(auth, session, callback) {
if (auth.username !== 'testuser' && auth.password !== 'testpass') {
callback(new Error('Authentication failed'));
var username = 'testuser';
var password = 'testpass';
// check username and password
if (auth.username === username &&
(
auth.method === 'CRAM-MD5' ?
auth.validatePassword(password) : // if cram-md5, validate challenge response
auth.password === password // for other methods match plaintext passwords
)
) {
return callback(null, {
user: 'userdata' // value could be an user id, or an user object etc. This value can be accessed from session.user afterwards
});
}
return callback(null, {
user: 'userdata' // value could be an user id, or an user object etc. This value can be accessed from session.user afterwards
});
return callback(new Error('Authentication failed'));
},

@@ -38,0 +51,0 @@

'use strict';
var util = require('util');
var crypto = require('crypto');
var SASL = module.exports = {

@@ -50,2 +53,19 @@

'SASL_CRAM-MD5': function(args, callback) {
if (args.length) {
this.send(501, 'Error: syntax: AUTH CRAM-MD5');
return callback();
}
var challenge = util.format('<%s%s@%s>',
String(Math.random()).replace(/^[0\.]+/, '').substr(0, 8), // random numbers
Math.floor(Date.now() / 1000), // timestamp
this.name // hostname
);
this._nextHandler = SASL['CRAM-MD5_token'].bind(this, true, challenge);
this.send(334, new Buffer(challenge).toString('base64'));
return callback();
},
PLAIN_token: function(canAbort, token, callback) {

@@ -69,3 +89,3 @@ token = (token || '').toString().trim();

this._server.logger.info('[%s] Trying to authenticate "%s"', this._id, username);
this._server.logger.info('[%s] Trying to authenticate "%s" with %s', this._id, username, 'PLAIN');
this._server.onAuth({

@@ -88,2 +108,3 @@ method: 'PLAIN',

this._server.logger.info('[%s] User "%s" authenticated');
this.session.user = response.user;

@@ -127,3 +148,3 @@

this._server.logger.info('[%s] Trying to authenticate "%s"', this._id, username);
this._server.logger.info('[%s] Trying to authenticate "%s" with %s', this._id, username, 'LOGIN');
this._server.onAuth({

@@ -146,2 +167,3 @@ method: 'LOGIN',

this._server.logger.info('[%s] User "%s" authenticated');
this.session.user = response.user;

@@ -187,3 +209,3 @@

this._server.logger.info('[%s] Trying to authenticate "%s"', this._id, username);
this._server.logger.info('[%s] Trying to authenticate "%s" with %s', this._id, username, 'XOAUTH2');
this._server.onAuth({

@@ -207,2 +229,3 @@ method: 'XOAUTH2',

this._server.logger.info('[%s] User "%s" authenticated');
this.session.user = response.user;

@@ -219,3 +242,45 @@

return callback();
},
'CRAM-MD5_token': function(canAbort, challenge, token, callback) {
token = (token || '').toString().trim();
if (canAbort && token === '*') {
this.send(501, 'Authentication aborted');
return callback();
}
var tokenParts = new Buffer(token, 'base64').toString().split(' ');
var username = tokenParts.shift();
var challengeResponse = (tokenParts.shift() || '').toLowerCase();
this._server.logger.info('[%s] Trying to authenticate "%s" with %s', this._id, username, 'CRAM-MD5');
this._server.onAuth({
method: 'CRAM-MD5',
username: username,
validatePassword: function(password) {
var hmac = crypto.createHmac('md5', password);
return hmac.update(challenge).digest('hex').toLowerCase() === challengeResponse;
}
}, this.session, function(err, response) {
if (err) {
this._server.logger.info('[%s] Authentication error for "%s"\n%s', this._id, username, err.message);
this.send(err.responseCode || 535, err.message);
return callback();
}
if (!response.user) {
this.send(response.responseCode || 535, response.message || 'Error: Authentication credentials invalid');
return callback();
}
this._server.logger.info('[%s] User "%s" authenticated');
this.session.user = response.user;
this.send(235, 'Authentication successful');
callback();
}.bind(this));
}
};

@@ -51,4 +51,21 @@ 'use strict';

'-----END CERTIFICATE-----',
// default cipher set copied from a random blog in the internets
ciphers: 'ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+3DES:DH+3DES:RSA+AESGCM:RSA+AES:RSA+3DES:!aNULL:!MD5:!DSS',
// default iojs cipher set, copied from https://certsimple.com/blog/a-plus-node-js-ssl
ciphers: [
'ECDHE-RSA-AES256-SHA384',
'DHE-RSA-AES256-SHA384',
'ECDHE-RSA-AES256-SHA256',
'DHE-RSA-AES256-SHA256',
'ECDHE-RSA-AES128-SHA256',
'DHE-RSA-AES128-SHA256',
'HIGH',
'!aNULL',
'!eNULL',
'!EXPORT',
'!DES',
'!RC4',
'!MD5',
'!PSK',
'!SRP',
'!CAMELLIA'
].join(':'),
honorCipherOrder: true

@@ -55,0 +72,0 @@ };

{
"name": "smtp-server",
"version": "1.2.0",
"version": "1.3.0",
"description": "Create custom SMTP servers on the fly",

@@ -13,8 +13,8 @@ "main": "lib/smtp-server.js",

"devDependencies": {
"chai": "^2.1.1",
"chai": "^2.2.0",
"grunt": "^0.4.5",
"grunt-contrib-jshint": "^0.11.0",
"grunt-contrib-jshint": "^0.11.2",
"grunt-mocha-test": "^0.12.7",
"mocha": "^2.2.1",
"sinon": "^1.13.0",
"mocha": "^2.2.4",
"sinon": "^1.14.1",
"smtp-connection": "^1.2.0"

@@ -21,0 +21,0 @@ },

@@ -114,3 +114,3 @@ # smtp-server

This module does not support `CRAM` based authentications since these require access to unencrypted user password during the authentication process. You shouldn't store passwords unencrypted anyway, so supporting it doesn't make much sense.
This module supports `CRAM-MD5` but the use of it is discouraged as it requires access to unencrypted user passwords during the authentication process. You shouldn't store passwords unencrypted.

@@ -134,3 +134,3 @@ ### Examples

XOAUTH2 support needs to enabled with the `authMethods` array option to use it as it is disabled by default.
XOAUTH2 support needs to enabled with the `authMethods` array option as it is disabled by default.
If you support multiple authentication mechanisms, then you can check the used mechanism from the `method` property.

@@ -160,2 +160,29 @@

#### CRAM-MD5 authentication
CRAM-MD5 support needs to enabled with the `authMethods` array option as it is disabled by default.
If you support multiple authentication mechanisms, then you can check the used mechanism from the `method` property.
This authentication method does not return a password with the username but a response to a challenge. To validate the returned challenge response, the authentication object includes a method `validatePassword` that takes the actual plaintext password as an argument and returns either `true` if the password matches with the challenge response or `false` if it does not.
```javascript
var server = new SMTPServer({
authMethods: ['CRAM-MD5'], // CRAM-MD5 is not enabled by default
onAuth: function(auth, session, callback){
if(auth.method !== 'CRAM-MD5'){
// should never occur in this case as only CRAM-MD5 is allowed
return callback(new Error('Expecting CRAM-MD5'));
}
// CRAM-MD5 does not provide a password but a challenge response
// that can be validated against the actual password of the user
if(auth.username !== 'abc' || !auth.validatePassword('def')){
return callback(new Error('Invalid username or password'));
}
callback(null, {user: 123}); // where 123 is the user id or similar property
}
});
```
## Validating sender addresses

@@ -223,3 +250,3 @@

var server = new SMTPServer({
onRcptTo: function(stream, session, callback){}
onData: function(stream, session, callback){}
});

@@ -226,0 +253,0 @@ ```

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

});
// TODO: Add tests for CRAM-MD5
// smtp-connection does not support it currently
});

@@ -753,0 +756,0 @@

SocketSocket SOC 2 Logo

Product

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

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc