Permalink
Browse files

Modified Nodemailer to use a pluggable engine system, and converted t…

…he SMTP and sendmail functionality into engines.
  • Loading branch information...
David Ellis
David Ellis committed Aug 11, 2011
1 parent e8701d7 commit 967146cf0b988429b9e0ebc51d2eb6049ad2f48b
Showing with 85 additions and 101 deletions.
  1. +32 −3 lib/{smtp.js → engines/SMTP.js}
  2. 0 lib/{ → engines/SMTP}/starttls.js
  3. +30 −0 lib/engines/sendmail.js
  4. +23 −98 lib/mail.js
@@ -4,7 +4,7 @@ var netlib = require("net"),
oslib = require('os'),
tlslib = require('tls'),
EventEmitter = require('events').EventEmitter,
- starttls = require('./starttls.js');
+ starttls = require('./SMTP/starttls.js');
/**
* smtp
@@ -50,10 +50,39 @@ var netlib = require("net"),
*
**/
+exports.send = function(emailMessage, config, callback) {
+ emailMessage.prepareVariables();
+
+ var client = new SMTPClient(emailMessage.SERVER.host, emailMessage.SERVER.port, {
+ hostname: emailMessage.SERVER.hostname,
+ use_authentication: emailMessage.SERVER.use_authentication,
+ user: emailMessage.SERVER.user,
+ pass: emailMessage.SERVER.pass,
+ ssl: emailMessage.SERVER.ssl,
+ debug: emailMessage.debug,
+ instanceId: config.instanceId
+ });
+
+ client.on("empty",function() {
+ client.send("QUIT",function() {
+ client.close();
+ });
+ });
+
+ client.on("connection_stable", (function(){
+ this.emit.apply(this,["connection_stable"].concat([].slice.call(arguments)));
+ }).bind(emailMessage));
+
+ client.on("error", function(error){
+ callback && callback(error, null);
+ });
+
+ client.sendMail(emailMessage, callback);
+};
+
// expose constructor SMTPClient to the world
exports.SMTPClient = SMTPClient;
-
/**
* new smtp.SMTPClient(host, port[, options])
* - host (String): SMTP server hostname
@@ -711,4 +740,4 @@ SMTPClient.prototype._createConnection = function(callback){
//10 seconds for data
this._connection.on("connect", this._waitForTimeout.bind(this));
this._connection.on("data", this._onData = this._onData.bind(this, callback));
-}
+}
File renamed without changes.
View
@@ -0,0 +1,30 @@
+var exec;
+
+try{
+ exec = require('child_process').exec;
+}catch(E){
+ // probably on Windows Node.js v0.5.0 - v0.5.2
+}
+
+exports.send = function(emailMessage, config, callback) {
+ emailMessage.prepareVariables();
+
+ if(!exec){
+ return callback(new Error("No support for child processes in this version of Node.JS, use SMTP instead"));
+ }
+
+ var headers = emailMessage.generateHeaders(),
+ body = emailMessage.generateBody();
+
+ var path = typeof config=="string"?config:"sendmail";
+ exec('echo "'+(headers+"\r\n\r\n"+body).replace(/"/g,'\\"')+'" | '+path+" -t", function(error){
+ process.nextTick(function(){
+ if(error){
+ callback && callback(error, null);
+ }else{
+ callback && callback(null, true);
+ }
+ });
+ });
+ return;
+};
View
@@ -1,15 +1,21 @@
-var SMTPClient = exports.SMTPClient = require("./smtp").SMTPClient,
- mimelib = require("mimelib-noiconv"),
+var mimelib = require("mimelib-noiconv"),
util = require("util"),
EventEmitter = require("events").EventEmitter,
- exec;
-
-try{
- exec = require('child_process').exec;
-}catch(E){
- // probably on Windows Node.js v0.5.0 - v0.5.2
-}
-
+ fs = require("fs");
+/*
+ * Load all engines, assuming each .js file in the root of the engines
+ * directory is an engine. To avoid collisions, dependencies should be
+ * stored in a directory of the same name as the engine.
+ */
+var engines = {};
+fs.readdirSync(__dirname + '/engines').forEach(function(engine) {
+ if(/\.js$/.test(engine)) {
+ var engineName = engine.replace(/\.js$/, "");
+ //Load the engine into the engine object
+ engines[engineName] = require(__dirname + '/engines/' + engine);
+ }
+});
+
/*
* Version constants
*/
@@ -29,50 +35,12 @@ var X_MAILER_NAME = "Nodemailer",
// EXPOSE TO THE WORLD
-/**
- * mail.SMTP -> Object
- *
- * Configuration object, keeps the needed values to connect to the SMTP server
- *
- * - **host** Hostname of the SMTP server (required)
- * - **port** SMTP server port, defaults to 25
- * - **hostname** hostname of the local server, needed for identifying,
- * defaults to *untitled.server*
- * - **use_authentication** if set to *true* authentication procedure is
- * run after a successful connection
- * - **user** username for authentication
- * - **pass** password for authentication
- **/
-exports.SMTP = {
- host: false,
- port: false,
- hostname: false,
- use_authentication: false,
- ssl: false,
- user: false,
- pass: false
-};
-
exports.CommonServers = {
gmail:[],
yahoo:[],
hotmail:[]
};
-/**
- * mail.sendmail -> Boolean | String
- *
- * If set to true, "sendmail" command will be used instead of SMTP
- * If the value is a String then it will be used as the sendmail command
- *
- * mail.sendmail = true
- *
- * or
- *
- * mail.sendmail = "/path/to/sendmail"
- **/
-exports.sendmail = false;
-
// Expose EmailMessage for the world
exports.EmailMessage = EmailMessage;
@@ -459,65 +427,22 @@ EmailMessage.prototype.generateAddresses = function(addresses, limit, use_list){
* and success is true, then the message was sent to the recipients
**/
EmailMessage.prototype.send = function(callback){
- this.prepareVariables();
-
var instanceId = ++instancecounter;
-
+
if(this.debug){
var str = X_MAILER_NAME+", "+X_MAILER_VERSION+", Node.js "+process.version+": "+instanceId;
console.log(str);
console.log(Array(str.length+1).join("=")+"\n");
}
- // use sendmail if set
- if(exports.sendmail){
-
- if(!exec){
- return callback(new Error("No support for child processes in this version of Node.JS, use SMTP instead"));
+ //Use the engine configured by the user
+ for(var engine in engines) {
+ if(exports[engine]) {
+ exports[engine].instanceId = instanceId;
+ engines[engine].send(this, exports[engine], callback);
+ return;
}
-
- var headers = this.generateHeaders(),
- body = this.generateBody();
-
- var path = typeof exports.sendmail=="string"?exports.sendmail:"sendmail";
- exec('echo "'+(headers+"\r\n\r\n"+body).replace(/"/g,'\\"')+'" | '+path+" -t", function(error){
- process.nextTick(function(){
- if(error){
- callback && callback(error, null);
- }else{
- callback && callback(null, true);
- }
- });
- });
- return;
}
-
- // use SERVER
- var client = new SMTPClient(this.SERVER.host, this.SERVER.port, {
- hostname: this.SERVER.hostname,
- use_authentication: this.SERVER.use_authentication,
- user: this.SERVER.user,
- pass: this.SERVER.pass,
- ssl: this.SERVER.ssl,
- debug: this.debug,
- instanceId: instanceId
- });
-
- client.on("empty",function() {
- client.send("QUIT",function() {
- client.close();
- });
- });
-
- client.on("connection_stable", (function(){
- this.emit.apply(this,["connection_stable"].concat([].slice.call(arguments)));
- }).bind(this));
-
- client.on("error", function(error){
- callback && callback(error, null);
- });
-
- client.sendMail(this, callback);
}
/**

0 comments on commit 967146c

Please sign in to comment.