Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
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
@indutny indutny authored
Showing with 104 additions and 50 deletions.
  1. +103 −49 lib/node_mailer.js
  2. +1 −1  package.json
View
152 lib/node_mailer.js
@@ -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;
View
2  package.json
@@ -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.