FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

GitHub Viewer

// Copyright 2012-2018 (c) Peter Širka // // Permission is hereby granted, free of charge, to any person obtaining a // copy of this software and associated documentation files (the // "Software"), to deal in the Software without restriction, including // without limitation the rights to use, copy, modify, merge, publish, // distribute, sublicense, and/or sell copies of the Software, and to permit // persons to whom the Software is furnished to do so, subject to the // following conditions: // // The above copyright notice and this permission notice shall be included // in all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE // USE OR OTHER DEALINGS IN THE SOFTWARE. /** * @module FrameworkMail * @version 2.9.4 */ 'use strict'; const Net = require('net'); const Tls = require('tls'); const Fs = require('fs'); const CRLF = '\r\n'; const REG_ESMTP = /\besmtp\b/i; const REG_STATE = /\d+/; const REG_WINLINE = /\r\n/g; const REG_NEWLINE = /\n/g; const REG_AUTH = /(AUTH LOGIN|AUTH PLAIN)/i; const EMPTYARRAY = []; var INDEXSENDER = 0; var INDEXATTACHMENT = 0; if (!global.framework_utils) global.framework_utils = require('./utils'); const BUF_CRLF = framework_utils.createBuffer(CRLF); const CONCAT = [null, null]; /** * Mailer * @class * @property {Boolean} debug Debug mode (true/false). */ function Mailer() { this.debug = false; this.Message = Message; this.Mail = Message; this.connections = {}; this.$events = {}; } Mailer.prototype.emit = function(name, a, b, c, d, e, f, g) { var evt = this.$events[name]; if (evt) { var clean = false; for (var i = 0, length = evt.length; i < length; i++) { if (evt[i].$once) clean = true; evt[i].call(this, a, b, c, d, e, f, g); } if (clean) { evt = evt.remove(n => n.$once); if (evt.length) this.$events[name] = evt; else this.$events[name] = undefined; } } return this; }; Mailer.prototype.on = function(name, fn) { if (this.$events[name]) this.$events[name].push(fn); else this.$events[name] = [fn]; return this; }; Mailer.prototype.once = function(name, fn) { fn.$once = true; return this.on(name, fn); }; Mailer.prototype.removeListener = function(name, fn) { var evt = this.$events[name]; if (evt) { evt = evt.remove(n => n === fn); if (evt.length) this.$events[name] = evt; else this.$events[name] = undefined; } return this; }; Mailer.prototype.removeAllListeners = function(name) { if (name) this.$events[name] = undefined; else this.$events = {}; return this; }; /** * Create Mail Message * @param {String} subject * @param {String} body * @return {MailMessage} */ Mailer.prototype.create = function(subject, body) { return new Message(subject, body); }; /** * Message send callback * @callback ResolveMxCallback * @param {Error} err Error handling. * @param {Socket} socket Net socket. */ /** * Mail Message * @param {String} subject * @param {String} body * @property {String} subject * @property {String} body */ function Message(subject, body) { this.subject = subject || ''; this.body = body || ''; this.files; this.addressTo = []; this.addressReply; this.addressCC; this.addressBCC; this.addressFrom = { name: '', address: '' }; this.closed = false; this.tls = false; this.$callback; // Supports (but it's hidden): // this.headers; // this.$unsubscribe; } Message.prototype.unsubscribe = function(url) { var tmp = url.substring(0, 6); this.$unsubscribe = tmp === 'http:/' || tmp === 'https:' ? '' : ''; return this; }; Message.prototype.callback = function(fn) { this.$callback = fn; return this; }; Message.prototype.sender = function(address, name) { return this.from(address, name); }; Message.prototype.from = function(address, name) { if (address[address.length - 1] === '>') { var index = address.indexOf('') { var index = address.indexOf('') { var index = address.indexOf(' self.$send(obj, options, true)); obj.socket2.on('error', function(err) { mailer.destroy(obj); self.closed = true; self.callback && self.callback(err); self.callback = null; if (obj.try || err.stack.indexOf('ECONNRESET') !== -1) return; mailer.$events.error && mailer.emit('error', err, obj); }); obj.socket2.on('clientError', function(err) { mailer.destroy(obj); self.callback && self.callback(err); self.callback = null; mailer.$events.error && !obj.try && mailer.emit('error', err, obj); }); obj.socket2.on('connect', () => !options.secure && self.$send(obj, options)); }; Mailer.prototype.destroy = function(obj) { if (obj.destroyed) return this; obj.destroyed = true; obj.closed = true; if (obj.socket) { obj.socket.removeAllListeners(); obj.socket.end(); obj.socket.destroy(); obj.socket = null; } if (obj.socket2) { obj.socket2.removeAllListeners(); obj.socket2.end(); obj.socket2.destroy(); obj.socket2 = null; } delete this.connections[obj.id]; return this; }; const ATTACHMENT_SO = { encoding: 'base64' }; Mailer.prototype.$writeattachment = function(obj) { var attachment = obj.files ? obj.files.shift() : false; if (!attachment) { mailer.$writeline(obj, '--' + obj.boundary + '--', '', '.'); obj.messagecallback && obj.messagecallback(null, obj.instance); obj.messagecallback = null; return this; } var name = attachment.name; var stream = Fs.createReadStream(attachment.filename, ATTACHMENT_SO); var message = []; var extension = attachment.extension; var isCalendar = extension === 'ics'; message.push('--' + obj.boundary); if (!isCalendar) { if (attachment.contentId) { message.push('Content-Disposition: inline; filename="' + name + '"'); message.push('Content-ID: '); } else message.push('Content-Disposition: attachment; filename="' + name + '"'); } message.push('Content-Type: ' + attachment.type + ';' + (isCalendar ? ' charset="utf-8"; method=REQUEST' : '')); message.push('Content-Transfer-Encoding: base64'); message.push(CRLF); mailer.$writeline(obj, message.join(CRLF)); stream.$mailer = mailer; stream.$mailerobj = obj; stream.on('data', writeattachment_data); CLEANUP(stream, function() { mailer.$writeline(obj, CRLF); mailer.$writeattachment(obj); }); return this; }; function writeattachment_data(chunk) { var length = chunk.length; var count = 0; var beg = 0; while (count < length) { count += 68; if (count > length) count = length; this.$mailer.$writeline(this.$mailerobj, chunk.slice(beg, count).toString('base64')); beg = count; } } Mailer.prototype.try = function(smtp, options, callback) { return this.send(smtp, options, undefined, callback); }; Mailer.prototype.send2 = function(messages, callback) { var opt = F.temporary['mail-settings']; if (!opt) { var config = F.config['mail-smtp-options']; if (config) { if (typeof(config) === 'object') opt = config; else opt = config.toString().parseJSON(); } if (!opt) opt = {}; F.temporary['mail-settings'] = opt; } return this.send(F.config['mail-smtp'], opt, messages, callback); }; Mailer.prototype.send = function(smtp, options, messages, callback) { if (options instanceof Array) { callback = messages; messages = options; options = {}; } else if (typeof(options) === 'function') { callback = options; options = {}; } var self = this; var id = 'abcdefghijkl' + (INDEXSENDER++); self.connections[id] = {}; var obj = self.connections[id]; obj.id = id; obj.try = messages === undefined; obj.messages = obj.try ? EMPTYARRAY : messages instanceof Array ? messages : [messages]; obj.callback = callback; obj.closed = false; obj.message = null; obj.files = null; obj.count = 0; obj.socket; obj.tls = false; obj.date = global.F ? global.F.datetime : new Date(); smtp = smtp || null; if (options && options.secure && !options.port) options.port = 465; options = framework_utils.copy(options, { secure: false, port: 25, user: '', password: '', timeout: 10000, tls: null }); if (options.secure) { var internal = framework_utils.copy(options); internal.host = smtp; obj.socket = Tls.connect(internal, () => mailer.$send(obj, options)); } else obj.socket = Net.createConnection(options.port, smtp); if (!smtp) { var err = new Error('No SMTP server configuration. Mail message won\'t be sent.'); callback && callback(err); F.error(err, 'mail-smtp'); return self; } obj.socket.$host = smtp; obj.host = smtp.substring(smtp.lastIndexOf('.', smtp.lastIndexOf('.') - 1) + 1); obj.socket.on('error', function(err) { mailer.destroy(obj); obj.callback && obj.callback(err); obj.callback = null; if (obj.try || err.stack.indexOf('ECONNRESET') !== -1) return; mailer.$events.error && mailer.emit('error', err, obj); }); obj.socket.on('clientError', function(err) { mailer.destroy(obj); obj.callback && obj.callback(err); obj.callback = null; mailer.$events.error && !obj.try && mailer.emit('error', err, obj); }); obj.socket.setTimeout(options.timeout || 8000, function() { var err = new Error(framework_utils.httpStatus(408)); mailer.destroy(obj); obj.callback && obj.callback(err); obj.callback = null; mailer.$events.error && !obj.try && mailer.emit('error', err, obj); }); obj.socket.on('connect', () => !options.secure && mailer.$send(obj, options)); return self; }; Mailer.prototype.$writemessage = function(obj, buffer) { var self = this; var msg = obj.messages.shift(); var message = []; if (global.F) global.F.stats.other.mail++; obj.boundary = '--totaljs' + obj.date.getTime() + obj.count; obj.files = msg.files; obj.count++; buffer.push('MAIL FROM: '); message.push('Message-ID: '); message.push('MIME-Version: 1.0'); message.push('From: ' + (msg.addressFrom.name ? unicode_encode(msg.addressFrom.name) + ' ' : msg.addressFrom.address)); var length; if (msg.headers) { var headers = Object.keys(msg.headers); for (var i = 0, length = headers.length; i < length; i++) message.push(headers[i] + ': ' + msg.headers[headers[i]]); } length = msg.addressTo.length; var builder = ''; var mail; var item; if (length) { for (var i = 0; i < length; i++) { item = msg.addressTo[i]; if (item instanceof Object) mail = ''; else mail = ''; buffer.push('RCPT TO: ' + mail); builder += (builder ? ', ' : '') + (item instanceof Object ? unicode_encode(item.name) + ' ' : '') + mail; } message.push('To: ' + builder); builder = ''; } if (msg.addressCC) { length = msg.addressCC.length; for (var i = 0; i < length; i++) { item = msg.addressCC[i]; if (item instanceof Object) mail = ''; else mail = ''; buffer.push('RCPT TO: ' + mail); builder += (builder ? ', ' : '') + (item instanceof Object ? unicode_encode(item.name) + ' ' : '') + mail; } message.push('Cc: ' + builder); builder = ''; } if (msg.addressBCC) { length = msg.addressBCC.length; for (var i = 0; i < length; i++) buffer.push('RCPT TO: '); } buffer.push('DATA'); buffer.push(''); message.push('Date: ' + obj.date.toUTCString()); message.push('Subject: ' + unicode_encode(msg.subject)); msg.$unsubscribe && message.push('List-Unsubscribe: ' + msg.$unsubscribe); if (msg.addressReply) { length = msg.addressReply.length; for (var i = 0; i < length; i++) builder += (builder !== '' ? ', ' : '') + ''; message.push('Reply-To: ' + builder); builder = ''; } message.push('Content-Type: multipart/mixed; boundary=' + obj.boundary); message.push(''); message.push('--' + obj.boundary); message.push('Content-Type: ' + (msg.body.indexOf('') !== -1 ? 'text/html' : 'text/plain') + '; charset=utf-8'); message.push('Content-Transfer-Encoding: base64'); message.push(''); message.push(prepareBASE64(framework_utils.createBuffer(msg.body.replace(REG_WINLINE, '\n').replace(REG_NEWLINE, CRLF)).toString('base64'))); obj.message = message.join(CRLF); obj.messagecallback = msg.$callback; obj.instance = msg; message = null; return self; }; Mailer.prototype.$writeline = function(obj) { if (obj.closed) return false; var socket = obj.socket2 ? obj.socket2 : obj.socket; for (var i = 1; i < arguments.length; i++) { var line = arguments[i]; if (line) { mailer.debug && console.log('SEND', line); socket.write(line + CRLF); } } return true; }; Mailer.prototype.$send = function(obj, options, autosend) { var self = this; var buffer = []; var isAuthorized = false; var isAuthorization = false; var command = ''; var auth = []; var socket = obj.socket2 ? obj.socket2 : obj.socket; var host = obj.host; var line = null; var isAttach = !options.tls || (obj.tls && options.tls); isAttach && mailer.$events.send && mailer.emit('send', obj); socket.setEncoding('utf8'); socket.on('end', function() { mailer.destroy(obj); obj.callback && obj.callback(); obj.callback = null; line = null; }); socket.on('data', function(data) { if (obj.closed) return; while (true) { var index = data.indexOf(BUF_CRLF); if (index === -1) { if (line) { CONCAT[0] = line; CONCAT[1] = data; line = Buffer.concat(CONCAT); } else line = data; break; } var tmp = data.slice(0, index).toString('utf8'); data = data.slice(index + BUF_CRLF.length); tmp && socket && socket.emit('line', tmp); } }); socket.on('line', function(line) { line = line.toUpperCase(); mailer.debug && console.log('

Back | FazBrowse Home | New Git URL