@nocobase/plugin-workflow-mailer 2.3.0-beta.9 → 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.
Files changed (187) hide show
  1. package/dist/externalVersion.js +6 -6
  2. package/dist/node_modules/joi/dist/joi-browser.min.js +1 -1
  3. package/dist/node_modules/joi/lib/index.js +1 -1
  4. package/dist/node_modules/joi/lib/messages.js +35 -6
  5. package/dist/node_modules/joi/lib/types/keys.js +18 -1
  6. package/dist/node_modules/joi/lib/types/link.js +18 -2
  7. package/dist/node_modules/joi/lib/types/string.js +2 -2
  8. package/dist/node_modules/joi/package.json +1 -1
  9. package/dist/node_modules/nodemailer/dist/cjs/addressparser/index.d.ts +59 -0
  10. package/dist/node_modules/nodemailer/dist/cjs/addressparser/index.js +790 -0
  11. package/dist/node_modules/nodemailer/dist/cjs/base64/index.d.ts +36 -0
  12. package/dist/node_modules/nodemailer/dist/cjs/base64/index.js +119 -0
  13. package/dist/node_modules/nodemailer/dist/cjs/dkim/index.d.ts +52 -0
  14. package/dist/node_modules/nodemailer/dist/cjs/dkim/index.js +228 -0
  15. package/dist/node_modules/nodemailer/dist/cjs/dkim/message-parser.d.ts +48 -0
  16. package/dist/node_modules/nodemailer/dist/cjs/dkim/message-parser.js +180 -0
  17. package/dist/node_modules/nodemailer/dist/cjs/dkim/relaxed-body.d.ts +36 -0
  18. package/dist/node_modules/nodemailer/dist/cjs/dkim/relaxed-body.js +148 -0
  19. package/dist/node_modules/nodemailer/dist/cjs/dkim/sign.d.ts +52 -0
  20. package/dist/node_modules/nodemailer/dist/cjs/dkim/sign.js +165 -0
  21. package/dist/node_modules/nodemailer/dist/cjs/errors.d.ts +96 -0
  22. package/dist/node_modules/nodemailer/dist/cjs/errors.js +70 -0
  23. package/dist/node_modules/nodemailer/dist/cjs/fetch/cookies.d.ts +107 -0
  24. package/dist/node_modules/nodemailer/dist/cjs/fetch/cookies.js +282 -0
  25. package/dist/node_modules/nodemailer/dist/cjs/fetch/index.d.ts +65 -0
  26. package/dist/node_modules/nodemailer/dist/cjs/fetch/index.js +384 -0
  27. package/dist/node_modules/nodemailer/dist/cjs/json-transport/index.d.ts +64 -0
  28. package/dist/node_modules/nodemailer/dist/cjs/json-transport/index.js +99 -0
  29. package/dist/node_modules/nodemailer/dist/cjs/mail-composer/index.d.ts +174 -0
  30. package/dist/node_modules/nodemailer/dist/cjs/mail-composer/index.js +613 -0
  31. package/dist/node_modules/nodemailer/dist/cjs/mailer/index.d.ts +237 -0
  32. package/dist/node_modules/nodemailer/dist/cjs/mailer/index.js +415 -0
  33. package/dist/node_modules/nodemailer/dist/cjs/mailer/mail-message.d.ts +97 -0
  34. package/dist/node_modules/nodemailer/dist/cjs/mailer/mail-message.js +342 -0
  35. package/dist/node_modules/nodemailer/dist/cjs/mime-funcs/index.d.ts +161 -0
  36. package/dist/node_modules/nodemailer/dist/cjs/mime-funcs/index.js +787 -0
  37. package/dist/node_modules/nodemailer/dist/cjs/mime-funcs/mime-types.d.ts +2 -0
  38. package/dist/node_modules/nodemailer/dist/cjs/mime-funcs/mime-types.js +2103 -0
  39. package/dist/node_modules/nodemailer/dist/cjs/mime-node/index.d.ts +333 -0
  40. package/dist/node_modules/nodemailer/dist/cjs/mime-node/index.js +1493 -0
  41. package/dist/node_modules/nodemailer/dist/cjs/mime-node/last-newline.d.ts +5 -0
  42. package/dist/node_modules/nodemailer/dist/cjs/mime-node/last-newline.js +32 -0
  43. package/dist/node_modules/nodemailer/dist/cjs/mime-node/le-unix.d.ts +9 -0
  44. package/dist/node_modules/nodemailer/dist/cjs/mime-node/le-unix.js +40 -0
  45. package/dist/node_modules/nodemailer/dist/cjs/mime-node/le-windows.d.ts +10 -0
  46. package/dist/node_modules/nodemailer/dist/cjs/mime-node/le-windows.js +47 -0
  47. package/dist/node_modules/nodemailer/dist/cjs/nodemailer.d.ts +124 -0
  48. package/dist/node_modules/nodemailer/dist/cjs/nodemailer.js +1 -0
  49. package/dist/node_modules/nodemailer/dist/cjs/package-info.d.ts +3 -0
  50. package/dist/node_modules/nodemailer/dist/cjs/package-info.js +7 -0
  51. package/dist/node_modules/nodemailer/dist/cjs/package.json +3 -0
  52. package/dist/node_modules/nodemailer/dist/cjs/punycode/index.d.ts +73 -0
  53. package/dist/node_modules/nodemailer/{lib → dist/cjs}/punycode/index.js +63 -112
  54. package/dist/node_modules/nodemailer/dist/cjs/qp/index.d.ts +32 -0
  55. package/dist/node_modules/nodemailer/dist/cjs/qp/index.js +207 -0
  56. package/dist/node_modules/nodemailer/dist/cjs/sendmail-transport/index.d.ts +69 -0
  57. package/dist/node_modules/nodemailer/dist/cjs/sendmail-transport/index.js +210 -0
  58. package/dist/node_modules/nodemailer/dist/cjs/ses-transport/index.d.ts +112 -0
  59. package/dist/node_modules/nodemailer/dist/cjs/ses-transport/index.js +252 -0
  60. package/dist/node_modules/nodemailer/dist/cjs/shared/index.d.ts +260 -0
  61. package/dist/node_modules/nodemailer/dist/cjs/shared/index.js +680 -0
  62. package/dist/node_modules/nodemailer/dist/cjs/shared/objects.d.ts +23 -0
  63. package/dist/node_modules/nodemailer/dist/cjs/shared/objects.js +43 -0
  64. package/dist/node_modules/nodemailer/dist/cjs/shared/url.d.ts +21 -0
  65. package/dist/node_modules/nodemailer/dist/cjs/shared/url.js +255 -0
  66. package/dist/node_modules/nodemailer/dist/cjs/smtp-connection/data-stream.d.ts +15 -0
  67. package/dist/node_modules/nodemailer/dist/cjs/smtp-connection/data-stream.js +108 -0
  68. package/dist/node_modules/nodemailer/dist/cjs/smtp-connection/http-proxy-client.d.ts +47 -0
  69. package/dist/node_modules/nodemailer/dist/cjs/smtp-connection/http-proxy-client.js +189 -0
  70. package/dist/node_modules/nodemailer/dist/cjs/smtp-connection/index.d.ts +416 -0
  71. package/dist/node_modules/nodemailer/dist/cjs/smtp-connection/index.js +1837 -0
  72. package/dist/node_modules/nodemailer/dist/cjs/smtp-pool/index.d.ts +133 -0
  73. package/dist/node_modules/nodemailer/dist/cjs/smtp-pool/index.js +569 -0
  74. package/dist/node_modules/nodemailer/dist/cjs/smtp-pool/pool-resource.d.ts +62 -0
  75. package/dist/node_modules/nodemailer/dist/cjs/smtp-pool/pool-resource.js +257 -0
  76. package/dist/node_modules/nodemailer/dist/cjs/smtp-transport/index.d.ts +156 -0
  77. package/dist/node_modules/nodemailer/dist/cjs/smtp-transport/index.js +371 -0
  78. package/dist/node_modules/nodemailer/dist/cjs/stream-transport/index.d.ts +65 -0
  79. package/dist/node_modules/nodemailer/dist/cjs/stream-transport/index.js +146 -0
  80. package/dist/node_modules/nodemailer/dist/cjs/well-known/index.d.ts +35 -0
  81. package/dist/node_modules/nodemailer/dist/cjs/well-known/index.js +41 -0
  82. package/dist/node_modules/nodemailer/dist/cjs/well-known/services.d.ts +2 -0
  83. package/dist/node_modules/nodemailer/dist/cjs/well-known/services.js +674 -0
  84. package/dist/node_modules/nodemailer/dist/cjs/xoauth2/index.d.ts +201 -0
  85. package/dist/node_modules/nodemailer/dist/cjs/xoauth2/index.js +426 -0
  86. package/dist/node_modules/nodemailer/dist/esm/addressparser/index.d.ts +59 -0
  87. package/dist/node_modules/nodemailer/dist/esm/addressparser/index.js +786 -0
  88. package/dist/node_modules/nodemailer/dist/esm/base64/index.d.ts +36 -0
  89. package/dist/node_modules/nodemailer/{lib → dist/esm}/base64/index.js +39 -68
  90. package/dist/node_modules/nodemailer/dist/esm/dkim/index.d.ts +52 -0
  91. package/dist/node_modules/nodemailer/{lib → dist/esm}/dkim/index.js +62 -92
  92. package/dist/node_modules/nodemailer/dist/esm/dkim/message-parser.d.ts +48 -0
  93. package/dist/node_modules/nodemailer/dist/esm/dkim/message-parser.js +176 -0
  94. package/dist/node_modules/nodemailer/dist/esm/dkim/relaxed-body.d.ts +36 -0
  95. package/dist/node_modules/nodemailer/dist/esm/dkim/relaxed-body.js +141 -0
  96. package/dist/node_modules/nodemailer/dist/esm/dkim/sign.d.ts +52 -0
  97. package/dist/node_modules/nodemailer/dist/esm/dkim/sign.js +125 -0
  98. package/dist/node_modules/nodemailer/dist/esm/errors.d.ts +96 -0
  99. package/dist/node_modules/nodemailer/dist/esm/errors.js +67 -0
  100. package/dist/node_modules/nodemailer/dist/esm/fetch/cookies.d.ts +107 -0
  101. package/dist/node_modules/nodemailer/dist/esm/fetch/cookies.js +242 -0
  102. package/dist/node_modules/nodemailer/dist/esm/fetch/index.d.ts +65 -0
  103. package/dist/node_modules/nodemailer/dist/esm/fetch/index.js +344 -0
  104. package/dist/node_modules/nodemailer/dist/esm/json-transport/index.d.ts +64 -0
  105. package/dist/node_modules/nodemailer/dist/esm/json-transport/index.js +62 -0
  106. package/dist/node_modules/nodemailer/dist/esm/mail-composer/index.d.ts +174 -0
  107. package/dist/node_modules/nodemailer/{lib → dist/esm}/mail-composer/index.js +283 -275
  108. package/dist/node_modules/nodemailer/dist/esm/mailer/index.d.ts +237 -0
  109. package/dist/node_modules/nodemailer/{lib → dist/esm}/mailer/index.js +151 -205
  110. package/dist/node_modules/nodemailer/dist/esm/mailer/mail-message.d.ts +97 -0
  111. package/dist/node_modules/nodemailer/{lib → dist/esm}/mailer/mail-message.js +111 -125
  112. package/dist/node_modules/nodemailer/dist/esm/mime-funcs/index.d.ts +161 -0
  113. package/dist/node_modules/nodemailer/dist/esm/mime-funcs/index.js +738 -0
  114. package/dist/node_modules/nodemailer/dist/esm/mime-funcs/mime-types.d.ts +2 -0
  115. package/dist/node_modules/nodemailer/{lib → dist/esm}/mime-funcs/mime-types.js +43 -49
  116. package/dist/node_modules/nodemailer/dist/esm/mime-node/index.d.ts +333 -0
  117. package/dist/node_modules/nodemailer/{lib → dist/esm}/mime-node/index.js +576 -437
  118. package/dist/node_modules/nodemailer/dist/esm/mime-node/last-newline.d.ts +5 -0
  119. package/dist/node_modules/nodemailer/{lib → dist/esm}/mime-node/last-newline.js +4 -10
  120. package/dist/node_modules/nodemailer/dist/esm/mime-node/le-unix.d.ts +9 -0
  121. package/dist/node_modules/nodemailer/{lib → dist/esm}/mime-node/le-unix.js +7 -15
  122. package/dist/node_modules/nodemailer/dist/esm/mime-node/le-windows.d.ts +10 -0
  123. package/dist/node_modules/nodemailer/{lib → dist/esm}/mime-node/le-windows.js +6 -16
  124. package/dist/node_modules/nodemailer/dist/esm/nodemailer.d.ts +124 -0
  125. package/dist/node_modules/nodemailer/dist/esm/nodemailer.js +166 -0
  126. package/dist/node_modules/nodemailer/dist/esm/package-info.d.ts +3 -0
  127. package/dist/node_modules/nodemailer/dist/esm/package-info.js +4 -0
  128. package/dist/node_modules/nodemailer/dist/esm/package.json +3 -0
  129. package/dist/node_modules/nodemailer/dist/esm/punycode/index.d.ts +73 -0
  130. package/dist/node_modules/nodemailer/dist/esm/punycode/index.js +405 -0
  131. package/dist/node_modules/nodemailer/dist/esm/qp/index.d.ts +32 -0
  132. package/dist/node_modules/nodemailer/{lib → dist/esm}/qp/index.js +59 -77
  133. package/dist/node_modules/nodemailer/dist/esm/sendmail-transport/index.d.ts +69 -0
  134. package/dist/node_modules/nodemailer/dist/esm/sendmail-transport/index.js +170 -0
  135. package/dist/node_modules/nodemailer/dist/esm/ses-transport/index.d.ts +112 -0
  136. package/dist/node_modules/nodemailer/dist/esm/ses-transport/index.js +212 -0
  137. package/dist/node_modules/nodemailer/dist/esm/shared/index.d.ts +260 -0
  138. package/dist/node_modules/nodemailer/dist/esm/shared/index.js +631 -0
  139. package/dist/node_modules/nodemailer/dist/esm/shared/objects.d.ts +23 -0
  140. package/dist/node_modules/nodemailer/dist/esm/shared/objects.js +38 -0
  141. package/dist/node_modules/nodemailer/dist/esm/shared/url.d.ts +21 -0
  142. package/dist/node_modules/nodemailer/dist/esm/shared/url.js +214 -0
  143. package/dist/node_modules/nodemailer/dist/esm/smtp-connection/data-stream.d.ts +15 -0
  144. package/dist/node_modules/nodemailer/dist/esm/smtp-connection/data-stream.js +103 -0
  145. package/dist/node_modules/nodemailer/dist/esm/smtp-connection/http-proxy-client.d.ts +47 -0
  146. package/dist/node_modules/nodemailer/dist/esm/smtp-connection/http-proxy-client.js +149 -0
  147. package/dist/node_modules/nodemailer/dist/esm/smtp-connection/index.d.ts +416 -0
  148. package/dist/node_modules/nodemailer/dist/esm/smtp-connection/index.js +1797 -0
  149. package/dist/node_modules/nodemailer/dist/esm/smtp-pool/index.d.ts +133 -0
  150. package/dist/node_modules/nodemailer/{lib → dist/esm}/smtp-pool/index.js +195 -314
  151. package/dist/node_modules/nodemailer/dist/esm/smtp-pool/pool-resource.d.ts +62 -0
  152. package/dist/node_modules/nodemailer/{lib → dist/esm}/smtp-pool/pool-resource.js +70 -107
  153. package/dist/node_modules/nodemailer/dist/esm/smtp-transport/index.d.ts +156 -0
  154. package/dist/node_modules/nodemailer/dist/esm/smtp-transport/index.js +331 -0
  155. package/dist/node_modules/nodemailer/dist/esm/stream-transport/index.d.ts +65 -0
  156. package/dist/node_modules/nodemailer/dist/esm/stream-transport/index.js +106 -0
  157. package/dist/node_modules/nodemailer/dist/esm/well-known/index.d.ts +35 -0
  158. package/dist/node_modules/nodemailer/{lib → dist/esm}/well-known/index.js +12 -23
  159. package/dist/node_modules/nodemailer/dist/esm/well-known/services.d.ts +2 -0
  160. package/dist/node_modules/nodemailer/dist/esm/well-known/services.js +671 -0
  161. package/dist/node_modules/nodemailer/dist/esm/xoauth2/index.d.ts +201 -0
  162. package/dist/node_modules/nodemailer/dist/esm/xoauth2/index.js +386 -0
  163. package/dist/node_modules/nodemailer/dist/well-known/services.json +640 -0
  164. package/dist/node_modules/nodemailer/package.json +1 -1
  165. package/package.json +4 -4
  166. package/dist/node_modules/nodemailer/.gitattributes +0 -6
  167. package/dist/node_modules/nodemailer/.ncurc.js +0 -7
  168. package/dist/node_modules/nodemailer/.prettierrc.js +0 -8
  169. package/dist/node_modules/nodemailer/lib/addressparser/index.js +0 -313
  170. package/dist/node_modules/nodemailer/lib/dkim/message-parser.js +0 -155
  171. package/dist/node_modules/nodemailer/lib/dkim/relaxed-body.js +0 -154
  172. package/dist/node_modules/nodemailer/lib/dkim/sign.js +0 -117
  173. package/dist/node_modules/nodemailer/lib/fetch/cookies.js +0 -281
  174. package/dist/node_modules/nodemailer/lib/fetch/index.js +0 -274
  175. package/dist/node_modules/nodemailer/lib/json-transport/index.js +0 -82
  176. package/dist/node_modules/nodemailer/lib/mime-funcs/index.js +0 -625
  177. package/dist/node_modules/nodemailer/lib/nodemailer.js +0 -1
  178. package/dist/node_modules/nodemailer/lib/sendmail-transport/index.js +0 -210
  179. package/dist/node_modules/nodemailer/lib/ses-transport/index.js +0 -349
  180. package/dist/node_modules/nodemailer/lib/shared/index.js +0 -688
  181. package/dist/node_modules/nodemailer/lib/smtp-connection/data-stream.js +0 -108
  182. package/dist/node_modules/nodemailer/lib/smtp-connection/http-proxy-client.js +0 -143
  183. package/dist/node_modules/nodemailer/lib/smtp-connection/index.js +0 -1825
  184. package/dist/node_modules/nodemailer/lib/smtp-transport/index.js +0 -416
  185. package/dist/node_modules/nodemailer/lib/stream-transport/index.js +0 -135
  186. package/dist/node_modules/nodemailer/lib/well-known/services.json +0 -343
  187. package/dist/node_modules/nodemailer/lib/xoauth2/index.js +0 -376
@@ -1,23 +1,26 @@
1
1
  /* eslint no-undefined: 0 */
2
-
3
- 'use strict';
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 {Object} mail Mail options
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', { newline: this.mail.newline }).setRaw(this.mail.raw);
36
- } else if (this._useMixed) {
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
- } else if (this._useAlternative) {
44
+ }
45
+ else if (this._useAlternative) {
39
46
  this.message = this._createAlternative();
40
- } else if (this._useRelated) {
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
- let key = header.replace(/-(\w)/g, (o, c) => c.toUpperCase());
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 {Boolean} findRelated If true separate related attachments from attached ones
83
- * @returns {Object} An object of arrays (`related` and `attached`)
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 icalEvent, eventObject;
87
- let attachments = [].concat(this.mail.attachments || []).map((attachment, i) => {
88
- let data;
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
- let contentType = attachment.contentType || mimeFuncs.detectMimeType(attachment.filename || attachment.path || attachment.href || 'bin');
96
- let isImage = /^image\//i.test(contentType);
97
- let contentDisposition = attachment.contentDisposition || (isMessageNode || (isImage && attachment.cid) ? 'inline' : 'attachment');
98
-
99
- data = {
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: 'contentTransferEncoding' in attachment ? attachment.contentTransferEncoding : 'base64'
110
+ contentTransferEncoding
103
111
  };
104
-
105
112
  if (attachment.filename) {
106
113
  data.filename = attachment.filename;
107
- } else if (!isMessageNode && attachment.filename !== false) {
108
- data.filename = (attachment.path || attachment.href || '').split('/').pop().split('?').shift() || 'attachment-' + (i + 1);
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
- } else if (attachment.path) {
133
+ }
134
+ else if (attachment.path) {
126
135
  data.content = {
127
136
  path: attachment.path
128
137
  };
129
- } else if (attachment.href) {
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
- } else {
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
- if (
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 {Array} An array of alternative elements. Includes the `text` and `html` values as well
238
+ * @returns An array of alternative elements. Includes the `text` and `html` values as well
192
239
  */
193
240
  getAlternatives() {
194
- let alternatives = [],
195
- text,
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 (typeof this.mail.text === 'object' && (this.mail.text.content || this.mail.text.path || this.mail.text.href || this.mail.text.raw)) {
244
+ if (isContentObject(this.mail.text)) {
204
245
  text = this.mail.text;
205
- } else {
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
- } else {
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 (typeof this.mail.amp === 'object' && (this.mail.amp.content || this.mail.amp.path || this.mail.amp.href || this.mail.amp.raw)) {
266
+ if (isContentObject(this.mail.amp)) {
229
267
  amp = this.mail.amp;
230
- } else {
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
- if (
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 = 'text/calendar; charset=utf-8; method=' + (eventObject.method || 'PUBLISH').toString().trim().toUpperCase();
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 (typeof this.mail.html === 'object' && (this.mail.html.content || this.mail.html.path || this.mail.html.href || this.mail.html.raw)) {
287
+ if (isContentObject(this.mail.html)) {
271
288
  html = this.mail.html;
272
- } else {
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
- let data;
289
-
290
- if (/^data:/i.test(alternative.path || alternative.href)) {
291
- alternative = this._processDataUrl(alternative);
292
- }
293
-
294
- data = {
295
- contentType: alternative.contentType || mimeFuncs.detectMimeType(alternative.filename || alternative.path || alternative.href || 'txt'),
296
- contentTransferEncoding: alternative.contentTransferEncoding
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
- if (alternative.filename) {
300
- data.filename = alternative.filename;
301
- }
302
-
303
- if (/^https?:\/\//i.test(alternative.path)) {
304
- alternative.href = alternative.path;
305
- alternative.path = undefined;
306
- }
307
-
308
- if (alternative.raw) {
309
- data.raw = alternative.raw;
310
- } else if (alternative.path) {
311
- data.content = {
312
- path: alternative.path
313
- };
314
- } else if (alternative.href) {
315
- data.content = {
316
- href: alternative.href
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 {Object} parentNode Parent for this note. If it does not exist, a root node is created
341
- * @returns {Object} MimeNode node element
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
- let node;
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
- } else {
357
- node = parentNode.createChild('multipart/mixed', {
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
- } else if (this._useRelated) {
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
- // if the element is a html node from related subpart then ignore it
376
- if (!this._useRelated || element !== this._htmlNode) {
377
- this._createContentNode(node, element);
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 {Object} parentNode Parent for this note. If it does not exist, a root node is created
389
- * @returns {Object} MimeNode node element
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
- let node;
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
- } else {
405
- node = parentNode.createChild('multipart/alternative', {
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
- } else {
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 {Object} parentNode Parent for this note. If it does not exist, a root node is created
428
- * @returns {Object} MimeNode node element
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
- let node;
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
- } else {
444
- node = parentNode.createChild('multipart/related; type="text/html"', {
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 {Object} parentNode Parent for this note. If it does not exist, a root node is created
463
- * @param {Object} element Node data
464
- * @returns {Object} MimeNode node element
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
- if (!parentNode) {
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
- } else {
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
- } else if (this.mail.encoding && /^text\//i.test(element.contentType)) {
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
- } else {
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 {Object} element Content element
538
- * @return {Object} Parsed element
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
- if ((element.path || element.href).match(/^data:/)) {
543
- parsedDataUri = parseDataURI(element.path || element.href);
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;