Socket
Socket
Sign inDemoInstall

mailer

Package Overview
Dependencies
2
Maintainers
0
Versions
18
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 0.4.52 to 0.5.6

3

demo-template.js

@@ -12,3 +12,3 @@ var email = require("./lib/node_mailer");

subject : "node_mailer test email",
template : "../templates/sample.txt", // path to template name
template : "./templates/sample.txt", // path to template name
data : {

@@ -25,3 +25,2 @@ "username": "Billy Bob",

authentication : "login", // auth login is supported; anything else is no auth
username : "dXNlcm5hbWU=", // Base64 encoded username

@@ -28,0 +27,0 @@ password : "cGFzc3dvcmQ=" // Base64 encoded password

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 : 'username', // Base64 encoded username
password : 'password' // Base64 encoded password
},

@@ -20,2 +20,2 @@ function(err, result){

});
}
}

@@ -25,331 +25,119 @@ /* Copyright (c) 2009-2010 Marak Squires, Elijah Insua, Fedor Indutny - http://github.com/marak/node_mailer

var SMTPClient = require("nodemailer").SMTPClient;
var EmailMessage = require("nodemailer").EmailMessage;
var fs = require('fs');
var mustache = require('../vendor/mustache');
var _templateCache = {};
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 = {};
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]
}
}
})
client.on("empty",function(){
delete hostClients[options.user];
client.close();})
}
SMTPClientPool.prototype.send = function send(message, callback) {
this.servers[message.SERVER.host][message.SERVER.user].sendMail(message,callback);
}
exports.connections = connections;
var pool = new SMTPClientPool();
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;
}
exports.send = function node_mail(message, callback) {
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();
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
};
function doProcess() {
var email = self._queue.shift();
if(message.username || message.password) {
pool.addClient(server.port, server.host, server);
}
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);
// If a template was passed in as part of the message
if (message.template) {
// If the template path is in the cache
if (_templateCache[message.template]) {
// If the template is already fully loaded in the cahe
if (_templateCache[message.template].loaded) {
// Use the cached template and send the email
message.body = mustache.to_html(_templateCache[message.template].template, message.data);
pool.send(new EmailMessage({
to: message.to,
sender: message.from,
subject: message.subject,
body: message.body,
server: server,
debug: message.debug
}), callback);
}
else {
// We've started to load the template, but it's not loaded yet. queue up this message to be sent later
_templateCache[message.template].queue.push(message);
}
}
},
connect : function(fn) {
if (!this._stream && !this._connecting) {
this._connecting = true;
var self = this,
stream = tcp.createConnection(this.options.port, this.options.host),
stream_promise = new process.EventEmitter;
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);
}
}
});
});
else {
// The template path wasn't found in the cache, start to load the template
_templateCache[message.template] = {};
_templateCache[message.template].loaded = false;
_templateCache[message.template].template = '';
_templateCache[message.template].queue = [];
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) {
fs.readFile(message.template, function(err, result){
if (err) {
// Probably process error
console.log(err.red.bold);
console.log(err);
return;
}
process.nextTick(function() {
self._process()
});
});
});
},
disconnect : function() {
this._processing = false;
if (this._stream) {
this._stream.end('quit\r\n');
this._stream = null;
}
}
};
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);
}
_templateCache[message.template].template = result.toString();
_templateCache[message.template].loaded = true;
// create a new connection if needed
var connectionKey = [options.host, options.port].join(':');
if (!connections[connectionKey]) {
connections[connectionKey] = new Connection(options, callback);
}
// "Drain" the queue
_templateCache[message.template].queue.forEach(function(msg, i){
msg.body = mustache.to_html(_templateCache[message.template].template, msg.data);
pool.send(new EmailMessage({
to: msg.to,
sender: msg.from,
subject: msg.subject,
body: msg.body,
server: server,
debug: msg.debug
}), callback);
});
// queue this email in the appropriate connection
connections[connectionKey].queue(this);
};
// Clear the queue out
_templateCache[message.template].queue = [];
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);
});
}
}
else{
return new Email(options, callback);
else { // No template being used
pool.send(new EmailMessage({
to: message.to,
sender: message.from,
subject: message.subject,
body: message.body,
server: server,
debug: message.debug
}), callback);
}
};
{
"name": "mailer",
"description": "send emails from node.js to a smtp server, simple as cake",
"version": "0.4.52",
"version": "0.5.6",
"author": "Marak Squires",
"contributors" : [
"Elijah Insua <tmpvar@gmail.com> (http://tmvpar.com/)",
"Fedor Indutny <fedor.indutny@gmail.com> (http://indutny.com/)"
"Fedor Indutny <fedor.indutny@gmail.com> (http://indutny.com/)",
"Bradley Meck <bradley.meck@gmail.com> (http://bradleymeck.com)"
],

@@ -15,7 +16,7 @@ "repository": {

"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"
}

@@ -30,2 +30,3 @@ #v0.4.51

port : "25", // smtp server port
ssl: true, // for SSL support - REQUIRES NODE v0.3.x OR HIGHER
domain : "localhost", // domain used by client to identify itself to server

@@ -45,2 +46,7 @@ to : "marak.squires@gmail.com",

# USING SSL
node_mailer SSL connections (not TLS / STARTTLS, just SSL from the beginning of the connection). To use it,
add an option ssl: true. See usage above.
# USING TEMPLATES

@@ -50,3 +56,3 @@

/templates/sample.text
/templates/sample.txt

@@ -97,5 +103,7 @@ Hello {{username}},

## Authors
Marak Squires, Elijah Insua, Fedor Indutny
Marak Squires, Elijah Insua, Fedor Indutny, Bradley Meck
SocketSocket SOC 2 Logo

Product

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

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc