Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

removed template logic, using Nodemailer as backing library

Edited demo.js via GitHub
  • Loading branch information...
commit c3d74c083d991c1c0a1af7c132b099179fb153ef 1 parent a3b4f0a
@bmeck bmeck authored
View
16 demo.js
@@ -1,18 +1,18 @@
var email = require("./lib/node_mailer");
for(var i = 0; i < 10; i++){
-
email.send({
- host : "localhost", // smtp server hostname
- port : "25", // smtp server port
- domain : "localhost", // domain used by client to identify itself to server
- to : "marak.squires@gmail.com",
- from : "obama@whitehouse.gov",
+ ssl: true,
+ host : "smtp.gmail.com", // smtp server hostname
+ port : 465, // smtp server port
+ domain : "[127.0.0.1]", // domain used by client to identify itself to server
+ to : "bradley.meck@gmail.com",
+ from : "bradley.meck@gmail.com",
subject : "node_mailer test email",
body: "Hello! This is a test of the node_mailer.",
authentication : "login", // auth login is supported; anything else is no auth
- username : "dXNlcm5hbWU=", // Base64 encoded username
- password : "cGFzc3dvcmQ=" // Base64 encoded password
+ username : undefined, // Base64 encoded username
+ password : undefined // Base64 encoded password
},
function(err, result){
if(err){ console.log(err); }
View
414 lib/node_mailer.js
@@ -22,372 +22,54 @@ FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
*/
-
-var tcp = require('net'),
- fs = require('fs'),
- carrier = require('carrier'),
- colors = require('colors'),
- mustache = require('../vendor/mustache'),
- defaultOptions = {
- to : "marak.squires@gmail.com",
- from : "obama@whitehouse.gov",
- data : {},
- subject : "node_mailer test email",
- body : "hello this is a test email from the node_mailer",
- host : "localhost",
- domain : "localhost",
- 'content-type': 'text/plain',
- port : 25
- },
- keys = Object.keys(defaultOptions),
- connections = {},
- templateCache = {};
-
-exports.connections = connections;
-
-var Connection = function(options, callback) {
- this.options = options;
- this.callback = callback || function(){};
-};
-Connection.prototype = {
- options : {},
- _stream : null,
- _connecting : false,
- _queue : [],
- _processing : false,
- _process : function() {
- var self = this;
- if (!self._stream ||
- ['open', 'writeOnly'].indexOf(self._stream.readyState) === -1)
- {
- return;
- }
-
- if (!self._processing) {
- var dequeue = function() {
- if (!self._stream ||
- ['open', 'writeOnly'].indexOf(self._stream.readyState) === -1)
- {
- self.connect(function(err) {
- if (err) {
- console.log(err.red.bold);
- return;
- }
- doProcess();
- });
- return;
- } else doProcess();
-
- function doProcess() {
- var email = self._queue.shift();
-
- if (!email) return;
- var from = email.options.from,
- msg;
-
- function _cb_tpl(fn) {
- return function(err) {
- if (err) {
- try {
- self.disconnect();
- } catch(e) {
- }
- return;
- }
- fn();
- };
- }
-
- writeFrom();
-
- function writeFrom() {
- self._stream.write(
- 'mail from: ' + (/<.+>/.test(from) ? from : '<' + from + '>') +
- '\r\n'
- );
-
- self._stream.promise.wait('accepted', _cb_tpl(writeTo));
- }
-
- function writeTo() {
- self._stream.write('rcpt to: ' + email.options.to + '\r\n');
- self._stream.promise.wait('accepted', _cb_tpl(writeDataStart));
- }
-
- function writeDataStart() {
- self._stream.write('data\r\n');
- self._stream.promise.wait('continue', _cb_tpl(writeData));
- }
-
- function writeData() {
- self._stream.write([
- 'From: ' + email.options.from,
- 'To: ' + email.options.to,
- 'Subject: ' + email.options.subject,
- 'Content-Type: ' + email.options['content-type'],
- '',
- email.options.body,
- '.',
- 'RSET',
- ''
- ].join('\r\n'));
-
- onEnd();
- }
-
- function onEnd() {
- if (self._queue.length > 0) {
- process.nextTick(dequeue);
- } else {
- self.disconnect();
- }
- }
- }
- };
-
- self._processing = true;
- process.nextTick(dequeue);
- }
- },
- connect : function(fn) {
- if (!this._stream && !this._connecting) {
- this._connecting = true;
-
- var self = this,
- stream_promise = new process.EventEmitter,
- connectionHandler;
-
- connectionHandler = function() {
- self._stream = stream;
- self._connecting = false;
-
- stream.write("helo " + self.options.domain + "\r\n");
- stream.promise.wait('accepted', function() {
- if(self.options.authentication === "login") {
- stream.write("auth login\r\n");
- stream.write(self.options.username + "\r\n");
- stream.write(self.options.password + "\r\n");
-
- if (typeof fn === 'function') {
- // Set auth callback
- stream_promise.wait('auth', function(err) {
- if (err) {
- try {
- self.disconnect();
- } catch (e) {
- }
- }
- fn(err, self._stream);
- }, self.options.auth_timeout);
- }
- } else {
- if (typeof fn === 'function') {
- fn(null, self._stream);
- }
- }
- });
- };
-
- if (this.options.ssl) {
- tls = tls || require('tls');
- stream = tls.connect(this.options.port,this.options.host,connectionHandler);
-
- } else {
- stream = tcp.createConnection(this.options.port, this.options.host);
- }
-
- stream.promise = stream_promise;
-
- // Parse reply lines
- carrier.carry(stream, function(line) {
- // If we got successfull auth
- if (/^235\s/.test(line)) {
- stream_promise.emit('auth');
- } else
- // If server has accepted something
- if (/^250\s/.test(line)) {
- stream_promise.emit('accepted');
- } else
- // If server says Continue
- if (/^354\s/.test(line)) {
- stream_promise.emit('continue');
- }
- });
-
- // Wait for event with timeout
- stream_promise.wait = function(event, callback, timeout) {
- stream_promise.on(event, onEvent);
-
- function onEvent() {
- stream_promise.removeListener(event, onEvent);
- clearTimeout(timeout);
- callback(null);
- }
-
- var timeout = setTimeout(function() {
- stream_promise.removeListener(event, onEvent);
- callback('timeout');
- }, timeout || 5000);
- };
-
- stream.setEncoding("utf8");
- stream.on("connect", function() {
- self._stream = stream;
- self._connecting = false;
-
- stream.write("helo " + self.options.domain + "\r\n");
- stream.promise.wait('accepted', function() {
- if(self.options.authentication === "login") {
- stream.write("auth login\r\n");
- stream.write(self.options.username + "\r\n");
- stream.write(self.options.password + "\r\n");
-
- if (typeof fn === 'function') {
- // Set auth callback
- stream_promise.wait('auth', function(err) {
- if (err) {
- try {
- self.disconnect();
- } catch (e) {
- }
- }
- fn(err, self._stream);
- }, self.options.auth_timeout);
- }
- } else {
- if (typeof fn === 'function') {
- fn(null, self._stream);
- }
- }
- });
- });
-
- stream.on("error", function() {
- self.callback(new Error("could not connect"));
- console.log(arguments);
- stream.destroy();
- self._connecting = false;
- stream = null;
- });
-
- stream.on("end", function() {
- self.callback(null);
- self._connecting = false;
- self._stream = null;
- });
- } else if (typeof fn === 'function') {
- process.nextTick(function() {
- fn(this._stream);
- });
- }
- },
- queue : function(email) {
- var self = this;
- self._queue.push(email);
- process.nextTick(function() {
- self.connect(function(err) {
- if (err) {
- // Probably process error
- console.log(err.red.bold);
- return;
- }
- process.nextTick(function() {
- self._process()
- });
- });
- });
- },
- disconnect : function() {
- this._processing = false;
- if (this._stream) {
- this._stream.end('quit\r\n');
- this._stream = null;
+var SMTPClient = require("Nodemailer").SMTPClient;
+var EmailMessage = require("Nodemailer").EmailMessage;
+
+function SMTPClientPool() {
+ this.servers = {};
+}
+SMTPClientPool.prototype.addClient = function(port,host,options) {
+ if(this.servers[host] && this.servers[host][options.user]) return;
+ var hostClients = this.servers[host] || (this.servers[host] = {});
+ var pool = this;
+ var client = hostClients[options.user] = new SMTPClient(host,port,options);
+ client.on("close",function() {
+ if(client == hostClients[options.user]) {
+ //only because this could be crazy long lived and dynamic
+ delete hostClients[options.user];
+ if(Object.keys(hostClients).length == 0) {
+ delete pool.servers[host]
+ }
}
- }
-};
-
-var Email = function(options, callback) {
- this.options = options;
-
- if (options.lineWrap === undefined && /html/i.test(options['content-type'])) {
- options.lineWrap = false;
- }
-
- if (options.lineWrap !== false) {
- this.options.body = this.lineWrap(this.options.body);
- }
-
- // create a new connection if needed
- var connectionKey = [options.host, options.port].join(':');
- if (!connections[connectionKey]) {
- connections[connectionKey] = new Connection(options, callback);
- }
-
- // queue this email in the appropriate connection
- connections[connectionKey].queue(this);
-};
-
-Email.prototype = {
- options : {},
- lineWrap : function(str) {
- // Split by lines
- return str.split(/\r|\n|\r\n/g).reduce(function(prev, piece) {
-
- var parts = [];
-
- // Wrap line
- while (piece.length) {
- var match = piece.match(/^.{1,80}(?:\s|$)/),
- matchlen;
-
- if (!match) {
- match = [piece.substr(0, 80)];
- }
-
- if (matchlen = match[0].length) {
- parts.push(match[0]);
- piece = piece.substr(matchlen);
- }
- };
-
- return prev.concat(parts);
-
- }, []).join('\r\n');
- }
-};
-
-exports.send = function(options, callback) {
- var i, key;
- options = options || {};
-
- // fill in the gaps with defaultOptions
- for (i=0; i<keys.length; i++) {
- key = keys[i];
- if (typeof options[key] === "undefined") {
- options[key] = defaultOptions[key];
- }
- }
-
- // determine if we need to load a template before processing email for sending
-
- // there is currently a bit of a dog pile effect on the template caching, but in theory
- // it should eventually cache before we run out of File Descriptors. templateCache should be refactored
- if(options.template){
- if(typeof templateCache[options.template] != 'undefined'){
- options.body = mustache.to_html(templateCache[options.template], options.data);
- return new Email(options, callback);
- }
- else{
- fs.readFile(options.template, function (err, data) {
- if (err) throw err;
- templateCache[options.template] = data.toString();
- options.body = mustache.to_html(templateCache[options.template], options.data);
- return new Email(options, callback);
- });
+ })
+}
+SMTPClientPool.prototype.send = function send(message,callback) {
+ this.servers[message.SERVER.host][message.SERVER.user].sendMail(message,callback);
+}
+
+var pool = new SMTPClientPool();
+
+exports.send = function node_mail(message,callback) {
+ var server = {
+ host: message.host,
+ hostname: message.domain,
+ port: +message.port,
+ use_authentication: message.authentication,
+ ssl: message.ssl,
+ user: new Buffer(message.username || '', 'base64').toString('utf8'),
+ pass: new Buffer(message.password || '', 'base64').toString('utf8'),
+ debug: true
}
+ if(message.username || message.password) {
+ pool.addClient(server.port,server.host,server);
}
- else{
- return new Email(options, callback);
- }
-
-};
+ pool.send(new EmailMessage({
+ to: message.to,
+ sender: message.from,
+ subject: message.subject,
+
+ body: message.body,
+ server: server,
+ debug: message.debug
+ }),callback)
+};
1  node_modules/Nodemailer
@@ -0,0 +1 @@
+Subproject commit 9c65516088e19cd70d3fd7217376711c1445897e
View
4 package.json
@@ -12,9 +12,9 @@
"url": "http://github.com/Marak/node_mailer.git"
},
"dependencies": {
- "carrier": ">= 0.0.4",
+ "nodemailer": ">= 0.1.10",
"colors": ">= 0.3.0"
},
- "engine": [ "node >=0.1.90" ],
+ "engine": [ "node >=0.3.0" ],
"main": "lib/node_mailer"
}
Please sign in to comment.
Something went wrong with that request. Please try again.