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