@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
|
@@ -0,0 +1,384 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
const node_http_1 = __importDefault(require("node:http"));
|
|
40
|
+
const node_https_1 = __importDefault(require("node:https"));
|
|
41
|
+
const urllib = __importStar(require("../shared/url.js"));
|
|
42
|
+
const node_zlib_1 = __importDefault(require("node:zlib"));
|
|
43
|
+
const node_stream_1 = require("node:stream");
|
|
44
|
+
const cookies_js_1 = __importDefault(require("./cookies.js"));
|
|
45
|
+
const packageData = __importStar(require("../package-info.js"));
|
|
46
|
+
const node_net_1 = __importDefault(require("node:net"));
|
|
47
|
+
const errors = __importStar(require("../errors.js"));
|
|
48
|
+
const objects_js_1 = require("../shared/objects.js");
|
|
49
|
+
const MAX_REDIRECTS = 5;
|
|
50
|
+
// a stalled server would otherwise hold the request, and whatever waits on it, open forever
|
|
51
|
+
const DEFAULT_TIMEOUT = 60 * 1000;
|
|
52
|
+
// the body is usually buffered in memory by the caller, so an unbounded download is refused
|
|
53
|
+
const DEFAULT_MAX_BYTES = 64 * 1024 * 1024;
|
|
54
|
+
// Only genuine TLS settings are taken from options.tls. That object reaches us straight
|
|
55
|
+
// from a user supplied attachment (content.tls), so keys like host, port, path, socketPath
|
|
56
|
+
// or lookup would otherwise repoint the request at a destination that never went through
|
|
57
|
+
// the URL checks below.
|
|
58
|
+
//
|
|
59
|
+
// The source of truth is the tls.connect() option list in the Node docs. A key missing
|
|
60
|
+
// here is dropped silently, so extend this list rather than working around it.
|
|
61
|
+
const TLS_OPTION_KEYS = [
|
|
62
|
+
'ALPNProtocols',
|
|
63
|
+
'ca',
|
|
64
|
+
'cert',
|
|
65
|
+
'checkServerIdentity',
|
|
66
|
+
'ciphers',
|
|
67
|
+
'crl',
|
|
68
|
+
'dhparam',
|
|
69
|
+
'ecdhCurve',
|
|
70
|
+
'honorCipherOrder',
|
|
71
|
+
'key',
|
|
72
|
+
'maxVersion',
|
|
73
|
+
'minVersion',
|
|
74
|
+
'passphrase',
|
|
75
|
+
'pfx',
|
|
76
|
+
'rejectUnauthorized',
|
|
77
|
+
'secureContext',
|
|
78
|
+
'secureOptions',
|
|
79
|
+
'secureProtocol',
|
|
80
|
+
'servername',
|
|
81
|
+
'sessionIdContext',
|
|
82
|
+
'sigalgs'
|
|
83
|
+
];
|
|
84
|
+
/**
|
|
85
|
+
* Resolves a URL only if it is one this module is willing to request.
|
|
86
|
+
*
|
|
87
|
+
* urllib.parse throws for a host that contains forbidden bytes, and it is called for
|
|
88
|
+
* every URL that reaches nmfetch, including ones that arrive from a message attachment
|
|
89
|
+
* or from a redirect Location header. An uncaught throw here takes the process down,
|
|
90
|
+
* so a URL that does not parse is reported the same way as one with a scheme we refuse.
|
|
91
|
+
*
|
|
92
|
+
* @param url URL to parse
|
|
93
|
+
* @returns Parsed URL, or false if it is not a usable http(s) URL
|
|
94
|
+
*/
|
|
95
|
+
function parseFetchUrl(url) {
|
|
96
|
+
let parsed;
|
|
97
|
+
try {
|
|
98
|
+
parsed = urllib.parse(url);
|
|
99
|
+
}
|
|
100
|
+
catch (_err) {
|
|
101
|
+
return false;
|
|
102
|
+
}
|
|
103
|
+
if (parsed.protocol !== 'http:' && parsed.protocol !== 'https:') {
|
|
104
|
+
return false;
|
|
105
|
+
}
|
|
106
|
+
return parsed;
|
|
107
|
+
}
|
|
108
|
+
function nmfetch(url, options) {
|
|
109
|
+
options = options || {};
|
|
110
|
+
options.fetchRes = options.fetchRes || new node_stream_1.PassThrough();
|
|
111
|
+
options.cookies = options.cookies || new cookies_js_1.default();
|
|
112
|
+
options.redirects = options.redirects || 0;
|
|
113
|
+
options.maxRedirects = isNaN(options.maxRedirects) ? MAX_REDIRECTS : options.maxRedirects;
|
|
114
|
+
const fetchRes = options.fetchRes;
|
|
115
|
+
const parsed = parseFetchUrl(url);
|
|
116
|
+
if (!parsed) {
|
|
117
|
+
// Only http(s) URLs can be fetched. Any other scheme (file:, gopher:, a
|
|
118
|
+
// protocol-relative redirect target etc.) would otherwise be silently served over
|
|
119
|
+
// plain HTTP, possibly against an unintended host. Bail out before the cookie jar
|
|
120
|
+
// is touched so a refused URL can not seed it, and release a caller supplied body:
|
|
121
|
+
// this is the one exit that runs before the error handler below is attached to it,
|
|
122
|
+
// so an error on that stream would have nowhere to go and the fd or socket behind
|
|
123
|
+
// it would never be released.
|
|
124
|
+
if (options.body && typeof options.body.destroy === 'function') {
|
|
125
|
+
options.body.on('error', () => false);
|
|
126
|
+
options.body.destroy();
|
|
127
|
+
}
|
|
128
|
+
setImmediate(() => {
|
|
129
|
+
const err = new Error('Unsupported protocol for URL ' + url);
|
|
130
|
+
err.code = errors.EFETCH;
|
|
131
|
+
err.sourceUrl = url;
|
|
132
|
+
fetchRes.emit('error', err);
|
|
133
|
+
});
|
|
134
|
+
return fetchRes;
|
|
135
|
+
}
|
|
136
|
+
if (options.cookie) {
|
|
137
|
+
[].concat(options.cookie || []).forEach(cookie => {
|
|
138
|
+
options.cookies.set(cookie, url);
|
|
139
|
+
});
|
|
140
|
+
options.cookie = false;
|
|
141
|
+
}
|
|
142
|
+
let method = (options.method || '').toString().trim().toUpperCase() || 'GET';
|
|
143
|
+
let finished = false;
|
|
144
|
+
let cookies;
|
|
145
|
+
let body;
|
|
146
|
+
const handler = parsed.protocol === 'https:' ? node_https_1.default : node_http_1.default;
|
|
147
|
+
const headers = {
|
|
148
|
+
'accept-encoding': 'gzip,deflate',
|
|
149
|
+
'user-agent': 'nodemailer/' + packageData.version
|
|
150
|
+
};
|
|
151
|
+
Object.keys(options.headers || {}).forEach(key => {
|
|
152
|
+
// options.headers is the caller's httpHeaders, straight off an attachment
|
|
153
|
+
if ((0, objects_js_1.isProtoKey)(key.toLowerCase().trim())) {
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
headers[key.toLowerCase().trim()] = options.headers[key];
|
|
157
|
+
});
|
|
158
|
+
if (options.userAgent) {
|
|
159
|
+
headers['user-agent'] = options.userAgent;
|
|
160
|
+
}
|
|
161
|
+
if (parsed.auth) {
|
|
162
|
+
headers.Authorization = 'Basic ' + Buffer.from(parsed.auth).toString('base64');
|
|
163
|
+
}
|
|
164
|
+
if ((cookies = options.cookies.get(url))) {
|
|
165
|
+
headers.cookie = cookies;
|
|
166
|
+
}
|
|
167
|
+
if (options.body) {
|
|
168
|
+
if (options.contentType !== false) {
|
|
169
|
+
headers['Content-Type'] = options.contentType || 'application/x-www-form-urlencoded';
|
|
170
|
+
}
|
|
171
|
+
if (typeof options.body.pipe === 'function') {
|
|
172
|
+
// it's a stream
|
|
173
|
+
headers['Transfer-Encoding'] = 'chunked';
|
|
174
|
+
body = options.body;
|
|
175
|
+
body.on('error', (err) => {
|
|
176
|
+
if (finished) {
|
|
177
|
+
return;
|
|
178
|
+
}
|
|
179
|
+
finished = true;
|
|
180
|
+
err.code = errors.EFETCH;
|
|
181
|
+
err.sourceUrl = url;
|
|
182
|
+
fetchRes.emit('error', err);
|
|
183
|
+
});
|
|
184
|
+
}
|
|
185
|
+
else {
|
|
186
|
+
if (options.body instanceof Buffer) {
|
|
187
|
+
body = options.body;
|
|
188
|
+
}
|
|
189
|
+
else if (typeof options.body === 'object') {
|
|
190
|
+
try {
|
|
191
|
+
// encodeURIComponent can fail on invalid input (partial emoji etc.)
|
|
192
|
+
body = Buffer.from(Object.keys(options.body)
|
|
193
|
+
.map(key => {
|
|
194
|
+
const value = options.body[key].toString().trim();
|
|
195
|
+
return encodeURIComponent(key) + '=' + encodeURIComponent(value);
|
|
196
|
+
})
|
|
197
|
+
.join('&'));
|
|
198
|
+
}
|
|
199
|
+
catch (E) {
|
|
200
|
+
// the caller attaches its error listener once nmfetch has returned, so
|
|
201
|
+
// the error is emitted on the next tick and the stream is handed back
|
|
202
|
+
// the way every other failure is reported
|
|
203
|
+
finished = true;
|
|
204
|
+
E.code = errors.EFETCH;
|
|
205
|
+
E.sourceUrl = url;
|
|
206
|
+
setImmediate(() => fetchRes.emit('error', E));
|
|
207
|
+
return fetchRes;
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
else {
|
|
211
|
+
body = Buffer.from(options.body.toString().trim());
|
|
212
|
+
}
|
|
213
|
+
headers['Content-Type'] = options.contentType || 'application/x-www-form-urlencoded';
|
|
214
|
+
headers['Content-Length'] = body.length;
|
|
215
|
+
}
|
|
216
|
+
// if method is not provided, use POST instead of GET
|
|
217
|
+
method = (options.method || '').toString().trim().toUpperCase() || 'POST';
|
|
218
|
+
}
|
|
219
|
+
let req;
|
|
220
|
+
const reqOptions = {
|
|
221
|
+
method,
|
|
222
|
+
host: parsed.hostname,
|
|
223
|
+
path: parsed.path,
|
|
224
|
+
port: parsed.port ? parsed.port : parsed.protocol === 'https:' ? 443 : 80,
|
|
225
|
+
headers,
|
|
226
|
+
// Validate TLS certificates by default. Callers that genuinely need to
|
|
227
|
+
// reach a self-signed/internal host opt out explicitly with
|
|
228
|
+
// options.tls = { rejectUnauthorized: false }.
|
|
229
|
+
rejectUnauthorized: true,
|
|
230
|
+
agent: false
|
|
231
|
+
};
|
|
232
|
+
if (options.tls) {
|
|
233
|
+
// see TLS_OPTION_KEYS
|
|
234
|
+
Object.keys(options.tls).forEach(key => {
|
|
235
|
+
if (TLS_OPTION_KEYS.includes(key)) {
|
|
236
|
+
reqOptions[key] = options.tls[key];
|
|
237
|
+
}
|
|
238
|
+
});
|
|
239
|
+
}
|
|
240
|
+
if (parsed.protocol === 'https:' &&
|
|
241
|
+
parsed.hostname &&
|
|
242
|
+
parsed.hostname !== reqOptions.host &&
|
|
243
|
+
!node_net_1.default.isIP(parsed.hostname) &&
|
|
244
|
+
!reqOptions.servername) {
|
|
245
|
+
reqOptions.servername = parsed.hostname;
|
|
246
|
+
}
|
|
247
|
+
try {
|
|
248
|
+
req = handler.request(reqOptions);
|
|
249
|
+
}
|
|
250
|
+
catch (E) {
|
|
251
|
+
finished = true;
|
|
252
|
+
setImmediate(() => {
|
|
253
|
+
E.code = errors.EFETCH;
|
|
254
|
+
E.sourceUrl = url;
|
|
255
|
+
fetchRes.emit('error', E);
|
|
256
|
+
});
|
|
257
|
+
return fetchRes;
|
|
258
|
+
}
|
|
259
|
+
// reports the first failure of this request on fetchRes and releases the request
|
|
260
|
+
const fail = (err, sourceUrl = url) => {
|
|
261
|
+
if (finished) {
|
|
262
|
+
return;
|
|
263
|
+
}
|
|
264
|
+
finished = true;
|
|
265
|
+
err.code = errors.EFETCH;
|
|
266
|
+
err.sourceUrl = sourceUrl;
|
|
267
|
+
fetchRes.emit('error', err);
|
|
268
|
+
req.abort();
|
|
269
|
+
};
|
|
270
|
+
const timeout = typeof options.timeout === 'number' && options.timeout >= 0 ? options.timeout : DEFAULT_TIMEOUT;
|
|
271
|
+
if (timeout) {
|
|
272
|
+
req.setTimeout(timeout, () => fail(new Error('Request Timeout')));
|
|
273
|
+
}
|
|
274
|
+
req.on('error', (err) => fail(err));
|
|
275
|
+
req.on('response', res => {
|
|
276
|
+
let inflate;
|
|
277
|
+
if (finished) {
|
|
278
|
+
return;
|
|
279
|
+
}
|
|
280
|
+
switch (res.headers['content-encoding']) {
|
|
281
|
+
case 'gzip':
|
|
282
|
+
case 'deflate':
|
|
283
|
+
inflate = node_zlib_1.default.createUnzip();
|
|
284
|
+
break;
|
|
285
|
+
}
|
|
286
|
+
if (res.headers['set-cookie']) {
|
|
287
|
+
[].concat(res.headers['set-cookie'] || []).forEach(cookie => {
|
|
288
|
+
options.cookies.set(cookie, url);
|
|
289
|
+
});
|
|
290
|
+
}
|
|
291
|
+
if ([301, 302, 303, 307, 308].includes(res.statusCode) && res.headers.location) {
|
|
292
|
+
// redirect
|
|
293
|
+
options.redirects++;
|
|
294
|
+
if (options.redirects > options.maxRedirects) {
|
|
295
|
+
return fail(new Error('Maximum redirect count exceeded'));
|
|
296
|
+
}
|
|
297
|
+
// redirect does not include POST body
|
|
298
|
+
options.method = 'GET';
|
|
299
|
+
options.body = false;
|
|
300
|
+
let redirectUrl;
|
|
301
|
+
try {
|
|
302
|
+
redirectUrl = urllib.resolve(url, res.headers.location);
|
|
303
|
+
}
|
|
304
|
+
catch (_err) {
|
|
305
|
+
// the legacy resolver throws on a Location the WHATWG parser also refused,
|
|
306
|
+
// so fall through to the check below with what the server actually sent
|
|
307
|
+
redirectUrl = res.headers.location;
|
|
308
|
+
}
|
|
309
|
+
const redirectParsed = parseFetchUrl(redirectUrl);
|
|
310
|
+
if (!redirectParsed) {
|
|
311
|
+
// Refuse the redirect target here rather than leaving it to the recursive
|
|
312
|
+
// call: that call gets its own `finished` flag and no handle on this
|
|
313
|
+
// request, so this one would stay open and could emit a second error on
|
|
314
|
+
// the shared fetchRes once it times out. Callers listen with req.once().
|
|
315
|
+
return fail(new Error('Unsupported protocol for URL ' + redirectUrl), redirectUrl);
|
|
316
|
+
}
|
|
317
|
+
// Do not forward credentials when the redirect leaves the original
|
|
318
|
+
// security context: a different host, or a downgrade from https to
|
|
319
|
+
// http (which would otherwise put them on the wire in cleartext).
|
|
320
|
+
// Strip sensitive request headers so an attacker who controls the
|
|
321
|
+
// redirect target cannot harvest them.
|
|
322
|
+
const crossHost = redirectParsed.hostname !== parsed.hostname;
|
|
323
|
+
const downgrade = parsed.protocol === 'https:' && redirectParsed.protocol === 'http:';
|
|
324
|
+
if (options.headers && (crossHost || downgrade)) {
|
|
325
|
+
const sensitive = ['authorization', 'cookie', 'proxy-authorization'];
|
|
326
|
+
Object.keys(options.headers).forEach(key => {
|
|
327
|
+
if (sensitive.includes(key.toLowerCase())) {
|
|
328
|
+
delete options.headers[key];
|
|
329
|
+
}
|
|
330
|
+
});
|
|
331
|
+
}
|
|
332
|
+
// this request is done with, release it so its socket and timeout do not
|
|
333
|
+
// outlive it and report a late error on the shared fetchRes
|
|
334
|
+
finished = true;
|
|
335
|
+
res.resume();
|
|
336
|
+
req.abort();
|
|
337
|
+
return nmfetch(redirectUrl, options);
|
|
338
|
+
}
|
|
339
|
+
fetchRes.statusCode = res.statusCode;
|
|
340
|
+
fetchRes.headers = res.headers;
|
|
341
|
+
if (res.statusCode >= 300 && !options.allowErrorResponse) {
|
|
342
|
+
return fail(new Error('Invalid status code ' + res.statusCode));
|
|
343
|
+
}
|
|
344
|
+
res.on('error', (err) => fail(err));
|
|
345
|
+
const maxBytes = typeof options.maxBytes === 'number' && options.maxBytes > 0 ? options.maxBytes : DEFAULT_MAX_BYTES;
|
|
346
|
+
const source = inflate || res;
|
|
347
|
+
let received = 0;
|
|
348
|
+
source.on('data', (chunk) => {
|
|
349
|
+
received += chunk.length;
|
|
350
|
+
if (received <= maxBytes || finished) {
|
|
351
|
+
return;
|
|
352
|
+
}
|
|
353
|
+
source.unpipe(fetchRes);
|
|
354
|
+
fail(new Error('Response size exceeds the allowed ' + maxBytes + ' bytes'));
|
|
355
|
+
});
|
|
356
|
+
if (inflate) {
|
|
357
|
+
res.pipe(inflate).pipe(fetchRes);
|
|
358
|
+
inflate.on('error', (err) => fail(err));
|
|
359
|
+
}
|
|
360
|
+
else {
|
|
361
|
+
res.pipe(fetchRes);
|
|
362
|
+
}
|
|
363
|
+
});
|
|
364
|
+
setImmediate(() => {
|
|
365
|
+
if (body) {
|
|
366
|
+
try {
|
|
367
|
+
if (typeof body.pipe === 'function') {
|
|
368
|
+
return body.pipe(req);
|
|
369
|
+
}
|
|
370
|
+
req.write(body);
|
|
371
|
+
}
|
|
372
|
+
catch (err) {
|
|
373
|
+
return fail(err);
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
req.end();
|
|
377
|
+
});
|
|
378
|
+
return fetchRes;
|
|
379
|
+
}
|
|
380
|
+
nmfetch.Cookies = cookies_js_1.default;
|
|
381
|
+
nmfetch.DEFAULT_TIMEOUT = DEFAULT_TIMEOUT;
|
|
382
|
+
exports.default = nmfetch;
|
|
383
|
+
module.exports = exports.default;
|
|
384
|
+
Object.defineProperty(module.exports, 'default', { value: exports.default, enumerable: false, writable: true, configurable: true });
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import type { Logger } from '../shared/index.js';
|
|
2
|
+
import type { MimeNodeEnvelope } from '../mime-node/index.js';
|
|
3
|
+
import type MailMessage from '../mailer/mail-message.js';
|
|
4
|
+
import type { default as Mail, SentMessageInfo, SendMailOptions, TransportOptions } from '../mailer/index.js';
|
|
5
|
+
/**
|
|
6
|
+
* Options for the JSON transport
|
|
7
|
+
*/
|
|
8
|
+
export interface JSONTransportOptions extends TransportOptions {
|
|
9
|
+
/** Selects this transport in createTransport */
|
|
10
|
+
jsonTransport?: boolean | undefined;
|
|
11
|
+
/** If true, the message is returned as an object instead of a JSON string */
|
|
12
|
+
skipEncoding?: boolean | undefined;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* The value the JSON transport hands to the send callback. M is the type of the message
|
|
16
|
+
* field: a JSON string by default, the message object itself when skipEncoding is set
|
|
17
|
+
*/
|
|
18
|
+
export interface JSONSentMessageInfo<M = string> extends SentMessageInfo {
|
|
19
|
+
/** The envelope the message was generated with */
|
|
20
|
+
envelope: MimeNodeEnvelope;
|
|
21
|
+
/** Message-ID value of the message */
|
|
22
|
+
messageId: string;
|
|
23
|
+
/** The normalized message as a JSON string, or as the object itself when skipEncoding is set */
|
|
24
|
+
message: M;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* The value the JSON transport hands to the send callback when skipEncoding is set: the
|
|
28
|
+
* message field holds the message object. Typed loosely so that a transporter created with
|
|
29
|
+
* skipEncoding still fits a variable declared with the plain result type
|
|
30
|
+
*/
|
|
31
|
+
export type JSONSentMessageObjectInfo = JSONSentMessageInfo<any>;
|
|
32
|
+
/**
|
|
33
|
+
* Generates a Transport object to generate JSON output
|
|
34
|
+
*
|
|
35
|
+
* @constructor
|
|
36
|
+
* @param optional config parameter
|
|
37
|
+
*/
|
|
38
|
+
declare class JSONTransport {
|
|
39
|
+
mailer: Mail<JSONSentMessageInfo>;
|
|
40
|
+
options: JSONTransportOptions;
|
|
41
|
+
name: string;
|
|
42
|
+
version: string;
|
|
43
|
+
logger: Logger;
|
|
44
|
+
constructor(options?: JSONTransportOptions);
|
|
45
|
+
/**
|
|
46
|
+
* <p>Compiles a mailcomposer message and forwards it to handler that sends it.</p>
|
|
47
|
+
*
|
|
48
|
+
* @param mail MailComposer object
|
|
49
|
+
* @param done Callback function to run when the sending is completed
|
|
50
|
+
*/
|
|
51
|
+
send(mail: MailMessage<JSONSentMessageInfo>, done: (err: Error | null, info?: JSONSentMessageInfo) => void): void;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Type aliases in the layout of @types/nodemailer, so `JSONTransport.Options` style references keep working
|
|
55
|
+
*/
|
|
56
|
+
declare namespace JSONTransport {
|
|
57
|
+
type Options = JSONTransportOptions;
|
|
58
|
+
type MailOptions = SendMailOptions;
|
|
59
|
+
type SentMessageInfo = JSONSentMessageInfo;
|
|
60
|
+
type SentMessageObjectInfo = JSONSentMessageObjectInfo;
|
|
61
|
+
}
|
|
62
|
+
/** The same aliases as module level exports, for `import * as JSONTransport` and `import JSONTransport = require()` */
|
|
63
|
+
export type { JSONTransportOptions as Options, SendMailOptions as MailOptions, JSONSentMessageInfo as SentMessageInfo, JSONSentMessageObjectInfo as SentMessageObjectInfo };
|
|
64
|
+
export default JSONTransport;
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
const packageData = __importStar(require("../package-info.js"));
|
|
37
|
+
const shared = __importStar(require("../shared/index.js"));
|
|
38
|
+
/**
|
|
39
|
+
* Generates a Transport object to generate JSON output
|
|
40
|
+
*
|
|
41
|
+
* @constructor
|
|
42
|
+
* @param optional config parameter
|
|
43
|
+
*/
|
|
44
|
+
class JSONTransport {
|
|
45
|
+
constructor(options) {
|
|
46
|
+
options = options || {};
|
|
47
|
+
this.options = options;
|
|
48
|
+
this.name = 'JSONTransport';
|
|
49
|
+
this.version = packageData.version;
|
|
50
|
+
this.logger = shared.getLogger(this.options, {
|
|
51
|
+
component: this.options.component || 'json-transport'
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* <p>Compiles a mailcomposer message and forwards it to handler that sends it.</p>
|
|
56
|
+
*
|
|
57
|
+
* @param mail MailComposer object
|
|
58
|
+
* @param done Callback function to run when the sending is completed
|
|
59
|
+
*/
|
|
60
|
+
send(mail, done) {
|
|
61
|
+
// Sendmail strips this header line by itself. send() runs after the message was
|
|
62
|
+
// compiled, so mail.message is set
|
|
63
|
+
mail.message.keepBcc = true;
|
|
64
|
+
const envelope = mail.message.getEnvelope();
|
|
65
|
+
const messageId = mail.message.messageId();
|
|
66
|
+
const recipients = [].concat(envelope.to || []);
|
|
67
|
+
if (recipients.length > 3) {
|
|
68
|
+
recipients.push('...and ' + recipients.splice(2).length + ' more');
|
|
69
|
+
}
|
|
70
|
+
this.logger.info({
|
|
71
|
+
tnx: 'send',
|
|
72
|
+
messageId
|
|
73
|
+
}, 'Composing JSON structure of %s to <%s>', messageId, recipients.join(', '));
|
|
74
|
+
setImmediate(() => {
|
|
75
|
+
mail.normalize((err, data) => {
|
|
76
|
+
if (err) {
|
|
77
|
+
this.logger.error({
|
|
78
|
+
err,
|
|
79
|
+
tnx: 'send',
|
|
80
|
+
messageId
|
|
81
|
+
}, 'Failed building JSON structure for %s. %s', messageId, err.message);
|
|
82
|
+
return done(err);
|
|
83
|
+
}
|
|
84
|
+
delete data.envelope;
|
|
85
|
+
delete data.normalizedHeaders;
|
|
86
|
+
// the message field is the object itself with skipEncoding, the
|
|
87
|
+
// createTransport overload for that option types the result accordingly
|
|
88
|
+
return done(null, {
|
|
89
|
+
envelope,
|
|
90
|
+
messageId,
|
|
91
|
+
message: this.options.skipEncoding ? data : JSON.stringify(data)
|
|
92
|
+
});
|
|
93
|
+
});
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
exports.default = JSONTransport;
|
|
98
|
+
module.exports = exports.default;
|
|
99
|
+
Object.defineProperty(module.exports, 'default', { value: exports.default, enumerable: false, writable: true, configurable: true });
|