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