@nocobase/plugin-notification-email 1.4.0-alpha.20240928155737

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 (65) hide show
  1. package/LICENSE.txt +123 -0
  2. package/README.md +1 -0
  3. package/client.d.ts +2 -0
  4. package/client.js +1 -0
  5. package/dist/client/ConfigForm.d.ts +10 -0
  6. package/dist/client/MessageConfigForm.d.ts +12 -0
  7. package/dist/client/hooks/useTranslation.d.ts +9 -0
  8. package/dist/client/index.d.ts +15 -0
  9. package/dist/client/index.js +16 -0
  10. package/dist/constant.d.ts +10 -0
  11. package/dist/constant.js +39 -0
  12. package/dist/externalVersion.js +17 -0
  13. package/dist/index.d.ts +10 -0
  14. package/dist/index.js +48 -0
  15. package/dist/locale/en-US.json +22 -0
  16. package/dist/locale/zh-CN.json +22 -0
  17. package/dist/node_modules/nodemailer/.gitattributes +6 -0
  18. package/dist/node_modules/nodemailer/.ncurc.js +7 -0
  19. package/dist/node_modules/nodemailer/.prettierrc.js +8 -0
  20. package/dist/node_modules/nodemailer/LICENSE +16 -0
  21. package/dist/node_modules/nodemailer/SECURITY.txt +22 -0
  22. package/dist/node_modules/nodemailer/lib/addressparser/index.js +313 -0
  23. package/dist/node_modules/nodemailer/lib/base64/index.js +142 -0
  24. package/dist/node_modules/nodemailer/lib/dkim/index.js +251 -0
  25. package/dist/node_modules/nodemailer/lib/dkim/message-parser.js +155 -0
  26. package/dist/node_modules/nodemailer/lib/dkim/relaxed-body.js +154 -0
  27. package/dist/node_modules/nodemailer/lib/dkim/sign.js +117 -0
  28. package/dist/node_modules/nodemailer/lib/fetch/cookies.js +281 -0
  29. package/dist/node_modules/nodemailer/lib/fetch/index.js +274 -0
  30. package/dist/node_modules/nodemailer/lib/json-transport/index.js +82 -0
  31. package/dist/node_modules/nodemailer/lib/mail-composer/index.js +565 -0
  32. package/dist/node_modules/nodemailer/lib/mailer/index.js +427 -0
  33. package/dist/node_modules/nodemailer/lib/mailer/mail-message.js +315 -0
  34. package/dist/node_modules/nodemailer/lib/mime-funcs/index.js +625 -0
  35. package/dist/node_modules/nodemailer/lib/mime-funcs/mime-types.js +2102 -0
  36. package/dist/node_modules/nodemailer/lib/mime-node/index.js +1305 -0
  37. package/dist/node_modules/nodemailer/lib/mime-node/last-newline.js +33 -0
  38. package/dist/node_modules/nodemailer/lib/mime-node/le-unix.js +43 -0
  39. package/dist/node_modules/nodemailer/lib/mime-node/le-windows.js +52 -0
  40. package/dist/node_modules/nodemailer/lib/nodemailer.js +1 -0
  41. package/dist/node_modules/nodemailer/lib/qp/index.js +219 -0
  42. package/dist/node_modules/nodemailer/lib/sendmail-transport/index.js +210 -0
  43. package/dist/node_modules/nodemailer/lib/ses-transport/index.js +349 -0
  44. package/dist/node_modules/nodemailer/lib/shared/index.js +638 -0
  45. package/dist/node_modules/nodemailer/lib/smtp-connection/data-stream.js +108 -0
  46. package/dist/node_modules/nodemailer/lib/smtp-connection/http-proxy-client.js +143 -0
  47. package/dist/node_modules/nodemailer/lib/smtp-connection/index.js +1812 -0
  48. package/dist/node_modules/nodemailer/lib/smtp-pool/index.js +648 -0
  49. package/dist/node_modules/nodemailer/lib/smtp-pool/pool-resource.js +253 -0
  50. package/dist/node_modules/nodemailer/lib/smtp-transport/index.js +416 -0
  51. package/dist/node_modules/nodemailer/lib/stream-transport/index.js +135 -0
  52. package/dist/node_modules/nodemailer/lib/well-known/index.js +47 -0
  53. package/dist/node_modules/nodemailer/lib/well-known/services.json +338 -0
  54. package/dist/node_modules/nodemailer/lib/xoauth2/index.js +376 -0
  55. package/dist/node_modules/nodemailer/package.json +1 -0
  56. package/dist/server/index.d.ts +9 -0
  57. package/dist/server/index.js +42 -0
  58. package/dist/server/mail-server.d.ts +14 -0
  59. package/dist/server/mail-server.js +78 -0
  60. package/dist/server/plugin.d.ts +19 -0
  61. package/dist/server/plugin.js +69 -0
  62. package/package.json +23 -0
  63. package/server.d.ts +2 -0
  64. package/server.js +1 -0
  65. package/tsconfig.json +7 -0
@@ -0,0 +1,565 @@
1
+ /* eslint no-undefined: 0 */
2
+
3
+ 'use strict';
4
+
5
+ const MimeNode = require('../mime-node');
6
+ const mimeFuncs = require('../mime-funcs');
7
+
8
+ /**
9
+ * Creates the object for composing a MimeNode instance out from the mail options
10
+ *
11
+ * @constructor
12
+ * @param {Object} mail Mail options
13
+ */
14
+ class MailComposer {
15
+ constructor(mail) {
16
+ this.mail = mail || {};
17
+ this.message = false;
18
+ }
19
+
20
+ /**
21
+ * Builds MimeNode instance
22
+ */
23
+ compile() {
24
+ this._alternatives = this.getAlternatives();
25
+ this._htmlNode = this._alternatives.filter(alternative => /^text\/html\b/i.test(alternative.contentType)).pop();
26
+ this._attachments = this.getAttachments(!!this._htmlNode);
27
+
28
+ this._useRelated = !!(this._htmlNode && this._attachments.related.length);
29
+ this._useAlternative = this._alternatives.length > 1;
30
+ this._useMixed = this._attachments.attached.length > 1 || (this._alternatives.length && this._attachments.attached.length === 1);
31
+
32
+ // Compose MIME tree
33
+ if (this.mail.raw) {
34
+ this.message = new MimeNode('message/rfc822', { newline: this.mail.newline }).setRaw(this.mail.raw);
35
+ } else if (this._useMixed) {
36
+ this.message = this._createMixed();
37
+ } else if (this._useAlternative) {
38
+ this.message = this._createAlternative();
39
+ } else if (this._useRelated) {
40
+ this.message = this._createRelated();
41
+ } else {
42
+ this.message = this._createContentNode(
43
+ false,
44
+ []
45
+ .concat(this._alternatives || [])
46
+ .concat(this._attachments.attached || [])
47
+ .shift() || {
48
+ contentType: 'text/plain',
49
+ content: ''
50
+ }
51
+ );
52
+ }
53
+
54
+ // Add custom headers
55
+ if (this.mail.headers) {
56
+ this.message.addHeader(this.mail.headers);
57
+ }
58
+
59
+ // Add headers to the root node, always overrides custom headers
60
+ ['from', 'sender', 'to', 'cc', 'bcc', 'reply-to', 'in-reply-to', 'references', 'subject', 'message-id', 'date'].forEach(header => {
61
+ let key = header.replace(/-(\w)/g, (o, c) => c.toUpperCase());
62
+ if (this.mail[key]) {
63
+ this.message.setHeader(header, this.mail[key]);
64
+ }
65
+ });
66
+
67
+ // Sets custom envelope
68
+ if (this.mail.envelope) {
69
+ this.message.setEnvelope(this.mail.envelope);
70
+ }
71
+
72
+ // ensure Message-Id value
73
+ this.message.messageId();
74
+
75
+ return this.message;
76
+ }
77
+
78
+ /**
79
+ * List all attachments. Resulting attachment objects can be used as input for MimeNode nodes
80
+ *
81
+ * @param {Boolean} findRelated If true separate related attachments from attached ones
82
+ * @returns {Object} An object of arrays (`related` and `attached`)
83
+ */
84
+ getAttachments(findRelated) {
85
+ let icalEvent, eventObject;
86
+ let attachments = [].concat(this.mail.attachments || []).map((attachment, i) => {
87
+ let data;
88
+ let isMessageNode = /^message\//i.test(attachment.contentType);
89
+
90
+ if (/^data:/i.test(attachment.path || attachment.href)) {
91
+ attachment = this._processDataUrl(attachment);
92
+ }
93
+
94
+ let contentType = attachment.contentType || mimeFuncs.detectMimeType(attachment.filename || attachment.path || attachment.href || 'bin');
95
+ let isImage = /^image\//i.test(contentType);
96
+ let contentDisposition = attachment.contentDisposition || (isMessageNode || (isImage && attachment.cid) ? 'inline' : 'attachment');
97
+
98
+ data = {
99
+ contentType,
100
+ contentDisposition,
101
+ contentTransferEncoding: 'contentTransferEncoding' in attachment ? attachment.contentTransferEncoding : 'base64'
102
+ };
103
+
104
+ if (attachment.filename) {
105
+ data.filename = attachment.filename;
106
+ } else if (!isMessageNode && attachment.filename !== false) {
107
+ data.filename = (attachment.path || attachment.href || '').split('/').pop().split('?').shift() || 'attachment-' + (i + 1);
108
+ if (data.filename.indexOf('.') < 0) {
109
+ data.filename += '.' + mimeFuncs.detectExtension(data.contentType);
110
+ }
111
+ }
112
+
113
+ if (/^https?:\/\//i.test(attachment.path)) {
114
+ attachment.href = attachment.path;
115
+ attachment.path = undefined;
116
+ }
117
+
118
+ if (attachment.cid) {
119
+ data.cid = attachment.cid;
120
+ }
121
+
122
+ if (attachment.raw) {
123
+ data.raw = attachment.raw;
124
+ } else if (attachment.path) {
125
+ data.content = {
126
+ path: attachment.path
127
+ };
128
+ } else if (attachment.href) {
129
+ data.content = {
130
+ href: attachment.href,
131
+ httpHeaders: attachment.httpHeaders
132
+ };
133
+ } else {
134
+ data.content = attachment.content || '';
135
+ }
136
+
137
+ if (attachment.encoding) {
138
+ data.encoding = attachment.encoding;
139
+ }
140
+
141
+ if (attachment.headers) {
142
+ data.headers = attachment.headers;
143
+ }
144
+
145
+ return data;
146
+ });
147
+
148
+ if (this.mail.icalEvent) {
149
+ if (
150
+ typeof this.mail.icalEvent === 'object' &&
151
+ (this.mail.icalEvent.content || this.mail.icalEvent.path || this.mail.icalEvent.href || this.mail.icalEvent.raw)
152
+ ) {
153
+ icalEvent = this.mail.icalEvent;
154
+ } else {
155
+ icalEvent = {
156
+ content: this.mail.icalEvent
157
+ };
158
+ }
159
+
160
+ eventObject = {};
161
+ Object.keys(icalEvent).forEach(key => {
162
+ eventObject[key] = icalEvent[key];
163
+ });
164
+
165
+ eventObject.contentType = 'application/ics';
166
+ if (!eventObject.headers) {
167
+ eventObject.headers = {};
168
+ }
169
+ eventObject.filename = eventObject.filename || 'invite.ics';
170
+ eventObject.headers['Content-Disposition'] = 'attachment';
171
+ eventObject.headers['Content-Transfer-Encoding'] = 'base64';
172
+ }
173
+
174
+ if (!findRelated) {
175
+ return {
176
+ attached: attachments.concat(eventObject || []),
177
+ related: []
178
+ };
179
+ } else {
180
+ return {
181
+ attached: attachments.filter(attachment => !attachment.cid).concat(eventObject || []),
182
+ related: attachments.filter(attachment => !!attachment.cid)
183
+ };
184
+ }
185
+ }
186
+
187
+ /**
188
+ * List alternatives. Resulting objects can be used as input for MimeNode nodes
189
+ *
190
+ * @returns {Array} An array of alternative elements. Includes the `text` and `html` values as well
191
+ */
192
+ getAlternatives() {
193
+ let alternatives = [],
194
+ text,
195
+ html,
196
+ watchHtml,
197
+ amp,
198
+ icalEvent,
199
+ eventObject;
200
+
201
+ if (this.mail.text) {
202
+ if (typeof this.mail.text === 'object' && (this.mail.text.content || this.mail.text.path || this.mail.text.href || this.mail.text.raw)) {
203
+ text = this.mail.text;
204
+ } else {
205
+ text = {
206
+ content: this.mail.text
207
+ };
208
+ }
209
+ text.contentType = 'text/plain; charset=utf-8';
210
+ }
211
+
212
+ if (this.mail.watchHtml) {
213
+ if (
214
+ typeof this.mail.watchHtml === 'object' &&
215
+ (this.mail.watchHtml.content || this.mail.watchHtml.path || this.mail.watchHtml.href || this.mail.watchHtml.raw)
216
+ ) {
217
+ watchHtml = this.mail.watchHtml;
218
+ } else {
219
+ watchHtml = {
220
+ content: this.mail.watchHtml
221
+ };
222
+ }
223
+ watchHtml.contentType = 'text/watch-html; charset=utf-8';
224
+ }
225
+
226
+ if (this.mail.amp) {
227
+ if (typeof this.mail.amp === 'object' && (this.mail.amp.content || this.mail.amp.path || this.mail.amp.href || this.mail.amp.raw)) {
228
+ amp = this.mail.amp;
229
+ } else {
230
+ amp = {
231
+ content: this.mail.amp
232
+ };
233
+ }
234
+ amp.contentType = 'text/x-amp-html; charset=utf-8';
235
+ }
236
+
237
+ // NB! when including attachments with a calendar alternative you might end up in a blank screen on some clients
238
+ if (this.mail.icalEvent) {
239
+ if (
240
+ typeof this.mail.icalEvent === 'object' &&
241
+ (this.mail.icalEvent.content || this.mail.icalEvent.path || this.mail.icalEvent.href || this.mail.icalEvent.raw)
242
+ ) {
243
+ icalEvent = this.mail.icalEvent;
244
+ } else {
245
+ icalEvent = {
246
+ content: this.mail.icalEvent
247
+ };
248
+ }
249
+
250
+ eventObject = {};
251
+ Object.keys(icalEvent).forEach(key => {
252
+ eventObject[key] = icalEvent[key];
253
+ });
254
+
255
+ if (eventObject.content && typeof eventObject.content === 'object') {
256
+ // we are going to have the same attachment twice, so mark this to be
257
+ // resolved just once
258
+ eventObject.content._resolve = true;
259
+ }
260
+
261
+ eventObject.filename = false;
262
+ eventObject.contentType = 'text/calendar; charset=utf-8; method=' + (eventObject.method || 'PUBLISH').toString().trim().toUpperCase();
263
+ if (!eventObject.headers) {
264
+ eventObject.headers = {};
265
+ }
266
+ }
267
+
268
+ if (this.mail.html) {
269
+ if (typeof this.mail.html === 'object' && (this.mail.html.content || this.mail.html.path || this.mail.html.href || this.mail.html.raw)) {
270
+ html = this.mail.html;
271
+ } else {
272
+ html = {
273
+ content: this.mail.html
274
+ };
275
+ }
276
+ html.contentType = 'text/html; charset=utf-8';
277
+ }
278
+
279
+ []
280
+ .concat(text || [])
281
+ .concat(watchHtml || [])
282
+ .concat(amp || [])
283
+ .concat(html || [])
284
+ .concat(eventObject || [])
285
+ .concat(this.mail.alternatives || [])
286
+ .forEach(alternative => {
287
+ let data;
288
+
289
+ if (/^data:/i.test(alternative.path || alternative.href)) {
290
+ alternative = this._processDataUrl(alternative);
291
+ }
292
+
293
+ data = {
294
+ contentType: alternative.contentType || mimeFuncs.detectMimeType(alternative.filename || alternative.path || alternative.href || 'txt'),
295
+ contentTransferEncoding: alternative.contentTransferEncoding
296
+ };
297
+
298
+ if (alternative.filename) {
299
+ data.filename = alternative.filename;
300
+ }
301
+
302
+ if (/^https?:\/\//i.test(alternative.path)) {
303
+ alternative.href = alternative.path;
304
+ alternative.path = undefined;
305
+ }
306
+
307
+ if (alternative.raw) {
308
+ data.raw = alternative.raw;
309
+ } else if (alternative.path) {
310
+ data.content = {
311
+ path: alternative.path
312
+ };
313
+ } else if (alternative.href) {
314
+ data.content = {
315
+ href: alternative.href
316
+ };
317
+ } else {
318
+ data.content = alternative.content || '';
319
+ }
320
+
321
+ if (alternative.encoding) {
322
+ data.encoding = alternative.encoding;
323
+ }
324
+
325
+ if (alternative.headers) {
326
+ data.headers = alternative.headers;
327
+ }
328
+
329
+ alternatives.push(data);
330
+ });
331
+
332
+ return alternatives;
333
+ }
334
+
335
+ /**
336
+ * Builds multipart/mixed node. It should always contain different type of elements on the same level
337
+ * eg. text + attachments
338
+ *
339
+ * @param {Object} parentNode Parent for this note. If it does not exist, a root node is created
340
+ * @returns {Object} MimeNode node element
341
+ */
342
+ _createMixed(parentNode) {
343
+ let node;
344
+
345
+ if (!parentNode) {
346
+ node = new MimeNode('multipart/mixed', {
347
+ baseBoundary: this.mail.baseBoundary,
348
+ textEncoding: this.mail.textEncoding,
349
+ boundaryPrefix: this.mail.boundaryPrefix,
350
+ disableUrlAccess: this.mail.disableUrlAccess,
351
+ disableFileAccess: this.mail.disableFileAccess,
352
+ normalizeHeaderKey: this.mail.normalizeHeaderKey,
353
+ newline: this.mail.newline
354
+ });
355
+ } else {
356
+ node = parentNode.createChild('multipart/mixed', {
357
+ disableUrlAccess: this.mail.disableUrlAccess,
358
+ disableFileAccess: this.mail.disableFileAccess,
359
+ normalizeHeaderKey: this.mail.normalizeHeaderKey,
360
+ newline: this.mail.newline
361
+ });
362
+ }
363
+
364
+ if (this._useAlternative) {
365
+ this._createAlternative(node);
366
+ } else if (this._useRelated) {
367
+ this._createRelated(node);
368
+ }
369
+
370
+ []
371
+ .concat((!this._useAlternative && this._alternatives) || [])
372
+ .concat(this._attachments.attached || [])
373
+ .forEach(element => {
374
+ // if the element is a html node from related subpart then ignore it
375
+ if (!this._useRelated || element !== this._htmlNode) {
376
+ this._createContentNode(node, element);
377
+ }
378
+ });
379
+
380
+ return node;
381
+ }
382
+
383
+ /**
384
+ * Builds multipart/alternative node. It should always contain same type of elements on the same level
385
+ * eg. text + html view of the same data
386
+ *
387
+ * @param {Object} parentNode Parent for this note. If it does not exist, a root node is created
388
+ * @returns {Object} MimeNode node element
389
+ */
390
+ _createAlternative(parentNode) {
391
+ let node;
392
+
393
+ if (!parentNode) {
394
+ node = new MimeNode('multipart/alternative', {
395
+ baseBoundary: this.mail.baseBoundary,
396
+ textEncoding: this.mail.textEncoding,
397
+ boundaryPrefix: this.mail.boundaryPrefix,
398
+ disableUrlAccess: this.mail.disableUrlAccess,
399
+ disableFileAccess: this.mail.disableFileAccess,
400
+ normalizeHeaderKey: this.mail.normalizeHeaderKey,
401
+ newline: this.mail.newline
402
+ });
403
+ } else {
404
+ node = parentNode.createChild('multipart/alternative', {
405
+ disableUrlAccess: this.mail.disableUrlAccess,
406
+ disableFileAccess: this.mail.disableFileAccess,
407
+ normalizeHeaderKey: this.mail.normalizeHeaderKey,
408
+ newline: this.mail.newline
409
+ });
410
+ }
411
+
412
+ this._alternatives.forEach(alternative => {
413
+ if (this._useRelated && this._htmlNode === alternative) {
414
+ this._createRelated(node);
415
+ } else {
416
+ this._createContentNode(node, alternative);
417
+ }
418
+ });
419
+
420
+ return node;
421
+ }
422
+
423
+ /**
424
+ * Builds multipart/related node. It should always contain html node with related attachments
425
+ *
426
+ * @param {Object} parentNode Parent for this note. If it does not exist, a root node is created
427
+ * @returns {Object} MimeNode node element
428
+ */
429
+ _createRelated(parentNode) {
430
+ let node;
431
+
432
+ if (!parentNode) {
433
+ node = new MimeNode('multipart/related; type="text/html"', {
434
+ baseBoundary: this.mail.baseBoundary,
435
+ textEncoding: this.mail.textEncoding,
436
+ boundaryPrefix: this.mail.boundaryPrefix,
437
+ disableUrlAccess: this.mail.disableUrlAccess,
438
+ disableFileAccess: this.mail.disableFileAccess,
439
+ normalizeHeaderKey: this.mail.normalizeHeaderKey,
440
+ newline: this.mail.newline
441
+ });
442
+ } else {
443
+ node = parentNode.createChild('multipart/related; type="text/html"', {
444
+ disableUrlAccess: this.mail.disableUrlAccess,
445
+ disableFileAccess: this.mail.disableFileAccess,
446
+ normalizeHeaderKey: this.mail.normalizeHeaderKey,
447
+ newline: this.mail.newline
448
+ });
449
+ }
450
+
451
+ this._createContentNode(node, this._htmlNode);
452
+
453
+ this._attachments.related.forEach(alternative => this._createContentNode(node, alternative));
454
+
455
+ return node;
456
+ }
457
+
458
+ /**
459
+ * Creates a regular node with contents
460
+ *
461
+ * @param {Object} parentNode Parent for this note. If it does not exist, a root node is created
462
+ * @param {Object} element Node data
463
+ * @returns {Object} MimeNode node element
464
+ */
465
+ _createContentNode(parentNode, element) {
466
+ element = element || {};
467
+ element.content = element.content || '';
468
+
469
+ let node;
470
+ let encoding = (element.encoding || 'utf8')
471
+ .toString()
472
+ .toLowerCase()
473
+ .replace(/[-_\s]/g, '');
474
+
475
+ if (!parentNode) {
476
+ node = new MimeNode(element.contentType, {
477
+ filename: element.filename,
478
+ baseBoundary: this.mail.baseBoundary,
479
+ textEncoding: this.mail.textEncoding,
480
+ boundaryPrefix: this.mail.boundaryPrefix,
481
+ disableUrlAccess: this.mail.disableUrlAccess,
482
+ disableFileAccess: this.mail.disableFileAccess,
483
+ normalizeHeaderKey: this.mail.normalizeHeaderKey,
484
+ newline: this.mail.newline
485
+ });
486
+ } else {
487
+ node = parentNode.createChild(element.contentType, {
488
+ filename: element.filename,
489
+ textEncoding: this.mail.textEncoding,
490
+ disableUrlAccess: this.mail.disableUrlAccess,
491
+ disableFileAccess: this.mail.disableFileAccess,
492
+ normalizeHeaderKey: this.mail.normalizeHeaderKey,
493
+ newline: this.mail.newline
494
+ });
495
+ }
496
+
497
+ // add custom headers
498
+ if (element.headers) {
499
+ node.addHeader(element.headers);
500
+ }
501
+
502
+ if (element.cid) {
503
+ node.setHeader('Content-Id', '<' + element.cid.replace(/[<>]/g, '') + '>');
504
+ }
505
+
506
+ if (element.contentTransferEncoding) {
507
+ node.setHeader('Content-Transfer-Encoding', element.contentTransferEncoding);
508
+ } else if (this.mail.encoding && /^text\//i.test(element.contentType)) {
509
+ node.setHeader('Content-Transfer-Encoding', this.mail.encoding);
510
+ }
511
+
512
+ if (!/^text\//i.test(element.contentType) || element.contentDisposition) {
513
+ node.setHeader(
514
+ 'Content-Disposition',
515
+ element.contentDisposition || (element.cid && /^image\//i.test(element.contentType) ? 'inline' : 'attachment')
516
+ );
517
+ }
518
+
519
+ if (typeof element.content === 'string' && !['utf8', 'usascii', 'ascii'].includes(encoding)) {
520
+ element.content = Buffer.from(element.content, encoding);
521
+ }
522
+
523
+ // prefer pregenerated raw content
524
+ if (element.raw) {
525
+ node.setRaw(element.raw);
526
+ } else {
527
+ node.setContent(element.content);
528
+ }
529
+
530
+ return node;
531
+ }
532
+
533
+ /**
534
+ * Parses data uri and converts it to a Buffer
535
+ *
536
+ * @param {Object} element Content element
537
+ * @return {Object} Parsed element
538
+ */
539
+ _processDataUrl(element) {
540
+ let parts = (element.path || element.href).match(/^data:((?:[^;]*;)*(?:[^,]*)),(.*)$/i);
541
+ if (!parts) {
542
+ return element;
543
+ }
544
+
545
+ element.content = /\bbase64$/i.test(parts[1]) ? Buffer.from(parts[2], 'base64') : Buffer.from(decodeURIComponent(parts[2]));
546
+
547
+ if ('path' in element) {
548
+ element.path = false;
549
+ }
550
+
551
+ if ('href' in element) {
552
+ element.href = false;
553
+ }
554
+
555
+ parts[1].split(';').forEach(item => {
556
+ if (/^\w+\/[^/]+$/i.test(item)) {
557
+ element.contentType = element.contentType || item.toLowerCase();
558
+ }
559
+ });
560
+
561
+ return element;
562
+ }
563
+ }
564
+
565
+ module.exports = MailComposer;