total5 0.0.1-1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/503.html +65 -0
  2. package/CONTRIBUTING.md +55 -0
  3. package/LICENSE +211 -0
  4. package/README.md +32 -0
  5. package/api.js +289 -0
  6. package/bin/total5 +984 -0
  7. package/builders.js +1435 -0
  8. package/bundles.js +457 -0
  9. package/cache.js +58 -0
  10. package/changelog.txt +3 -0
  11. package/cluster.js +320 -0
  12. package/cms.js +625 -0
  13. package/controller.js +1419 -0
  14. package/cron.js +99 -0
  15. package/debug.js +539 -0
  16. package/edit.js +469 -0
  17. package/error.html +49 -0
  18. package/filestorage.js +1088 -0
  19. package/flow-flowstream.js +3152 -0
  20. package/flow.js +209 -0
  21. package/flowstream.js +1991 -0
  22. package/global.js +125 -0
  23. package/helpers/index.js +32 -0
  24. package/htmlparser.js +650 -0
  25. package/http.js +81 -0
  26. package/image.js +773 -0
  27. package/images.js +747 -0
  28. package/index.js +2658 -0
  29. package/jsonschema.js +691 -0
  30. package/ldap.js +792 -0
  31. package/mail.js +936 -0
  32. package/minificators.js +858 -0
  33. package/nosql-builder.js +440 -0
  34. package/nosql-querybuilder.js +316 -0
  35. package/nosql-reader.js +353 -0
  36. package/nosql-stream.js +617 -0
  37. package/nosql.js +763 -0
  38. package/openclient.js +219 -0
  39. package/package.json +32 -0
  40. package/pause.html +67 -0
  41. package/querybuilder.js +1361 -0
  42. package/release.js +167 -0
  43. package/routing.js +905 -0
  44. package/sourcemap.js +160 -0
  45. package/tangular.js +409 -0
  46. package/templates.js +145 -0
  47. package/templates.json +74 -0
  48. package/tms.js +384 -0
  49. package/tmsclient.js +125 -0
  50. package/todo.txt +7 -0
  51. package/tools/beta.sh +6 -0
  52. package/tools/release.sh +6 -0
  53. package/uibuilder.js +206 -0
  54. package/utils.js +6374 -0
  55. package/viewengine.js +880 -0
  56. package/websocket.js +1939 -0
  57. package/workers.js +129 -0
package/mail.js ADDED
@@ -0,0 +1,936 @@
1
+ // Total.js SMTP sender
2
+ // The MIT License
3
+ // Copyright 2016-2023 (c) Peter Širka <petersirka@gmail.com>
4
+
5
+ const CRLF = '\r\n';
6
+ const REG_ESMTP = /\besmtp\b/i;
7
+ const REG_STATE = /\d+/;
8
+ const REG_WINLINE = /\r\n/g;
9
+ const REG_NEWLINE = /\n/g;
10
+ const REG_AUTH = /(AUTH LOGIN|AUTH PLAIN|PLAIN LOGIN|XOAUTH2|XOAUTH)/i;
11
+ const REG_TLS = /TLS/;
12
+ const REG_STARTTLS = /STARTTLS/;
13
+ const ATTACHMENT = { encoding: 'base64' };
14
+
15
+ var INDEXATTACHMENT = 0;
16
+
17
+ const CRLF_BUFFER = Buffer.from(CRLF);
18
+ const CONCAT = [null, null];
19
+
20
+ var Mailer = {};
21
+ Mailer.debug = false;
22
+ Mailer.Message = Message;
23
+ Mailer.Mail = Message;
24
+ Mailer.connections = {};
25
+ Mailer.create = (subject, body) => new Message(subject, body);
26
+ F.TUtils.EventEmitter2.extend(Mailer);
27
+
28
+ function Message(subject, body) {
29
+ var self = this;
30
+ self.subject = subject || '';
31
+ self.body = body || '';
32
+ self.type = 'html';
33
+ self.files;
34
+ self.email_to = [];
35
+ self.email_reply;
36
+ self.email_cc;
37
+ self.email_bcc;
38
+ self.email_from = '';
39
+ self.closed = false;
40
+ self.tls = false;
41
+ self.$callback;
42
+
43
+ // t.headers;
44
+ // t.$unsubscribe;
45
+ }
46
+
47
+ Message.prototype.preview = function(val) {
48
+ this.$preview = val;
49
+ return this;
50
+ };
51
+
52
+ Message.prototype.unsubscribe = function(url) {
53
+ var tmp = url.substring(0, 6);
54
+ this.$unsubscribe = url ? (tmp === 'http:/' || tmp === 'https:' ? '<' + url + '>' : '<mailto:' + url + '>') : null;
55
+ return this;
56
+ };
57
+
58
+ Message.prototype.callback = function(fn) {
59
+ this.$callback = fn;
60
+ return this;
61
+ };
62
+
63
+ Message.prototype.sender = Message.prototype.from = function(email) {
64
+ this.email_from = email;
65
+ return this;
66
+ };
67
+
68
+ Message.prototype.high = function() {
69
+ this.$priority = 1;
70
+ return this;
71
+ };
72
+
73
+ Message.prototype.low = function() {
74
+ this.$priority = 5;
75
+ return this;
76
+ };
77
+
78
+ Message.prototype.confidential = function() {
79
+ this.$confidential = true;
80
+ return this;
81
+ };
82
+
83
+ Message.prototype.to = function(value, clear) {
84
+ var self = this;
85
+ if (clear)
86
+ self.email_to.length = 0;
87
+ self.email_to.push(value);
88
+ return self;
89
+ };
90
+
91
+ Message.prototype.cc = function(value, clear) {
92
+ var self = this;
93
+ if (clear || !self.email_cc)
94
+ self.email_cc = [];
95
+ self.email_cc.push(value);
96
+ return self;
97
+ };
98
+
99
+ Message.prototype.bcc = function(value, clear) {
100
+ var self = this;
101
+ if (clear || !self.email_bcc)
102
+ self.email_bcc = [];
103
+ self.email_bcc.push(value);
104
+ return self;
105
+ };
106
+
107
+ Message.prototype.reply = function(value, clear) {
108
+ var self = this;
109
+ if (clear || !self.email_reply)
110
+ self.email_reply = [];
111
+ self.email_reply.push(value);
112
+ return self;
113
+ };
114
+
115
+ Message.prototype.attachment = function(filename, name, contentid) {
116
+
117
+ var self = this;
118
+ var type;
119
+ var ext;
120
+
121
+ if (name) {
122
+ ext = F.TUtils.getExtension(name);
123
+ type = F.TUtils.contentTypes[ext];
124
+ }
125
+
126
+ var obj = {};
127
+ obj.name = name;
128
+ obj.filename = filename;
129
+ obj.type = type;
130
+ obj.ext = ext;
131
+
132
+ if (contentid) {
133
+ obj.disposition = 'inline';
134
+ obj.contentid = contentid;
135
+ }
136
+
137
+ if (!self.attachments)
138
+ self.attachments = [];
139
+
140
+ self.attachments.push(obj);
141
+ return self;
142
+ };
143
+
144
+ Message.prototype.attachmentfs = function(storage, id, name, contentid) {
145
+
146
+ var self = this;
147
+ var ext;
148
+ var type;
149
+
150
+ if (name) {
151
+ ext = F.TUtils.getExtension(name);
152
+ type = F.TUtils.contentTypes[ext];
153
+ }
154
+
155
+ var obj = {};
156
+ obj.storage = storage;
157
+ obj.name = name;
158
+ obj.filename = id;
159
+ obj.type = type;
160
+ obj.ext = ext;
161
+
162
+ if (contentid) {
163
+ obj.disposition = 'inline';
164
+ obj.contentid = contentid;
165
+ }
166
+
167
+ if (!self.attachments)
168
+ self.attachments = [];
169
+
170
+ self.attachments.push(obj);
171
+ return self;
172
+ };
173
+
174
+ Message.prototype.manually = function() {
175
+ this.$sending && clearImmediate(this.$sending);
176
+ return this;
177
+ };
178
+
179
+ Message.prototype.send2 = function(callback) {
180
+
181
+ var self = this;
182
+
183
+ if (F.config.$tapi && F.config.$tapimail) {
184
+
185
+ var data = {};
186
+
187
+ data.to = [];
188
+
189
+ for (let m of self.email_to)
190
+ data.to.push(m);
191
+
192
+ if (self.email_cc && self.email_cc.length) {
193
+ data.cc = [];
194
+ for (let m of self.email_cc)
195
+ data.cc.push(m);
196
+ }
197
+
198
+ if (self.email_bcc && self.email_bcc.length) {
199
+ data.bcc = [];
200
+ for (let m of self.email_bcc)
201
+ data.bcc.push(m);
202
+ }
203
+
204
+ if (self.email_reply && self.email_reply.length) {
205
+ data.reply = [];
206
+ for (let m of self.email_reply)
207
+ data.reply.push(m);
208
+ }
209
+
210
+ data.from = self.email_from;
211
+ data.subject = self.subject;
212
+ data.type = self.type;
213
+ data.body = self.body;
214
+ data.priority = self.$priotity;
215
+ data.unsubscribe = self.$unsubscribe;
216
+ data.confidential = self.$confidential;
217
+
218
+ F.api('TAPI/mail', data).callback(callback || NOOP);
219
+ return;
220
+ }
221
+
222
+ for (let key in F.temporary.smtp)
223
+ Mailer.destroy(F.temporary.smtp[key]);
224
+
225
+ Mailer.send(F.config.smtp, self, callback);
226
+ };
227
+
228
+ Message.prototype.send = function(smtp, options, callback) {
229
+ this.$callback2 = callback;
230
+ Mailer.send(smtp, options, this);
231
+ return this;
232
+ };
233
+
234
+ Mailer.tls = function(obj, opt) {
235
+
236
+ var self = this;
237
+
238
+ obj.tls = true;
239
+ obj.socket.removeAllListeners();
240
+
241
+ var tlsoptions = { socket: obj.socket, host: obj.socket.$host, ciphers: 'SSLv3' };
242
+
243
+ for (let key in opt.tls)
244
+ tlsoptions[key] = opt.tls[key];
245
+
246
+ obj.socket2 = F.Tls.connect(tlsoptions, () => self.$send(obj, opt, true));
247
+
248
+ obj.socket2.on('error', function(err) {
249
+ Mailer.destroy(obj);
250
+ self.closed = true;
251
+ self.callback && self.callback(err);
252
+ self.callback = null;
253
+ if (obj.try || err.stack.indexOf('ECONNRESET') !== -1)
254
+ return;
255
+ Mailer.$events.error && Mailer.emit('error', err, obj);
256
+ });
257
+
258
+ obj.socket2.on('clientError', function(err) {
259
+ Mailer.destroy(obj);
260
+ self.callback && self.callback(err);
261
+ self.callback = null;
262
+ Mailer.$events.error && !obj.try && Mailer.emit('error', err, obj);
263
+ });
264
+
265
+ obj.socket2.on('connect', () => !opt.secure && self.$send(obj, opt));
266
+ };
267
+
268
+ Mailer.destroy = function(obj) {
269
+
270
+ var self = this;
271
+
272
+ if (obj.destroyed)
273
+ return self;
274
+
275
+ obj.destroyed = true;
276
+ obj.closed = true;
277
+
278
+ if (obj.socket) {
279
+ obj.socket.removeAllListeners();
280
+ obj.socket.end();
281
+ obj.socket.destroy();
282
+ obj.socket = null;
283
+ }
284
+
285
+ if (obj.socket2) {
286
+ obj.socket2.removeAllListeners();
287
+ obj.socket2.end();
288
+ obj.socket2.destroy();
289
+ obj.socket2 = null;
290
+ }
291
+
292
+ if (obj === F.temporary.smtp[obj.server])
293
+ delete F.temporary.smtp[obj.server];
294
+
295
+ delete self.connections[obj.id];
296
+ return self;
297
+ };
298
+
299
+ Mailer.$writeattachment = function(obj) {
300
+
301
+ var attachment = obj.files ? obj.files.shift() : false;
302
+ if (!attachment) {
303
+
304
+ Mailer.$writeline(obj, '--' + obj.boundary + '--', '', '.');
305
+
306
+ if (obj.callback) {
307
+ obj.callback(null, obj.instance);
308
+ obj.callback = null;
309
+ }
310
+
311
+ if (obj.messagecallback) {
312
+ obj.messagecallback(null, obj.instance);
313
+ obj.messagecallback = null;
314
+ }
315
+
316
+ if (obj.messagecallback2) {
317
+ obj.messagecallback2(null, obj.instance);
318
+ obj.messagecallback2 = null;
319
+ }
320
+
321
+ return this;
322
+ }
323
+
324
+ var stream;
325
+
326
+ if (attachment.storage) {
327
+ FILESTORAGE(attachment.storage).readbase64(attachment.filename, function(err, meta) {
328
+ if (err) {
329
+ F.error(err, 'Mail.filestorage()', attachment.filename);
330
+ Mailer.$writeattachment(obj);
331
+ } else {
332
+
333
+ if (!attachment.name) {
334
+ attachment.name = meta.name;
335
+ attachment.type = meta.type;
336
+ attachment.extension = meta.ext;
337
+ }
338
+
339
+ writeattachemnt_stream(attachment, obj, meta.stream);
340
+ }
341
+ });
342
+ } else {
343
+ F.stats.performance.open++;
344
+ stream = F.Fs.createReadStream(attachment.filename, ATTACHMENT);
345
+ writeattachemnt_stream(attachment, obj, stream);
346
+ }
347
+
348
+ return this;
349
+ };
350
+
351
+ function writeattachemnt_stream(attachment, obj, stream) {
352
+
353
+ var name = attachment.name;
354
+ var isCalendar = attachment.extension === 'ics';
355
+ var message = [];
356
+
357
+ message.push('--' + obj.boundary);
358
+
359
+ if (!isCalendar) {
360
+ if (attachment.contentid) {
361
+ message.push('Content-Disposition: inline; filename="' + name + '"');
362
+ message.push('Content-ID: <' + attachment.contentid + '>');
363
+ } else
364
+ message.push('Content-Disposition: attachment; filename="' + name + '"');
365
+ }
366
+
367
+ message.push('Content-Type: ' + attachment.type + ';' + (isCalendar ? ' charset="utf-8"; method=REQUEST' : ''));
368
+ message.push('Content-Transfer-Encoding: base64');
369
+ message.push(CRLF);
370
+ Mailer.$writeline(obj, message.join(CRLF));
371
+
372
+ stream.$mailerdata = obj;
373
+ stream.on('data', writeattachmentbytes);
374
+
375
+ F.cleanup(stream, function() {
376
+ Mailer.$writeline(obj, CRLF);
377
+ Mailer.$writeattachment(obj);
378
+ });
379
+ }
380
+
381
+ function writeattachmentbytes(chunk) {
382
+
383
+ var length = chunk.length;
384
+ var count = 0;
385
+ var beg = 0;
386
+
387
+ while (count < length) {
388
+
389
+ count += 68;
390
+
391
+ if (count > length)
392
+ count = length;
393
+
394
+ Mailer.$writeline(this.$mailerdata, chunk.slice(beg, count).toString('base64'));
395
+ beg = count;
396
+ }
397
+ }
398
+
399
+ Mailer.try = function(smtp, options, callback) {
400
+ var self = this;
401
+ if (callback)
402
+ return self.send(smtp, options, undefined, callback);
403
+ else
404
+ return new Promise((resolve, reject) => self.send(smtp, options, undefined, err => err ? reject(err) : resolve()));
405
+ };
406
+
407
+ Mailer.send2 = function(messages, callback) {
408
+
409
+ var opt = F.temporary.mail;
410
+
411
+ if (!opt) {
412
+ var config = CONF.mail_smtp_options;
413
+ if (config) {
414
+ if (typeof(config) === 'object')
415
+ opt = config;
416
+ else
417
+ opt = config.toString().parseJSON();
418
+ }
419
+
420
+ if (!opt)
421
+ opt = {};
422
+
423
+ F.temporary.mail = opt;
424
+ }
425
+
426
+ return this.send(CONF.mail_smtp, opt, messages, callback);
427
+ };
428
+
429
+ Mailer.send = function(opt, messages, callback, cache) {
430
+
431
+ var cached = opt.keepalive != false ? F.temporary.smtp[opt.server] : null;
432
+
433
+ if (cached) {
434
+ if (messages instanceof Array) {
435
+ var count = messages.length;
436
+ F.stats.performance.mail += count;
437
+ for (var i = 0; i < count; i++)
438
+ cached.messages.push(messages[i]);
439
+ } else if (messages) {
440
+ F.stats.performance.mail++;
441
+ cached.messages.push(messages);
442
+ }
443
+ cached.trytosend();
444
+ return;
445
+ }
446
+
447
+ var self = this;
448
+ var id = F.TUtils.guid();
449
+
450
+ self.connections[id] = {};
451
+ var obj = self.connections[id];
452
+
453
+ obj.id = id;
454
+ obj.buffer = [];
455
+ obj.try = messages === undefined;
456
+ obj.messages = obj.try ? F.EMPTYARRAY : messages instanceof Array ? messages : [messages];
457
+
458
+ F.stats.performance.mail += obj.messages.length;
459
+
460
+ obj.callback = callback;
461
+ obj.closed = false;
462
+ obj.message = null;
463
+ obj.attachments = null;
464
+ obj.count = 0;
465
+ obj.socket;
466
+ obj.tls = false;
467
+ obj.date = new Date();
468
+
469
+ if (opt.secure && !opt.port)
470
+ opt.port = 465;
471
+
472
+ if (!opt.server) {
473
+ var err = new Error('No SMTP server configuration.');
474
+ callback && callback(err);
475
+ F.error(err, 'mail_smtp');
476
+ return self;
477
+ }
478
+
479
+ if (opt.secure) {
480
+ let internal = F.TUtils.copy(opt);
481
+ internal.host = opt.server;
482
+ obj.socket = F.Tls.connect(internal, () => Mailer.$send(obj, opt));
483
+ } else
484
+ obj.socket = F.Net.createConnection(opt.port, opt.server);
485
+
486
+ if (cache) {
487
+ obj.trytosend = function() {
488
+ if (!obj.sending && obj.messages && obj.messages.length) {
489
+ obj.sending = true;
490
+ obj.buffer = [];
491
+ Mailer.$writemessage(obj, obj.buffer);
492
+ Mailer.$writeline(obj, obj.buffer.shift());
493
+ }
494
+ };
495
+ obj.TS = NOW.add(cache === true ? '10 minutes' : typeof(cache) === 'number' ? (cache + ' minutes') : cache);
496
+ F.temporary.smtp[opt.server] = obj;
497
+ }
498
+
499
+ obj.cached = cache;
500
+ obj.smtp = opt;
501
+ obj.socket.$host = opt.server;
502
+ obj.host = opt.server.substring(opt.server.lastIndexOf('.', opt.server.lastIndexOf('.') - 1) + 1);
503
+
504
+ obj.socket.on('error', function(err) {
505
+
506
+ Mailer.destroy(obj);
507
+
508
+ var is = obj.callback ? true : false;
509
+
510
+ obj.callback && obj.callback(err);
511
+ obj.callback = null;
512
+
513
+ if (obj.try || err.stack.indexOf('ECONNRESET') !== -1)
514
+ return;
515
+
516
+ if (!obj.try && !is)
517
+ F.error(err, 'mail_smtp', opt.server);
518
+
519
+ if (obj === F.temporary.smtp[opt.server])
520
+ delete F.temporary.smtp[opt.server];
521
+
522
+ Mailer.$events.error && Mailer.emit('error', err, obj);
523
+ });
524
+
525
+ obj.socket.on('clientError', function(err) {
526
+
527
+ Mailer.destroy(obj);
528
+
529
+ if (!obj.try && !obj.callback)
530
+ F.error(err, 'mail_smtp', opt.server);
531
+
532
+ obj.callback && obj.callback(err);
533
+ obj.callback = null;
534
+
535
+ if (obj === F.temporary.smtp[opt.server])
536
+ delete F.temporary.smtp[opt.server];
537
+
538
+ if (Mailer.$events.error && !obj.try)
539
+ Mailer.emit('error', err, obj);
540
+
541
+ });
542
+
543
+ if (!cache) {
544
+ obj.socket.setTimeout(opt.timeout || 60000, function() {
545
+ var err = F.TUtils.httpstatus(408);
546
+ Mailer.destroy(obj);
547
+
548
+ if (!obj.try && !obj.callback)
549
+ F.error(err, 'mail_smtp', opt.server);
550
+
551
+ obj.callback && obj.callback(err);
552
+ obj.callback = null;
553
+
554
+ if (obj === F.temporary.smtp[opt.server])
555
+ delete F.temporary.smtp[opt.server];
556
+
557
+ if (Mailer.$events.error && !obj.try)
558
+ Mailer.emit('error', err, obj);
559
+ });
560
+ }
561
+
562
+ obj.sending = true;
563
+ obj.socket.on('connect', () => !opt.secure && Mailer.$send(obj, opt));
564
+ };
565
+
566
+ Mailer.$writemessage = function(obj, buffer) {
567
+
568
+ var self = this;
569
+ var msg = obj.messages.shift();
570
+ var message = [];
571
+
572
+ F.stats.other.mail++;
573
+ F.$events.$mail && F.emit('$mail', msg);
574
+
575
+ var dt = obj.date.getTime();
576
+
577
+ obj.boundary = '--total5' + dt;
578
+ obj.files = msg.files;
579
+ obj.count++;
580
+
581
+ message.push('MIME-Version: 1.0');
582
+ buffer.push('MAIL FROM: <' + msg.email_from + '>');
583
+ message.push('Message-ID: <total5_' + obj.date.toString(36) + '_' + (INDEXATTACHMENT++) + '_' + (INDEXATTACHMENT) + '>');
584
+
585
+ self.$priority && message.push('X-Priority: ' + self.$priority);
586
+ self.$confidential && message.push('Sensitivity: Company-Confidential');
587
+
588
+ message.push('From: <' + msg.email_from + '>');
589
+
590
+ if (msg.headers) {
591
+ for (let key in msg.headers)
592
+ message.push(key + ': ' + msg.headers[key]);
593
+ }
594
+
595
+ var builder = '';
596
+ var mail;
597
+
598
+ if (msg.email_to.length) {
599
+ for (let item of msg.email_to) {
600
+ mail = '<' + item + '>';
601
+ buffer.push('RCPT TO: ' + mail);
602
+ builder += (builder ? ', ' : '') + mail;
603
+ }
604
+ message.push('To: ' + builder);
605
+ builder = '';
606
+ }
607
+
608
+ if (msg.email_cc) {
609
+ for (let item of msg.email_cc) {
610
+ mail = '<' + item + '>';
611
+ buffer.push('RCPT TO: ' + mail);
612
+ builder += (builder ? ', ' : '') + mail;
613
+ }
614
+ message.push('Cc: ' + builder);
615
+ builder = '';
616
+ }
617
+
618
+ if (msg.email_bcc) {
619
+ for (let item of msg.email_bcc)
620
+ buffer.push('RCPT TO: <' + item + '>');
621
+ }
622
+
623
+ buffer.push('DATA');
624
+ buffer.push('');
625
+
626
+ message.push('Date: ' + obj.date.toUTCString());
627
+ message.push('Subject: ' + unicode_encode(msg.subject));
628
+
629
+ if (msg.$unsubscribe) {
630
+ message.push('List-Unsubscribe: ' + msg.$unsubscribe);
631
+ message.push('List-Unsubscribe-Post: List-Unsubscribe=One-Click');
632
+ }
633
+
634
+ if (msg.email_reply) {
635
+ for (let item of msg.email_reply)
636
+ builder += (builder !== '' ? ', ' : '') + '<' + item + '>';
637
+ message.push('Reply-To: ' + builder);
638
+ builder = '';
639
+ }
640
+
641
+ message.push('Content-Type: multipart/mixed; boundary="' + obj.boundary + '"');
642
+ message.push('');
643
+ message.push('--' + obj.boundary);
644
+ message.push('Content-Type: text/' + msg.type + '; charset="utf-8"');
645
+ message.push('Content-Transfer-Encoding: base64');
646
+ message.push('');
647
+ message.push(prepareBASE64(Buffer.from(msg.body.replace(REG_WINLINE, '\n').replace(REG_NEWLINE, CRLF)).toString('base64')));
648
+
649
+ // if (msg.type === 'html' && msg.$preview) {
650
+ // message.push('--' + obj.boundary);
651
+ // message.push('Content-Type: text/plain; charset="utf-8"; format="fixed"');
652
+ // message.push('Content-Transfer-Encoding: base64');
653
+ // message.push('');
654
+ // message.push(prepareBASE64(Buffer.from(msg.$preview.replace(REG_WINLINE, '\n').replace(REG_NEWLINE, CRLF)).toString('base64')));
655
+ // }
656
+
657
+ obj.message = message.join(CRLF);
658
+ obj.messagecallback = msg.$callback;
659
+ obj.messagecallback2 = msg.$callback2;
660
+ obj.instance = msg;
661
+
662
+ message = null;
663
+ return self;
664
+ };
665
+
666
+ Mailer.$writeline = function(obj) {
667
+
668
+ if (obj.closed)
669
+ return false;
670
+
671
+ var socket = obj.socket2 ? obj.socket2 : obj.socket;
672
+
673
+ for (var i = 1; i < arguments.length; i++) {
674
+ var line = arguments[i];
675
+ if (line) {
676
+ Mailer.debug && console.log('SEND', line);
677
+ socket.write(line + CRLF);
678
+ }
679
+ }
680
+
681
+ return true;
682
+ };
683
+
684
+ Mailer.$send = function(obj, options, autosend) {
685
+
686
+ var self = this;
687
+ var isAuthorized = false;
688
+ var isAuthorization = false;
689
+ var command = '';
690
+ var auth = [];
691
+ var socket = obj.socket2 ? obj.socket2 : obj.socket;
692
+ var host = obj.host;
693
+ var line = null;
694
+ var isAttach = !options.tls || (obj.tls && options.tls);
695
+
696
+ isAttach && Mailer.$events.send && Mailer.emit('send', obj);
697
+ socket.setEncoding('utf8');
698
+
699
+ socket.on('end', function() {
700
+ Mailer.destroy(obj);
701
+ obj.callback && obj.callback();
702
+ obj.callback = null;
703
+ if (obj.cached)
704
+ delete F.temporary.smtp[obj.server];
705
+ line = null;
706
+ });
707
+
708
+ socket.on('data', function(data) {
709
+
710
+ if (obj.closed)
711
+ return;
712
+
713
+ while (true) {
714
+
715
+ var index = data.indexOf(CRLF_BUFFER);
716
+ if (index === -1) {
717
+ if (line) {
718
+ CONCAT[0] = line;
719
+ CONCAT[1] = data;
720
+ line = Buffer.concat(CONCAT);
721
+ } else
722
+ line = data;
723
+ break;
724
+ }
725
+
726
+ var tmp = data.slice(0, index).toString('utf8');
727
+ data = data.slice(index + CRLF_BUFFER.length);
728
+ tmp && socket && socket.emit('line', tmp);
729
+ }
730
+ });
731
+
732
+ socket.on('line', function(line) {
733
+
734
+ line = line.toUpperCase();
735
+ Mailer.debug && console.log('<---', line);
736
+
737
+ var code = +line.match(REG_STATE)[0];
738
+ if (code === 250 && !isAuthorization) {
739
+ if (REG_AUTH.test(line) && (options.user && (options.password || options.token))) {
740
+ isAuthorization = true;
741
+ if (options.token && line.indexOf('XOAUTH2') !== -1) {
742
+ auth.push('AUTH XOAUTH2');
743
+ auth.push(Buffer.from('user=' + options.user + '\1auth=Bearer ' + options.token + '\1\1').toString('base64'));
744
+ } else if (line.lastIndexOf('XOAUTH') === -1) {
745
+ auth.push('AUTH LOGIN');
746
+ auth.push(Buffer.from(options.user).toString('base64'));
747
+ auth.push(Buffer.from(options.password).toString('base64'));
748
+ } else
749
+ auth.push('AUTH PLAIN ' + Buffer.from('\0'+ options.user + '\0' + options.password).toString('base64'));
750
+ }
751
+ }
752
+
753
+ // help
754
+ if (line.substring(3, 4) === '-')
755
+ return;
756
+
757
+ if (!isAuthorized && isAuthorization) {
758
+ isAuthorized = true;
759
+ code = 334;
760
+ }
761
+
762
+ switch (code) {
763
+ case 220:
764
+
765
+ if (obj.isTLS || REG_TLS.test(line)) {
766
+ Mailer.tls(obj, options);
767
+ } else {
768
+ obj.secured = REG_ESMTP.test(line);
769
+ command = options.heloid ? options.heloid : (obj.isTLS || (options.user && options.password) || obj.secured ? 'EHLO' : 'HELO');
770
+ Mailer.$writeline(obj, command + ' ' + host);
771
+ }
772
+
773
+ return;
774
+
775
+ case 250: // OPERATION
776
+ case 251: // FORWARD
777
+ case 235: // VERIFY
778
+ case 999: // Total.js again
779
+
780
+ if (obj.secured && !obj.isTLS && !obj.logged && obj.smtp.user && obj.smtp.password) {
781
+ // maybe TLS
782
+ obj.isTLS = true;
783
+ Mailer.$writeline(obj, 'STARTTLS');
784
+ return;
785
+ }
786
+
787
+ Mailer.$writeline(obj, obj.buffer.shift());
788
+
789
+ if (obj.buffer.length)
790
+ return;
791
+
792
+ // NEW MESSAGE
793
+ if (obj.messages.length) {
794
+ obj.buffer = [];
795
+ Mailer.$writemessage(obj, obj.buffer);
796
+ Mailer.$writeline(obj, obj.buffer.shift());
797
+ } else {
798
+
799
+ obj.sending = false;
800
+
801
+ // end
802
+ if (obj.cached)
803
+ obj.trytosend();
804
+ else
805
+ Mailer.$writeline(obj, 'QUIT');
806
+ }
807
+
808
+ return;
809
+
810
+ case 221: // BYE
811
+
812
+ if (!obj.cached)
813
+ Mailer.destroy(obj);
814
+
815
+ obj.callback && obj.callback(null, obj.try ? true : obj.count);
816
+ obj.callback = null;
817
+
818
+ return;
819
+
820
+ case 334: // LOGIN
821
+
822
+ if (!self.tls && !obj.isTLS && options.tls) {
823
+ obj.isTLS = true;
824
+ Mailer.$writeline(obj, 'STARTTLS');
825
+ return;
826
+ }
827
+
828
+ var value = auth.shift();
829
+ if (value) {
830
+ obj.logged = true;
831
+ Mailer.$writeline(obj, value);
832
+ } else {
833
+ var err = new Error('Forbidden.');
834
+ Mailer.destroy(obj);
835
+ obj.callback && obj.callback(err);
836
+ obj.callback = null;
837
+ Mailer.$events.error && !obj.try && Mailer.emit('error', err, obj);
838
+ }
839
+
840
+ return;
841
+
842
+ case 354:
843
+ Mailer.$writeline(obj, obj.message);
844
+ Mailer.$writeattachment(obj);
845
+ obj.message = null;
846
+ return;
847
+
848
+ default:
849
+
850
+ if (code < 400)
851
+ return;
852
+
853
+ if (!obj.isTLS && code === 530 && REG_STARTTLS.test(line)) {
854
+ obj.isTLS = true;
855
+ Mailer.$writeline(obj, 'STARTTLS');
856
+ return;
857
+ }
858
+
859
+ var err = line;
860
+
861
+ Mailer.$events.error && !obj.try && Mailer.emit('error', err, obj);
862
+
863
+ if (obj.messagecallback) {
864
+ obj.messagecallback(err, obj.instance);
865
+ obj.messagecallback = null;
866
+ }
867
+
868
+ if (obj.messagecallback2) {
869
+ obj.messagecallback2(err, obj.instance);
870
+ obj.messagecallback2 = null;
871
+ }
872
+
873
+ if (obj.messages.length) {
874
+
875
+ F.error(err, 'SMTP error');
876
+
877
+ // a problem
878
+ obj.buffer = [];
879
+ obj.count--;
880
+ socket.emit('line', '999 TRY NEXT MESSAGE');
881
+
882
+ } else {
883
+ Mailer.destroy(obj);
884
+ obj.callback && obj.callback(err);
885
+ obj.callback = null;
886
+ }
887
+
888
+ return;
889
+ }
890
+ });
891
+
892
+ autosend && self.$writeline(obj, 'EHLO ' + host);
893
+ };
894
+
895
+ Mailer.restart = function() {
896
+ var self = this;
897
+ self.off();
898
+ self.debug = false;
899
+ INDEXATTACHMENT = 0;
900
+ };
901
+
902
+ // Split Base64 to lines with 68 characters
903
+ function prepareBASE64(value) {
904
+
905
+ var index = 0;
906
+ var output = '';
907
+ var length = value.length;
908
+
909
+ while (index < length) {
910
+ var max = index + 68;
911
+ if (max > length)
912
+ max = length;
913
+ output += value.substring(index, max) + CRLF;
914
+ index = max;
915
+ }
916
+
917
+ return output;
918
+ }
919
+
920
+ function unicode_encode(val) {
921
+ return val ? '=?utf-8?B?' + Buffer.from(val.toString()).toString('base64') + '?=' : '';
922
+ }
923
+
924
+ // ======================================================
925
+ // EXPORTS
926
+ // ======================================================
927
+
928
+ exports.Mailer = Mailer;
929
+ exports.Message = Message;
930
+ exports.refresh = function() {
931
+ for (let key in F.temporary.smtp) {
932
+ let conn = F.temporary.smtp[key];
933
+ if (conn.TS < NOW && (!conn.messages || !conn.messages.length))
934
+ Mailer.destroy(F.temporary.smtp[key]);
935
+ }
936
+ };