Sindbad~EG File Manager
'use strict';
var SMTPConnection = require('smtp-connection');
var packageData = require('../package.json');
var wellknown = require('nodemailer-wellknown');
var shared = require('nodemailer-shared');
var EventEmitter = require('events').EventEmitter;
var util = require('util');
// expose to the world
module.exports = function (options) {
return new SMTPTransport(options);
};
/**
* Creates a SMTP transport object for Nodemailer
*
* @constructor
* @param {Object} options Connection options
*/
function SMTPTransport(options) {
EventEmitter.call(this);
options = options || {};
if (typeof options === 'string') {
options = {
url: options
};
}
var urlData;
var service = options.service;
if (typeof options.getSocket === 'function') {
this.getSocket = options.getSocket;
}
if (options.url) {
urlData = shared.parseConnectionUrl(options.url);
service = service || urlData.service;
}
this.options = assign(
false, // create new object
options, // regular options
urlData, // url options
service && wellknown(service) // wellknown options
);
this.logger = shared.getLogger(this.options);
// temporary object
var connection = new SMTPConnection(this.options);
this.name = 'SMTP';
this.version = packageData.version + '[client:' + connection.version + ']';
}
util.inherits(SMTPTransport, EventEmitter);
/**
* Placeholder function for creating proxy sockets. This method immediatelly returns
* without a socket
*
* @param {Object} options Connection options
* @param {Function} callback Callback function to run with the socket keys
*/
SMTPTransport.prototype.getSocket = function (options, callback) {
// return immediatelly
return callback(null, false);
};
/**
* Sends an e-mail using the selected settings
*
* @param {Object} mail Mail object
* @param {Function} callback Callback function
*/
SMTPTransport.prototype.send = function (mail, callback) {
this.getSocket(this.options, function (err, socketOptions) {
if (err) {
return callback(err);
}
var options = this.options;
if (socketOptions && socketOptions.connection) {
this.logger.info('Using proxied socket from %s:%s to %s:%s', socketOptions.connection.remoteAddress, socketOptions.connection.remotePort, options.host || '', options.port || '');
// only copy options if we need to modify it
options = assign(false, options);
Object.keys(socketOptions).forEach(function (key) {
options[key] = socketOptions[key];
});
}
var connection = new SMTPConnection(options);
var returned = false;
connection.once('error', function (err) {
if (returned) {
return;
}
returned = true;
connection.close();
return callback(err);
});
connection.once('end', function () {
if (returned) {
return;
}
returned = true;
return callback(new Error('Connection closed'));
});
var sendMessage = function () {
var envelope = mail.message.getEnvelope();
var messageId = (mail.message.getHeader('message-id') || '').replace(/[<>\s]/g, '');
var recipients = [].concat(envelope.to || []);
if (recipients.length > 3) {
recipients.push('...and ' + recipients.splice(2).length + ' more');
}
this.logger.info('Sending message <%s> to <%s>', messageId, recipients.join(', '));
connection.send(envelope, mail.message.createReadStream(), function (err, info) {
if (returned) {
return;
}
returned = true;
connection.close();
if (err) {
return callback(err);
}
info.envelope = {
from: envelope.from,
to: envelope.to
};
info.messageId = messageId;
return callback(null, info);
});
}.bind(this);
connection.connect(function () {
if (returned) {
return;
}
if (this.options.auth) {
connection.login(this.options.auth, function (err) {
if (returned) {
return;
}
if (err) {
returned = true;
connection.close();
return callback(err);
}
sendMessage();
});
} else {
sendMessage();
}
}.bind(this));
}.bind(this));
};
/**
* Verifies SMTP configuration
*
* @param {Function} callback Callback function
*/
SMTPTransport.prototype.verify = function (callback) {
var promise;
if (!callback && typeof Promise === 'function') {
promise = new Promise(function (resolve, reject) {
callback = shared.callbackPromise(resolve, reject);
});
}
this.getSocket(this.options, function (err, socketOptions) {
if (err) {
return callback(err);
}
var options = this.options;
if (socketOptions && socketOptions.connection) {
this.logger.info('Using proxied socket from %s:%s', socketOptions.connection.remoteAddress, socketOptions.connection.remotePort);
options = assign(false, options);
Object.keys(socketOptions).forEach(function (key) {
options[key] = socketOptions[key];
});
}
var connection = new SMTPConnection(options);
var returned = false;
connection.once('error', function (err) {
if (returned) {
return;
}
returned = true;
connection.close();
return callback(err);
});
connection.once('end', function () {
if (returned) {
return;
}
returned = true;
return callback(new Error('Connection closed'));
});
var finalize = function () {
if (returned) {
return;
}
returned = true;
connection.quit();
return callback(null, true);
};
connection.connect(function () {
if (returned) {
return;
}
if (this.options.auth) {
connection.login(this.options.auth, function (err) {
if (returned) {
return;
}
if (err) {
returned = true;
connection.close();
return callback(err);
}
finalize();
});
} else {
finalize();
}
}.bind(this));
}.bind(this));
return promise;
};
/**
* Copies properties from source objects to target objects
*/
function assign( /* target, ... sources */ ) {
var args = Array.prototype.slice.call(arguments);
var target = args.shift() || {};
args.forEach(function (source) {
Object.keys(source || {}).forEach(function (key) {
if (['tls', 'auth'].indexOf(key) >= 0 && source[key] && typeof source[key] === 'object') {
// tls and auth are special keys that need to be enumerated separately
// other objects are passed as is
if (!target[key]) {
// esnure that target has this key
target[key] = {};
}
Object.keys(source[key]).forEach(function (subKey) {
target[key][subKey] = source[key][subKey];
});
} else {
target[key] = source[key];
}
});
});
return target;
}
Sindbad File Manager Version 1.0, Coded By Sindbad EG ~ The Terrorists