Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

bump new version, wait for accept and continue responses before sendi…

…ng email
  • Loading branch information...
commit eace7c1bf41c7aa29b036cf47546e104e706912e 1 parent d34106f
Fedor Indutny indutny authored
Showing with 104 additions and 50 deletions.
  1. +103 −49 lib/node_mailer.js
  2. +1 −1  package.json
152 lib/node_mailer.js
View
@@ -72,35 +72,75 @@ Connection.prototype = {
console.log(err);
return;
}
- self._process;
+ doProcess();
});
return;
- }
-
- var email = self._queue.shift();
+ } else doProcess();
- if (email) {
- // TODO: incremental sending.. (think drain + pause/resume)
- var m = email.options.from.match(/.*<([^>]+)>\s*$/);
- var from = m ? m[1] : email.options.from;
-
- self._stream.write("mail from: <" + from + ">\r\n");
- self._stream.write("rcpt to: " + email.options.to + "\r\n");
- self._stream.write("data\r\n");
- self._stream.write("From: " + email.options.from + "\r\n");
- self._stream.write("To: " + email.options.to + "\r\n");
- self._stream.write("Subject: " + email.options.subject + "\r\n");
- self._stream.write("Content-Type: " + email.options['content-type'] + "\r\n");
- self._stream.write(email.options.body + "\r\n");
- self._stream.write(".\r\n");
- self._stream.write("RSET\r\n");
- }
+ function doProcess() {
+ var email = self._queue.shift();
- if (self._queue.length > 0) {
- process.nextTick(dequeue);
- } else {
- self._processing = false;
- self.disconnect();
+ 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();
+ }
+ }
}
};
@@ -116,15 +156,41 @@ Connection.prototype = {
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) ) {
- // Emit 'auth' event
+ 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;
@@ -138,29 +204,15 @@ Connection.prototype = {
if (typeof fn === 'function') {
// Set auth callback
- stream_promise.on('auth', onAuth);
- function onAuth() {
- // Reset timeout counter
- clearTimeout(auth_timeout);
-
- // Call callback
- fn(null, self._stream);
- };
-
- // Remove callback after timeout
- var auth_timeout = setTimeout(function() {
- // Remove listener
- stream_promise.removeListener('auth', onAuth);
-
- // Do not leave connection
- try {
- self.disconnect();
- } catch (e) {
+ stream_promise.wait('auth', function(err) {
+ if (err) {
+ try {
+ self.disconnect();
+ } catch (e) {
+ }
}
-
- // Call callback
- fn('auth_timeout');
- }, self.options.auth_timeout || 3000);
+ fn(err, self._stream);
+ }, self.options.auth_timeout);
}
} else {
if (typeof fn === 'function') {
@@ -171,6 +223,7 @@ Connection.prototype = {
stream.on("error", function() {
self.callback(new Error("could not connect"));
+ console.log(arguments);
stream.destroy();
self._connecting = false;
stream = null;
@@ -204,6 +257,7 @@ Connection.prototype = {
});
},
disconnect : function() {
+ this._processing = false;
if (this._stream) {
this._stream.end('quit\r\n');
this._stream = null;
2  package.json
View
@@ -1,7 +1,7 @@
{
"name": "mailer",
"description": "send emails from node.js to a smtp server, simple as cake",
- "version": "0.4.4",
+ "version": "0.4.5",
"author": "Marak Squires",
"contributors" : [
"Elijah Insua <tmpvar@gmail.com> (http://tmvpar.com/)"
Please sign in to comment.
Something went wrong with that request. Please try again.