galleon
Version:
A badass SMTP mail server built on Node to make your life simpler.
105 lines (89 loc) • 3.77 kB
JavaScript
// Essential
var MailParser = require("mailparser").MailParser;
var PassThrough = require('stream').PassThrough;
var fs = require('fs');
var path = require('path');
// Functions
var create = require("./create");
var Attachment = require('./attachment');
//
/* -------------- Module Human description -------------- */
/*
Processor creates a function that handles
processing of a stream and session through parsers
and spam detectors. The final product is then
recorded in the database.
Note that this module is mostly stream based
and any function placed here that does not involve
direct database interaction should be entirely
based on NodeJS streams.
*/
module.exports = function (context, databaseConnection, Spamc) {
return function INCOMING_EMAIL_PROCESSOR(stream, session, callback) {
var fileStream;
/* Find/Create a Spamc module with streaming capability */
// Will not use SPAMASSASIN if the process is not available
var mailparser = new MailParser({
showAttachmentLinks: true,
streamAttachments: true
});
mailparser.once("end", function (parsed) {
/* Fix naming issues */
// Return an error if we don't know who the envelope is sent to
if ((!session.envelope) && ((!parsed.to) || (!parsed.to[0]) || (!parsed.to[0].address))) {
return callback({
responseCode: 451,
message: "Failed to process Envelope headers"
});
}
parsed.envelopeTo = (session.envelope) ? session.envelope.rcptTo : parsed.to;
if (!context.attach) context.attach = require('./attachment').save;
create(context, databaseConnection, session, parsed, function (error) {
// Respond to SMTP Connection (WITH OR WITHOUT ERROR)
callback(error);
if (session.store) {
var reporter = Spamc.report();
var RawStream = fs.createReadStream(session.path);
RawStream.pipe(reporter);
// Once report is obtained
reporter.once('report', function (report) {
if (!report && context.environment.verbose) return console.error("SPAMC-STREAM-ERROR::NO_REPORT");
// Update Email from EID
databaseConnection.collections.mail.update({ eID: session.eID }, {
isSpam: report.isSpam || false,
spamScore: report.spamScore || false,
status: "approved"
}, function (error, models) {
if (error || (models.length < 1)) {
if (context.environment.verbose) console.error("SPAMC-STREAM-ERROR::NO_RECORD");
return;
}
})
});
RawStream.once('error', function (error) {
if (context.environment.verbose) console.error("RAW-STREAM-ERROR::", error)
})
reporter.once('error', function (error) {
if (context.environment.verbose) console.error("SPAMC-STREAM-ERROR::", error)
})
}
});
});
mailparser.on("attachment", function (attachment, mail) {
if ((!context.environment.paths) || (!context.environment.paths.attachments)) return;
Attachment.stream(context.environment.paths.attachments, session.eID, attachment);
});
mailparser.once("error", function () {
if (context.environment.verbose) console.log("PARSER-STREAM-ERROR", arguments)
callback(new Error("FAILED TO STORE EMAIL"));
})
// Set Stream Encoding
stream.setEncoding('utf8');
// Create new FS Write stream
if (session.store) fileStream = fs.createWriteStream(session.path); /* Add Error handling for FileStream */
// Pipe to FS Write Stream
if (session.store) stream.pipe(fileStream);
// Pipe to MailParser Stream
stream.pipe(mailparser);
}
}