Socket
Socket
Sign inDemoInstall

smtp-server

Package Overview
Dependencies
2
Maintainers
1
Versions
65
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 1.10.0 to 1.11.0

examples/lmtp.js

4

CHANGELOG.md
# Changelog
## v1.11.0 2016-07-07
* Added support for LMTP protocol. Set `lmtp` option to `true` in order to use it
## v1.10.0 2016-07-06

@@ -4,0 +8,0 @@

60

lib/smtp-connection.js

@@ -110,3 +110,3 @@ 'use strict';

if (this._server.options.maxClients && this._server.connections.size > this._server.options.maxClients) {
this.send(421, this.name + ' Too many connected clients, try again in a moment');
return this.send(421, this.name + ' Too many connected clients, try again in a moment');
}

@@ -142,3 +142,3 @@

this._server.logger.info('[%s] Connection from %s', this._id, this.clientHostname);
this.send(220, this.name + ' ESMTP' + (this._server.options.banner ? ' ' + this._server.options.banner : ''));
this.send(220, this.name + ' ' + (this._server.options.lmtp ? 'LMTP' : 'ESMTP') + (this._server.options.banner ? ' ' + this._server.options.banner : ''));
if (typeof next === 'function') {

@@ -295,3 +295,3 @@ next();

// block spammers that send payloads before server greeting
this.send(421, this.name + ' You talk too soon');
return this.send(421, this.name + ' You talk too soon');
}

@@ -302,3 +302,3 @@ }

if (/^(OPTIONS|GET|HEAD|POST|PUT|DELETE|TRACE|CONNECT) \/.* HTTP\/\d\.\d$/i.test(command)) {
this.send(421, 'HTTP requests not allowed');
return this.send(421, 'HTTP requests not allowed');
}

@@ -320,2 +320,13 @@

commandName = (command || '').toString().split(' ').shift().toUpperCase();
if (this._server.options.lmtp) {
switch (commandName) {
case 'HELO':
case 'EHLO':
this.send(500, 'Error: ' + commandName + ' not allowed in LMTP server');
return setImmediate(callback);
case 'LHLO':
commandName = 'EHLO';
break;
}
}
if (this._isSupported(commandName)) {

@@ -330,3 +341,3 @@ handler = this['handler_' + commandName];

if (this._unrecognizedCommands >= 10) {
this.send(421, 'Error: too many unrecognized commands');
return this.send(421, 'Error: too many unrecognized commands');
}

@@ -342,3 +353,3 @@

if (this._unauthenticatedCommands >= 10) {
this.send(421, 'Error: too many unauthenticated commands');
return this.send(421, 'Error: too many unauthenticated commands');
}

@@ -348,3 +359,3 @@ }

if (!this.hostNameAppearsAs && commandName && ['MAIL', 'RCPT', 'DATA', 'AUTH'].indexOf(commandName) >= 0) {
this.send(503, 'Error: send HELO/EHLO first');
this.send(503, 'Error: send ' + (this._server.options.lmtp ? 'LHLO' : 'HELO/EHLO') + ' first');
return setImmediate(callback);

@@ -472,3 +483,3 @@ }

if (parts.length !== 2) {
this.send(501, 'Error: syntax: EHLO hostname');
this.send(501, 'Error: syntax: ' + (this._server.options.lmtp ? 'LHLO' : 'EHLO') + ' hostname');
return callback();

@@ -506,3 +517,3 @@ }

this._resetSession(); // EHLO is effectively the same as RSET
this.send(250, ['OK: Nice to meet you ' + this.clientHostname].concat(features || []));
this.send(250, [this.name + ' Nice to meet you, ' + this.clientHostname].concat(features || []));

@@ -527,3 +538,3 @@ callback();

this._resetSession(); // HELO is effectively the same as RSET
this.send(250, 'OK: Nice to meet you ' + this.clientHostname);
this.send(250, this.name + ' Nice to meet you, ' + this.clientHostname);

@@ -692,3 +703,3 @@ callback();

// success
this.send(220, this.name + ' ESMTP' + (this._server.options.banner ? ' ' + this._server.options.banner : ''));
this.send(220, this.name + ' ' + (this._server.options.lmtp ? 'LMTP' : 'ESMTP') + (this._server.options.banner ? ' ' + this._server.options.banner : ''));
callback();

@@ -963,2 +974,4 @@ };

var close = function (err, message) {
var i, len;
this._server.logger.debug('[%s] C: <%s bytes of DATA>', this._id, this._parser.dataBytes);

@@ -971,4 +984,27 @@

if (err) {
this.send(err.responseCode || 450, err.message);
if (this._server.options.lmtp) {
// separate error response for every recipient when using LMTP
for (i = 0, len = this.session.envelope.rcptTo.length; i < len; i++) {
this.send(err.responseCode || 450, err.message);
}
} else {
// single error response when using SMTP
this.send(err.responseCode || 450, err.message);
}
} else if (Array.isArray(message)) {
// separate responses for every recipient when using LMTP
message.forEach(function (response) {
if (/Error\]$/i.test(Object.prototype.toString.call(response))) {
this.send(response.responseCode || 450, response.message);
} else {
this.send(250, typeof response === 'string' ? response : 'OK: message accepted');
}
}.bind(this));
} else if (this._server.options.lmtp) {
// separate success response for every recipient when using LMTP
for (i = 0, len = this.session.envelope.rcptTo.length; i < len; i++) {
this.send(250, typeof message === 'string' ? message : 'OK: message accepted');
}
} else {
// single success response when using SMTP
this.send(250, typeof message === 'string' ? message : 'OK: message queued');

@@ -975,0 +1011,0 @@ }

@@ -209,4 +209,5 @@ 'use strict';

this.logger.info(
'%sSMTP Server listening on %s:%s',
'%s%s Server listening on %s:%s',
this.options.secure ? 'Secure ' : '',
this.options.lmtp ? 'LMTP' : 'SMTP',
address.family === 'IPv4' ? address.address : '[' + address.address + ']',

@@ -222,3 +223,3 @@ address.port);

SMTPServer.prototype._onClose = function () {
this.logger.info('SMTP Server closed');
this.logger.info((this.options.lmtp ? 'LMTP' : 'SMTP') + ' Server closed');
this.emit('close');

@@ -225,0 +226,0 @@ };

{
"name": "smtp-server",
"version": "1.10.0",
"version": "1.11.0",
"description": "Create custom SMTP servers on the fly",
"main": "lib/smtp-server.js",
"scripts": {
"test": "grunt"
"test": "grunt mochaTest"
},

@@ -13,3 +13,3 @@ "author": "Andris Reinman",

"ipv6-normalize": "^1.0.1",
"nodemailer-shared": "^1.0.4"
"nodemailer-shared": "^1.0.5"
},

@@ -19,6 +19,7 @@ "devDependencies": {

"grunt": "^1.0.1",
"grunt-eslint": "^18.1.0",
"grunt-cli": "^1.2.0",
"grunt-eslint": "^19.0.0",
"grunt-mocha-test": "^0.12.7",
"mocha": "^2.4.5",
"smtp-connection": "^2.3.2"
"mocha": "^2.5.3",
"smtp-connection": "^2.7.0"
},

@@ -25,0 +26,0 @@ "engines": {

# smtp-server
Create SMTP server instances on the fly. This is not a full-blown server application like [Haraka](https://haraka.github.io/) but an easy way to add custom SMTP listeners to your app. This module is the successor for the server part of the (now deprecated) SMTP module [simplesmtp](https://www.npmjs.com/package/simplesmtp). For matching SMTP client see [smtp-connection](https://www.npmjs.com/package/smtp-connection).
Create SMTP and LMTP server instances on the fly. This is not a full-blown server application like [Haraka](https://haraka.github.io/) but an easy way to add custom SMTP listeners to your app. This module is the successor for the server part of the (now deprecated) SMTP module [simplesmtp](https://www.npmjs.com/package/simplesmtp). For matching SMTP client see [smtp-connection](https://www.npmjs.com/package/smtp-connection).

@@ -51,2 +51,3 @@ [![Build Status](https://secure.travis-ci.org/andris9/smtp-server.svg)](http://travis-ci.org/andris9/Nodemailer)

* **options.useXForward** boolean, if set to true, enables usage of [XFORWARD](http://www.postfix.org/XFORWARD_README.html) extension. See `session.xForward` (Map object) for the details provided by the client
* **options.lmtp** boolean, if set to true use LMTP protocol instead of SMTP
* **options.socketTimeout** how many milliseconds of inactivity to allow before disconnecting the client (defaults to 1 minute)

@@ -345,2 +346,35 @@ * **options.closeTimeout** how many millisceonds to wait before disconnecting pending connections once server.close() has been called (defaults to 30 seconds)

## Using LMTP
If `lmtp` option is set to true when starting the server, then LMTP protocol is used instead of SMTP. The main
difference between these two is how multiple recipients are handled. In case of SMTP the message either fails or succeeds
but in LMTP the message might fail and succeed individually for every recipient.
If your LMTP server application does not distinguish between different recipients then you do not need to care about it.
On the other hand if you want to report results separately for every recipient you can do this by providing an array
of responses instead of a single error or success message. The array must contain responses in the same order as in the
envelope rcptTo array.
```javascript
var server = new SMTPServer({
lmtp: true,
onData: function(stream, session, callback){
stream.pipe(process.stdout); // print message to console
stream.on('end', function(){
// reject every other recipient
var response = session.envelope.rcptTo.map(function (rcpt, i) {
if (i % 2) {
return new Error('<' + rcpt.address + '> Not accepted');
} else {
return '<' + rcpt.address + '> Accepted';
}
});
callback(null, response);
});
}
});
```
If you provide a single error by invoking `callback(err)` or single success message `callback(null, 'OK')` like when dealing with SMTP then every recipient gets the same response.
## Session object

@@ -347,0 +381,0 @@

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

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

Packages

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc