Skip to content

Commit

Permalink
Move setting up SMTP server into module to make it testable
Browse files Browse the repository at this point in the history
  • Loading branch information
mike-lang committed Jan 22, 2016
1 parent 490dfb8 commit 7cb8b2c
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 52 deletions.
54 changes: 2 additions & 52 deletions bin/hoodiecrow
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ var hoodiecrow = require("../lib/server"),
packageData = require("../package"),
fs = require("fs"),
argv = require('optimist').argv,
simplesmtp = require("simplesmtp"),
smtpServer = require("../lib/hoodiecrowSMTPServer"),

configLocation = argv.config || process.env.HOODIECROW_CONFIG,
storageLocation = argv.storage || process.env.HOODIECROW_STORAGE,
Expand Down Expand Up @@ -103,57 +103,7 @@ if(argv.h || argv.help){
});

if(smtpPort){
simplesmtp.createSimpleServer({SMTPBanner:"Hoodiecrow"}, function(req){
var data = [], dataLen = 0;
req.on("data", function(chunk){
if(!chunk || !chunk.length){
return;
}
data.push(chunk);
dataLen += chunk.length;
});
req.on("end", function(){
function handleDotEscaping(message) {
// According to http://tools.ietf.org/html/rfc5321#section-4.5.2,
// SMTP clients are to escape any period appearing as the first
// character of a line with another period. This code removes
// any of these inserted periods as they would appear as a doubled
// period in email if we didn't.
//
// This should probably be considered an issue in simpleSMTP
// since period escaping is part of the SMTP spec, but it doesn't
// seem to be possible to fix it there with this API unless emitted
// chunks coincide with lines submitted by the SMTP client. It
// wasn't immediately clear whether that is the case.
// And simpleSMTP is clearly labelled as deprecated anyway. Might
// as well hack in a fix here unless hoodiecrow were to move to
// simpleSMTP's replacement
//
var dotsNotHandled = message.toString('utf-8');
// If the message begins with a dot, we need to delete it, unless its part of a message terminator.
var firstLineHandled = dotsNotHandled[0] === '.' && !(dotsNotHandled[1] === '\r' && dotsNotHandled[2] === '\n') ?
dotsNotHanlded.substr(1) : dotsNotHandled;
// This split/join deletes all periods that appear as the first character of a line
// except for when it is immediately followed by <cr><lf> and thus is part of a message terminator.
var textSurroundingFirstCharacterDots = dotsNotHandled.split('\r\n.');
var intermediate = textSurroundingFirstCharacterDots.map(function(lineFollowingStartingDot) {
if (lineFollowingStartingDot.indexOf('\r\n') === 0) {
return '\r\n.' + lineFollowingStartingDot;
} else {
return lineFollowingStartingDot;
}
});
return new Buffer(intermediate.join('\r\n'));
}

var message = Buffer.concat(data, dataLen),
messageAfterHandlingDotEscaping = handleDotEscaping(message);
server.appendMessage("INBOX", [], false, messageAfterHandlingDotEscaping.toString("binary"));
});
req.accept();
}).listen(smtpPort, function(){
console.log("Incoming SMTP server up and running on port %s", smtpPort);
});
smtpServer.startSMTPServer(smtpPort, server);
}
}

76 changes: 76 additions & 0 deletions lib/hoodiecrowSMTPServer.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@

var simplesmtp = require('simplesmtp');

/***
* Starts simpleSMTP server, passing parsed email messages along to the
* hoodiecrow IMAP server as a new message in the INBOX.
*
* Note: Interprets data chunks coming out of simpleSMTP to fix dot escaping
* issue that is liable to leave duplicated dots in emails
*
*
* @param {Number} smtpPort - port to listen on for SMTP commands
* @param {Object} imapServer - the hoodiecrow IMAP server
* @param {Function} callback - function executed when SMTP server is listening
*/
exports.startSMTPServer = function startSMTPServer(smtpPort, imapServer, callback) {
var server = simplesmtp.createSimpleServer({SMTPBanner:"Hoodiecrow"}, function(req) {
var data = [], dataLen = 0;
req.on("data", function(chunk){
if(!chunk || !chunk.length){
return;
}
data.push(chunk);
dataLen += chunk.length;
});
req.on("end", function(){
function handleDotEscaping(message) {
// According to http://tools.ietf.org/html/rfc5321#section-4.5.2,
// SMTP clients are to escape any period appearing as the first
// character of a line with another period. This code removes
// any of these inserted periods as they would appear as a doubled
// period in email if we didn't.
//
// This should probably be considered an issue in simpleSMTP
// since period escaping is part of the SMTP spec, but it doesn't
// seem to be possible to fix it there with this API unless emitted
// chunks coincide with lines submitted by the SMTP client. It
// wasn't immediately clear whether that is the case.
// And simpleSMTP is clearly labelled as deprecated anyway. Might
// as well hack in a fix here unless hoodiecrow were to move to
// simpleSMTP's replacement
//
var dotsNotHandled = message.toString('utf-8');
// If the message begins with a dot, we need to delete it, unless its part of a message terminator.
var firstLineHandled = dotsNotHandled[0] === '.' && !(dotsNotHandled[1] === '\r' && dotsNotHandled[2] === '\n') ?
dotsNotHanlded.substr(1) : dotsNotHandled;
// This split/join deletes all periods that appear as the first character of a line
// except for when it is immediately followed by <cr><lf> and thus is part of a message terminator.
var textSurroundingFirstCharacterDots = dotsNotHandled.split('\r\n.');
var intermediate = textSurroundingFirstCharacterDots.map(function(lineFollowingStartingDot) {
if (lineFollowingStartingDot.indexOf('\r\n') === 0) {
return '\r\n.' + lineFollowingStartingDot;
} else {
return lineFollowingStartingDot;
}
});
return new Buffer(intermediate.join('\r\n'));
}

var message = Buffer.concat(data, dataLen),
messageAfterHandlingDotEscaping = handleDotEscaping(message);
imapServer.appendMessage("INBOX", [], false, messageAfterHandlingDotEscaping.toString("binary"));
});
req.accept();
});

server.listen(smtpPort, function(){
console.log("Incoming SMTP server up and running on port %s", smtpPort);
if (callback) {
return callback();
}
});

return server;

}

0 comments on commit 7cb8b2c

Please sign in to comment.