alepha
Version:
Easy-to-use modern TypeScript framework for building many kind of applications.
1,484 lines (1,483 loc) • 385 kB
JavaScript
import { createRequire } from "node:module";
import { $atom, $env, $hook, $module, $state, z } from "alepha";
import { AlephaEmail, EmailError, EmailProvider } from "alepha/email";
import { $logger } from "alepha/logger";
//#region \0rolldown/runtime.js
var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __commonJSMin = (cb, mod) => () => (mod || (cb((mod = { exports: {} }).exports, mod), cb = null), mod.exports);
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
key = keys[i];
if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, {
get: ((k) => from[k]).bind(null, key),
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
});
}
return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
value: mod,
enumerable: true
}) : target, mod));
var __require = /* #__PURE__ */ (() => createRequire(import.meta.url))();
//#endregion
//#region ../../../../node_modules/nodemailer/lib/punycode/index.js
var require_punycode = /* @__PURE__ */ __commonJSMin(((exports, module) => {
/** Highest positive signed 32-bit float value */
const maxInt = 2147483647;
/** Bootstring parameters */
const base = 36;
const tMin = 1;
const tMax = 26;
const skew = 38;
const damp = 700;
const initialBias = 72;
const initialN = 128;
const delimiter = "-";
/** Regular expressions */
const regexPunycode = /^xn--/;
const regexNonASCII = /[^\0-\x7F]/;
const regexSeparators = /[\x2E\u3002\uFF0E\uFF61]/g;
/** Error messages */
const errors = {
overflow: "Overflow: input needs wider integers to process",
"not-basic": "Illegal input >= 0x80 (not a basic code point)",
"invalid-input": "Invalid input"
};
/** Convenience shortcuts */
const baseMinusTMin = base - tMin;
const floor = Math.floor;
const stringFromCharCode = String.fromCharCode;
/**
* A generic error utility function.
* @private
* @param {String} type The error type.
* @returns {Error} Throws a `RangeError` with the applicable error message.
*/
function error(type) {
throw new RangeError(errors[type]);
}
/**
* A generic `Array#map` utility function.
* @private
* @param {Array} array The array to iterate over.
* @param {Function} callback The function that gets called for every array
* item.
* @returns {Array} A new array of values returned by the callback function.
*/
function map(array, callback) {
const result = [];
let length = array.length;
while (length--) result[length] = callback(array[length]);
return result;
}
/**
* A simple `Array#map`-like wrapper to work with domain name strings or email
* addresses.
* @private
* @param {String} domain The domain name or email address.
* @param {Function} callback The function that gets called for every
* character.
* @returns {String} A new string of characters returned by the callback
* function.
*/
function mapDomain(domain, callback) {
const parts = domain.split("@");
let result = "";
if (parts.length > 1) {
result = parts[0] + "@";
domain = parts[1];
}
domain = domain.replace(regexSeparators, ".");
const encoded = map(domain.split("."), callback).join(".");
return result + encoded;
}
/**
* Creates an array containing the numeric code points of each Unicode
* character in the string. While JavaScript uses UCS-2 internally,
* this function will convert a pair of surrogate halves (each of which
* UCS-2 exposes as separate characters) into a single code point,
* matching UTF-16.
* @see `punycode.ucs2.encode`
* @see <https://mathiasbynens.be/notes/javascript-encoding>
* @memberOf punycode.ucs2
* @name decode
* @param {String} string The Unicode input string (UCS-2).
* @returns {Array} The new array of code points.
*/
function ucs2decode(string) {
const output = [];
let counter = 0;
const length = string.length;
while (counter < length) {
const value = string.charCodeAt(counter++);
if (value >= 55296 && value <= 56319 && counter < length) {
const extra = string.charCodeAt(counter++);
if ((extra & 64512) == 56320) output.push(((value & 1023) << 10) + (extra & 1023) + 65536);
else {
output.push(value);
counter--;
}
} else output.push(value);
}
return output;
}
/**
* Creates a string based on an array of numeric code points.
* @see `punycode.ucs2.decode`
* @memberOf punycode.ucs2
* @name encode
* @param {Array} codePoints The array of numeric code points.
* @returns {String} The new Unicode string (UCS-2).
*/
const ucs2encode = (codePoints) => String.fromCodePoint(...codePoints);
/**
* Converts a basic code point into a digit/integer.
* @see `digitToBasic()`
* @private
* @param {Number} codePoint The basic numeric code point value.
* @returns {Number} The numeric value of a basic code point (for use in
* representing integers) in the range `0` to `base - 1`, or `base` if
* the code point does not represent a value.
*/
const basicToDigit = function(codePoint) {
if (codePoint >= 48 && codePoint < 58) return 26 + (codePoint - 48);
if (codePoint >= 65 && codePoint < 91) return codePoint - 65;
if (codePoint >= 97 && codePoint < 123) return codePoint - 97;
return base;
};
/**
* Converts a digit/integer into a basic code point.
* @see `basicToDigit()`
* @private
* @param {Number} digit The numeric value of a basic code point.
* @returns {Number} The basic code point whose value (when used for
* representing integers) is `digit`, which needs to be in the range
* `0` to `base - 1`. If `flag` is non-zero, the uppercase form is
* used; else, the lowercase form is used. The behavior is undefined
* if `flag` is non-zero and `digit` has no uppercase form.
*/
const digitToBasic = function(digit, flag) {
return digit + 22 + 75 * (digit < 26) - ((flag != 0) << 5);
};
/**
* Bias adaptation function as per section 3.4 of RFC 3492.
* https://tools.ietf.org/html/rfc3492#section-3.4
* @private
*/
const adapt = function(delta, numPoints, firstTime) {
let k = 0;
delta = firstTime ? floor(delta / damp) : delta >> 1;
delta += floor(delta / numPoints);
for (; delta > 455; k += base) delta = floor(delta / baseMinusTMin);
return floor(k + 36 * delta / (delta + skew));
};
/**
* Converts a Punycode string of ASCII-only symbols to a string of Unicode
* symbols.
* @memberOf punycode
* @param {String} input The Punycode string of ASCII-only symbols.
* @returns {String} The resulting string of Unicode symbols.
*/
const decode = function(input) {
const output = [];
const inputLength = input.length;
let i = 0;
let n = initialN;
let bias = initialBias;
let basic = input.lastIndexOf(delimiter);
if (basic < 0) basic = 0;
for (let j = 0; j < basic; ++j) {
if (input.charCodeAt(j) >= 128) error("not-basic");
output.push(input.charCodeAt(j));
}
for (let index = basic > 0 ? basic + 1 : 0; index < inputLength;) {
const oldi = i;
for (let w = 1, k = base;; k += base) {
if (index >= inputLength) error("invalid-input");
const digit = basicToDigit(input.charCodeAt(index++));
if (digit >= base) error("invalid-input");
if (digit > floor((maxInt - i) / w)) error("overflow");
i += digit * w;
const t = k <= bias ? tMin : k >= bias + tMax ? tMax : k - bias;
if (digit < t) break;
const baseMinusT = base - t;
if (w > floor(maxInt / baseMinusT)) error("overflow");
w *= baseMinusT;
}
const out = output.length + 1;
bias = adapt(i - oldi, out, oldi == 0);
if (floor(i / out) > maxInt - n) error("overflow");
n += floor(i / out);
i %= out;
output.splice(i++, 0, n);
}
return String.fromCodePoint(...output);
};
/**
* Converts a string of Unicode symbols (e.g. a domain name label) to a
* Punycode string of ASCII-only symbols.
* @memberOf punycode
* @param {String} input The string of Unicode symbols.
* @returns {String} The resulting Punycode string of ASCII-only symbols.
*/
const encode = function(input) {
const output = [];
input = ucs2decode(input);
const inputLength = input.length;
let n = initialN;
let delta = 0;
let bias = initialBias;
for (const currentValue of input) if (currentValue < 128) output.push(stringFromCharCode(currentValue));
const basicLength = output.length;
let handledCPCount = basicLength;
if (basicLength) output.push(delimiter);
while (handledCPCount < inputLength) {
let m = maxInt;
for (const currentValue of input) if (currentValue >= n && currentValue < m) m = currentValue;
const handledCPCountPlusOne = handledCPCount + 1;
if (m - n > floor((maxInt - delta) / handledCPCountPlusOne)) error("overflow");
delta += (m - n) * handledCPCountPlusOne;
n = m;
for (const currentValue of input) {
if (currentValue < n && ++delta > maxInt) error("overflow");
if (currentValue === n) {
let q = delta;
for (let k = base;; k += base) {
const t = k <= bias ? tMin : k >= bias + tMax ? tMax : k - bias;
if (q < t) break;
const qMinusT = q - t;
const baseMinusT = base - t;
output.push(stringFromCharCode(digitToBasic(t + qMinusT % baseMinusT, 0)));
q = floor(qMinusT / baseMinusT);
}
output.push(stringFromCharCode(digitToBasic(q, 0)));
bias = adapt(delta, handledCPCountPlusOne, handledCPCount === basicLength);
delta = 0;
++handledCPCount;
}
}
++delta;
++n;
}
return output.join("");
};
/**
* Converts a Punycode string representing a domain name or an email address
* to Unicode. Only the Punycoded parts of the input will be converted, i.e.
* it doesn't matter if you call it on a string that has already been
* converted to Unicode.
* @memberOf punycode
* @param {String} input The Punycoded domain name or email address to
* convert to Unicode.
* @returns {String} The Unicode representation of the given Punycode
* string.
*/
const toUnicode = function(input) {
return mapDomain(input, function(string) {
return regexPunycode.test(string) ? decode(string.slice(4).toLowerCase()) : string;
});
};
/**
* Converts a Unicode string representing a domain name or an email address to
* Punycode. Only the non-ASCII parts of the domain name will be converted,
* i.e. it doesn't matter if you call it with a domain that's already in
* ASCII.
* @memberOf punycode
* @param {String} input The domain name or email address to convert, as a
* Unicode string.
* @returns {String} The Punycode representation of the given domain name or
* email address.
*/
const toASCII = function(input) {
return mapDomain(input, function(string) {
return regexNonASCII.test(string) ? "xn--" + encode(string) : string;
});
};
module.exports = {
/**
* A string representing the current Punycode.js version number.
* @memberOf punycode
* @type String
*/
version: "2.3.1",
/**
* An object of methods to convert from JavaScript's internal character
* representation (UCS-2) to Unicode code points, and back.
* @see <https://mathiasbynens.be/notes/javascript-encoding>
* @memberOf punycode
* @type Object
*/
ucs2: {
decode: ucs2decode,
encode: ucs2encode
},
decode,
encode,
toASCII,
toUnicode
};
}));
//#endregion
//#region ../../../../node_modules/nodemailer/lib/shared/url.js
var require_url = /* @__PURE__ */ __commonJSMin(((exports, module) => {
const urllib = __require("url");
const punycode = require_punycode();
const URLImpl = typeof URL !== "undefined" && URL || urllib.URL;
const SLASHLESS_AUTHORITY = /^([a-zA-Z][a-zA-Z0-9+.-]*:)(?!\/\/)(.+)$/;
function safeDecode(str) {
try {
return decodeURIComponent(str);
} catch (_err) {
return str;
}
}
function normalizeHostname(raw) {
let hostname = raw || "";
if (!hostname) return "";
if (hostname.charAt(0) === "[" && hostname.charAt(hostname.length - 1) === "]") return hostname.slice(1, -1);
return punycode.toASCII(safeDecode(hostname));
}
module.exports.parse = (input, parseQueryString) => {
input = input || "";
if (!URLImpl) return urllib.parse(input, parseQueryString);
const slashless = SLASHLESS_AUTHORITY.exec(input);
const normalized = slashless ? slashless[1] + "//" + slashless[2] : input;
let u;
try {
u = new URLImpl(normalized);
} catch (_err) {
return urllib.parse(input, parseQueryString);
}
const hostname = normalizeHostname(u.hostname);
const port = u.port || null;
const pathname = u.pathname || null;
const search = u.search || null;
let auth = null;
if (u.username || u.password) auth = safeDecode(u.username) + (u.password ? ":" + safeDecode(u.password) : "");
let query;
if (parseQueryString) {
query = Object.create(null);
u.searchParams.forEach((value, key) => {
if (Object.prototype.hasOwnProperty.call(query, key)) if (Array.isArray(query[key])) query[key].push(value);
else query[key] = [query[key], value];
else query[key] = value;
});
} else query = search ? search.slice(1) : null;
return {
protocol: u.protocol || null,
host: u.host || null,
hostname,
port,
pathname,
search,
path: (pathname || "") + (search || "") || null,
href: u.href,
auth,
query
};
};
module.exports.resolve = (from, to) => {
if (!URLImpl) return urllib.resolve(from, to);
try {
return new URLImpl(to, from).href;
} catch (_err) {
return urllib.resolve(from, to);
}
};
}));
//#endregion
//#region ../../../../node_modules/nodemailer/lib/fetch/cookies.js
var require_cookies = /* @__PURE__ */ __commonJSMin(((exports, module) => {
const urllib = require_url();
const SESSION_TIMEOUT = 1800;
/**
* Creates a biskviit cookie jar for managing cookie values in memory
*
* @constructor
* @param {Object} [options] Optional options object
*/
var Cookies = class {
constructor(options) {
this.options = options || {};
this.cookies = [];
}
/**
* Stores a cookie string to the cookie storage
*
* @param {String} cookieStr Value from the 'Set-Cookie:' header
* @param {String} url Current URL
*/
set(cookieStr, url) {
const urlparts = urllib.parse(url || "");
const cookie = this.parse(cookieStr);
let domain;
if (cookie.domain) {
domain = cookie.domain.replace(/^\./, "");
if (urlparts.hostname.length < domain.length || ("." + urlparts.hostname).substr(-domain.length + 1) !== "." + domain) cookie.domain = urlparts.hostname;
} else cookie.domain = urlparts.hostname;
if (!cookie.path) cookie.path = this.getPath(urlparts.pathname);
if (!cookie.expires) cookie.expires = new Date(Date.now() + (Number(this.options.sessionTimeout || SESSION_TIMEOUT) || SESSION_TIMEOUT) * 1e3);
return this.add(cookie);
}
/**
* Returns cookie string for the 'Cookie:' header.
*
* @param {String} url URL to check for
* @returns {String} Cookie header or empty string if no matches were found
*/
get(url) {
return this.list(url).map((cookie) => cookie.name + "=" + cookie.value).join("; ");
}
/**
* Lists all valied cookie objects for the specified URL
*
* @param {String} url URL to check for
* @returns {Array} An array of cookie objects
*/
list(url) {
const result = [];
for (let i = this.cookies.length - 1; i >= 0; i--) {
const cookie = this.cookies[i];
if (this.isExpired(cookie)) {
this.cookies.splice(i, 1);
continue;
}
if (this.match(cookie, url)) result.unshift(cookie);
}
return result;
}
/**
* Parses cookie string from the 'Set-Cookie:' header
*
* @param {String} cookieStr String from the 'Set-Cookie:' header
* @returns {Object} Cookie object
*/
parse(cookieStr) {
const cookie = {};
(cookieStr || "").toString().split(";").forEach((cookiePart) => {
const valueParts = cookiePart.split("=");
const key = valueParts.shift().trim().toLowerCase();
let value = valueParts.join("=").trim();
let domain;
if (!key) return;
switch (key) {
case "expires":
value = new Date(value);
if (value.toString() !== "Invalid Date") cookie.expires = value;
break;
case "path":
cookie.path = value;
break;
case "domain":
domain = value.toLowerCase();
if (domain.length && domain.charAt(0) !== ".") domain = "." + domain;
cookie.domain = domain;
break;
case "max-age":
cookie.expires = new Date(Date.now() + (Number(value) || 0) * 1e3);
break;
case "secure":
cookie.secure = true;
break;
case "httponly":
cookie.httponly = true;
break;
default: if (!cookie.name) {
cookie.name = key;
cookie.value = value;
}
}
});
return cookie;
}
/**
* Checks if a cookie object is valid for a specified URL
*
* @param {Object} cookie Cookie object
* @param {String} url URL to check for
* @returns {Boolean} true if cookie is valid for specifiec URL
*/
match(cookie, url) {
const urlparts = urllib.parse(url || "");
if (urlparts.hostname !== cookie.domain && (cookie.domain.charAt(0) !== "." || ("." + urlparts.hostname).substr(-cookie.domain.length) !== cookie.domain)) return false;
if (this.getPath(urlparts.pathname).substr(0, cookie.path.length) !== cookie.path) return false;
if (cookie.secure && urlparts.protocol !== "https:") return false;
return true;
}
/**
* Adds (or updates/removes if needed) a cookie object to the cookie storage
*
* @param {Object} cookie Cookie value to be stored
*/
add(cookie) {
if (!cookie || !cookie.name) return false;
for (let i = 0, len = this.cookies.length; i < len; i++) if (this.compare(this.cookies[i], cookie)) {
if (this.isExpired(cookie)) {
this.cookies.splice(i, 1);
return false;
}
this.cookies[i] = cookie;
return true;
}
if (!this.isExpired(cookie)) this.cookies.push(cookie);
return true;
}
/**
* Checks if two cookie objects are the same
*
* @param {Object} a Cookie to check against
* @param {Object} b Cookie to check against
* @returns {Boolean} True, if the cookies are the same
*/
compare(a, b) {
return a.name === b.name && a.path === b.path && a.domain === b.domain && a.secure === b.secure && a.httponly === b.httponly;
}
/**
* Checks if a cookie is expired
*
* @param {Object} cookie Cookie object to check against
* @returns {Boolean} True, if the cookie is expired
*/
isExpired(cookie) {
return cookie.expires && cookie.expires < /* @__PURE__ */ new Date() || !cookie.value;
}
/**
* Returns normalized cookie path for an URL path argument
*
* @param {String} pathname
* @returns {String} Normalized path
*/
getPath(pathname) {
let path = (pathname || "/").split("/");
path.pop();
path = path.join("/").trim();
if (path.charAt(0) !== "/") path = "/" + path;
if (path.substr(-1) !== "/") path += "/";
return path;
}
};
module.exports = Cookies;
}));
//#endregion
//#region ../../../../node_modules/nodemailer/package.json
var require_package = /* @__PURE__ */ __commonJSMin(((exports, module) => {
module.exports = {
"name": "nodemailer",
"version": "9.0.3",
"description": "Easy as cake e-mail sending from your Node.js applications",
"main": "lib/nodemailer.js",
"scripts": {
"test": "node --test --test-concurrency=1 $(find test \\( -name '*-test.js' -o -name '*.test.js' \\))",
"test:coverage": "c8 node --test --test-concurrency=1 $(find test \\( -name '*-test.js' -o -name '*.test.js' \\))",
"format": "prettier --write \"**/*.{js,json,md}\"",
"format:check": "prettier --check \"**/*.{js,json,md}\"",
"lint": "eslint .",
"lint:fix": "eslint . --fix",
"update": "rm -rf node_modules/ package-lock.json && ncu -u && npm install",
"test:syntax": "docker run --rm -v \"$PWD:/app:ro\" -w /app node:6-alpine node test/syntax-compat.js"
},
"repository": {
"type": "git",
"url": "https://github.com/nodemailer/nodemailer.git"
},
"keywords": ["Nodemailer"],
"author": "Andris Reinman",
"license": "MIT-0",
"bugs": { "url": "https://github.com/nodemailer/nodemailer/issues" },
"homepage": "https://nodemailer.com/",
"devDependencies": {
"@aws-sdk/client-sesv2": "3.1068.0",
"bunyan": "1.8.15",
"c8": "11.0.0",
"eslint": "10.5.0",
"eslint-config-prettier": "10.1.8",
"globals": "17.6.0",
"libbase64": "1.3.0",
"libmime": "5.3.8",
"libqp": "2.1.1",
"prettier": "3.8.4",
"proxy": "1.0.2",
"proxy-test-server": "1.0.0",
"smtp-server": "3.19.0"
},
"engines": { "node": ">=6.0.0" }
};
}));
//#endregion
//#region ../../../../node_modules/nodemailer/lib/errors.js
var require_errors = /* @__PURE__ */ __commonJSMin(((exports, module) => {
/**
* Nodemailer Error Codes
*
* Centralized error code definitions for consistent error handling.
*
* Usage:
* const errors = require('./errors');
* let err = new Error('Connection closed');
* err.code = errors.ECONNECTION;
*/
/**
* Error code descriptions for documentation and debugging
*/
const ERROR_CODES = {
ECONNECTION: "Connection closed unexpectedly",
ETIMEDOUT: "Connection or operation timed out",
ESOCKET: "Socket-level error",
EDNS: "DNS resolution failed",
ETLS: "TLS handshake or STARTTLS failed",
EREQUIRETLS: "REQUIRETLS not supported by server (RFC 8689)",
EPROTOCOL: "Invalid SMTP server response",
EENVELOPE: "Invalid mail envelope (sender or recipients)",
EMESSAGE: "Message delivery error",
ESTREAM: "Stream processing error",
EAUTH: "Authentication failed",
ENOAUTH: "Authentication credentials not provided",
EOAUTH2: "OAuth2 token generation or refresh error",
EMAXLIMIT: "Pool resource limit reached (max messages per connection)",
ESENDMAIL: "Sendmail command error",
ESES: "AWS SES transport error",
ECONFIG: "Invalid configuration",
EPROXY: "Proxy connection error",
EFILEACCESS: "File access rejected (disableFileAccess is set)",
EURLACCESS: "URL access rejected (disableUrlAccess is set)",
EFETCH: "HTTP fetch error"
};
module.exports = { ERROR_CODES };
for (const code of Object.keys(ERROR_CODES)) module.exports[code] = code;
}));
//#endregion
//#region ../../../../node_modules/nodemailer/lib/fetch/index.js
var require_fetch = /* @__PURE__ */ __commonJSMin(((exports, module) => {
const http = __require("http");
const https = __require("https");
const urllib = require_url();
const zlib = __require("zlib");
const { PassThrough: PassThrough$3 } = __require("stream");
const Cookies = require_cookies();
const packageData = require_package();
const net$4 = __require("net");
const errors = require_errors();
const MAX_REDIRECTS = 5;
module.exports = function(url, options) {
return nmfetch(url, options);
};
module.exports.Cookies = Cookies;
function nmfetch(url, options) {
options = options || {};
options.fetchRes = options.fetchRes || new PassThrough$3();
options.cookies = options.cookies || new Cookies();
options.redirects = options.redirects || 0;
options.maxRedirects = isNaN(options.maxRedirects) ? MAX_REDIRECTS : options.maxRedirects;
if (options.cookie) {
[].concat(options.cookie || []).forEach((cookie) => {
options.cookies.set(cookie, url);
});
options.cookie = false;
}
const fetchRes = options.fetchRes;
const parsed = urllib.parse(url);
let method = (options.method || "").toString().trim().toUpperCase() || "GET";
let finished = false;
let cookies;
let body;
const handler = parsed.protocol === "https:" ? https : http;
const headers = {
"accept-encoding": "gzip,deflate",
"user-agent": "nodemailer/" + packageData.version
};
Object.keys(options.headers || {}).forEach((key) => {
headers[key.toLowerCase().trim()] = options.headers[key];
});
if (options.userAgent) headers["user-agent"] = options.userAgent;
if (parsed.auth) headers.Authorization = "Basic " + Buffer.from(parsed.auth).toString("base64");
if (cookies = options.cookies.get(url)) headers.cookie = cookies;
if (options.body) {
if (options.contentType !== false) headers["Content-Type"] = options.contentType || "application/x-www-form-urlencoded";
if (typeof options.body.pipe === "function") {
headers["Transfer-Encoding"] = "chunked";
body = options.body;
body.on("error", (err) => {
if (finished) return;
finished = true;
err.code = errors.EFETCH;
err.sourceUrl = url;
fetchRes.emit("error", err);
});
} else {
if (options.body instanceof Buffer) body = options.body;
else if (typeof options.body === "object") try {
body = Buffer.from(Object.keys(options.body).map((key) => {
const value = options.body[key].toString().trim();
return encodeURIComponent(key) + "=" + encodeURIComponent(value);
}).join("&"));
} catch (E) {
if (finished) return;
finished = true;
E.code = errors.EFETCH;
E.sourceUrl = url;
fetchRes.emit("error", E);
return;
}
else body = Buffer.from(options.body.toString().trim());
headers["Content-Type"] = options.contentType || "application/x-www-form-urlencoded";
headers["Content-Length"] = body.length;
}
method = (options.method || "").toString().trim().toUpperCase() || "POST";
}
let req;
const reqOptions = {
method,
host: parsed.hostname,
path: parsed.path,
port: parsed.port ? parsed.port : parsed.protocol === "https:" ? 443 : 80,
headers,
rejectUnauthorized: true,
agent: false
};
if (options.tls) Object.assign(reqOptions, options.tls);
if (parsed.protocol === "https:" && parsed.hostname && parsed.hostname !== reqOptions.host && !net$4.isIP(parsed.hostname) && !reqOptions.servername) reqOptions.servername = parsed.hostname;
try {
req = handler.request(reqOptions);
} catch (E) {
finished = true;
setImmediate(() => {
E.code = errors.EFETCH;
E.sourceUrl = url;
fetchRes.emit("error", E);
});
return fetchRes;
}
if (options.timeout) req.setTimeout(options.timeout, () => {
if (finished) return;
finished = true;
req.abort();
const err = /* @__PURE__ */ new Error("Request Timeout");
err.code = errors.EFETCH;
err.sourceUrl = url;
fetchRes.emit("error", err);
});
req.on("error", (err) => {
if (finished) return;
finished = true;
err.code = errors.EFETCH;
err.sourceUrl = url;
fetchRes.emit("error", err);
});
req.on("response", (res) => {
let inflate;
if (finished) return;
switch (res.headers["content-encoding"]) {
case "gzip":
case "deflate":
inflate = zlib.createUnzip();
break;
}
if (res.headers["set-cookie"]) [].concat(res.headers["set-cookie"] || []).forEach((cookie) => {
options.cookies.set(cookie, url);
});
if ([
301,
302,
303,
307,
308
].includes(res.statusCode) && res.headers.location) {
options.redirects++;
if (options.redirects > options.maxRedirects) {
finished = true;
const err = /* @__PURE__ */ new Error("Maximum redirect count exceeded");
err.code = errors.EFETCH;
err.sourceUrl = url;
fetchRes.emit("error", err);
req.abort();
return;
}
options.method = "GET";
options.body = false;
const redirectUrl = urllib.resolve(url, res.headers.location);
const redirectParsed = urllib.parse(redirectUrl);
const crossHost = redirectParsed.hostname !== parsed.hostname;
const downgrade = parsed.protocol === "https:" && redirectParsed.protocol === "http:";
if (options.headers && (crossHost || downgrade)) {
const sensitive = [
"authorization",
"cookie",
"proxy-authorization"
];
Object.keys(options.headers).forEach((key) => {
if (sensitive.includes(key.toLowerCase())) delete options.headers[key];
});
}
return nmfetch(redirectUrl, options);
}
fetchRes.statusCode = res.statusCode;
fetchRes.headers = res.headers;
if (res.statusCode >= 300 && !options.allowErrorResponse) {
finished = true;
const err = /* @__PURE__ */ new Error("Invalid status code " + res.statusCode);
err.code = errors.EFETCH;
err.sourceUrl = url;
fetchRes.emit("error", err);
req.abort();
return;
}
res.on("error", (err) => {
if (finished) return;
finished = true;
err.code = errors.EFETCH;
err.sourceUrl = url;
fetchRes.emit("error", err);
req.abort();
});
if (inflate) {
res.pipe(inflate).pipe(fetchRes);
inflate.on("error", (err) => {
if (finished) return;
finished = true;
err.code = errors.EFETCH;
err.sourceUrl = url;
fetchRes.emit("error", err);
req.abort();
});
} else res.pipe(fetchRes);
});
setImmediate(() => {
if (body) try {
if (typeof body.pipe === "function") return body.pipe(req);
req.write(body);
} catch (err) {
finished = true;
err.code = errors.EFETCH;
err.sourceUrl = url;
fetchRes.emit("error", err);
return;
}
req.end();
});
return fetchRes;
}
}));
//#endregion
//#region ../../../../node_modules/nodemailer/lib/shared/index.js
var require_shared = /* @__PURE__ */ __commonJSMin(((exports, module) => {
const urllib = require_url();
const util$1 = __require("util");
const fs$2 = __require("fs");
const nmfetch = require_fetch();
const errors = require_errors();
const dns$1 = __require("dns");
const net$3 = __require("net");
const os$1 = __require("os");
const DNS_TTL = 300 * 1e3;
const CACHE_CLEANUP_INTERVAL = 30 * 1e3;
const MAX_CACHE_SIZE = 1e3;
let lastCacheCleanup = 0;
module.exports._lastCacheCleanup = () => lastCacheCleanup;
module.exports._resetCacheCleanup = () => {
lastCacheCleanup = 0;
};
let networkInterfaces;
try {
networkInterfaces = os$1.networkInterfaces();
} catch (_err) {}
module.exports.networkInterfaces = networkInterfaces;
const isFamilySupported = (family, allowInternal) => {
const ifaces = module.exports.networkInterfaces;
if (!ifaces) return true;
return Object.keys(ifaces).map((key) => ifaces[key]).reduce((acc, val) => acc.concat(val), []).filter((i) => !i.internal || allowInternal).some((i) => i.family === "IPv" + family || i.family === family);
};
const resolve = (family, hostname, options, callback) => {
options = options || {};
if (!isFamilySupported(family, options.allowInternalNetworkInterfaces)) return callback(null, []);
(dns$1.Resolver ? new dns$1.Resolver(options) : dns$1)["resolve" + family](hostname, (err, addresses) => {
if (err) {
switch (err.code) {
case dns$1.NODATA:
case dns$1.NOTFOUND:
case dns$1.NOTIMP:
case dns$1.SERVFAIL:
case dns$1.CONNREFUSED:
case dns$1.REFUSED:
case "EAI_AGAIN": return callback(null, []);
}
return callback(err);
}
return callback(null, Array.isArray(addresses) ? addresses : [].concat(addresses || []));
});
};
const dnsCache = module.exports.dnsCache = /* @__PURE__ */ new Map();
const formatDNSValue = (value, extra) => {
if (!value) return Object.assign({}, extra || {});
const addresses = value.addresses || [];
const host = addresses.length > 0 ? addresses[Math.floor(Math.random() * addresses.length)] : null;
return Object.assign({
servername: value.servername,
host,
_addresses: addresses
}, extra || {});
};
module.exports.resolveHostname = (options, callback) => {
options = options || {};
if (!options.host && options.servername) options.host = options.servername;
if (!options.host || net$3.isIP(options.host)) {
const value = {
addresses: [options.host],
servername: options.servername || false
};
return callback(null, formatDNSValue(value, { cached: false }));
}
let cached;
if (dnsCache.has(options.host)) {
cached = dnsCache.get(options.host);
const now = Date.now();
if (now - lastCacheCleanup > CACHE_CLEANUP_INTERVAL) {
lastCacheCleanup = now;
for (const [host, entry] of dnsCache.entries()) if (entry.expires && entry.expires < now) dnsCache.delete(host);
if (dnsCache.size > MAX_CACHE_SIZE) {
const toDelete = Math.floor(MAX_CACHE_SIZE * .1);
Array.from(dnsCache.keys()).slice(0, toDelete).forEach((key) => dnsCache.delete(key));
}
}
if (!cached.expires || cached.expires >= now) return callback(null, formatDNSValue(cached.value, { cached: true }));
}
let ipv4Addresses = [];
let ipv6Addresses = [];
let ipv4Error = null;
let ipv6Error = null;
resolve(4, options.host, options, (err, addresses) => {
if (err) ipv4Error = err;
else ipv4Addresses = addresses || [];
resolve(6, options.host, options, (err, addresses) => {
if (err) ipv6Error = err;
else ipv6Addresses = addresses || [];
const allAddresses = ipv4Addresses.concat(ipv6Addresses);
if (allAddresses.length) {
const value = {
addresses: allAddresses,
servername: options.servername || options.host
};
dnsCache.set(options.host, {
value,
expires: Date.now() + (options.dnsTtl || DNS_TTL)
});
return callback(null, formatDNSValue(value, { cached: false }));
}
if (ipv4Error && ipv6Error) {
if (cached) {
dnsCache.set(options.host, {
value: cached.value,
expires: Date.now() + (options.dnsTtl || DNS_TTL)
});
return callback(null, formatDNSValue(cached.value, {
cached: true,
error: ipv4Error
}));
}
}
try {
dns$1.lookup(options.host, { all: true }, (err, addresses) => {
if (err) {
if (cached) {
dnsCache.set(options.host, {
value: cached.value,
expires: Date.now() + (options.dnsTtl || DNS_TTL)
});
return callback(null, formatDNSValue(cached.value, {
cached: true,
error: err
}));
}
return callback(err);
}
const supportedAddresses = addresses ? addresses.filter((addr) => isFamilySupported(addr.family)).map((addr) => addr.address) : [];
if (addresses && addresses.length && !supportedAddresses.length) console.warn(`Failed to resolve IPv${addresses[0].family} addresses with current network`);
if (!supportedAddresses.length && cached) return callback(null, formatDNSValue(cached.value, { cached: true }));
const value = {
addresses: supportedAddresses.length ? supportedAddresses : [options.host],
servername: options.servername || options.host
};
dnsCache.set(options.host, {
value,
expires: Date.now() + (options.dnsTtl || DNS_TTL)
});
return callback(null, formatDNSValue(value, { cached: false }));
});
} catch (lookupErr) {
if (cached) {
dnsCache.set(options.host, {
value: cached.value,
expires: Date.now() + (options.dnsTtl || DNS_TTL)
});
return callback(null, formatDNSValue(cached.value, {
cached: true,
error: lookupErr
}));
}
return callback(ipv4Error || ipv6Error || lookupErr);
}
});
});
};
/**
* Parses connection url to a structured configuration object
*
* @param {String} str Connection url
* @return {Object} Configuration object
*/
module.exports.parseConnectionUrl = (str) => {
str = str || "";
const options = {};
const url = urllib.parse(str, true);
switch (url.protocol) {
case "smtp:":
options.secure = false;
break;
case "smtps:":
options.secure = true;
break;
case "direct:":
options.direct = true;
break;
}
if (!isNaN(url.port) && Number(url.port)) options.port = Number(url.port);
if (url.hostname) options.host = url.hostname;
if (url.auth) {
const auth = url.auth.split(":");
options.auth = {
user: auth.shift(),
pass: auth.join(":")
};
}
Object.keys(url.query || {}).forEach((key) => {
let obj = options;
let lKey = key;
let value = url.query[key];
if (!isNaN(value)) value = Number(value);
switch (value) {
case "true":
value = true;
break;
case "false":
value = false;
break;
}
if (key.indexOf("tls.") === 0) {
lKey = key.substr(4);
if (!options.tls) options.tls = {};
obj = options.tls;
} else if (key.indexOf(".") >= 0) return;
if (!(lKey in obj)) obj[lKey] = value;
});
return options;
};
module.exports._logFunc = (logger, level, defaults, data, message, ...args) => {
const entry = Object.assign({}, defaults || {}, data || {});
delete entry.level;
let logLevel = level;
if (typeof logger[logLevel] !== "function") logLevel = [
"info",
"debug",
"log",
"trace",
"warn",
"error"
].find((name) => typeof logger[name] === "function");
if (logLevel) logger[logLevel](entry, message, ...args);
};
/**
* Returns a bunyan-compatible logger interface. Uses either provided logger or
* creates a default console logger
*
* @param {Object} [options] Options object that might include 'logger' value
* @return {Object} bunyan compatible logger
*/
module.exports.getLogger = (options, defaults) => {
options = options || {};
const response = {};
const levels = [
"trace",
"debug",
"info",
"warn",
"error",
"fatal"
];
if (!options.logger) {
levels.forEach((level) => {
response[level] = () => false;
});
return response;
}
const logger = options.logger === true ? createDefaultLogger(levels) : options.logger;
levels.forEach((level) => {
response[level] = (data, message, ...args) => {
module.exports._logFunc(logger, level, defaults, data, message, ...args);
};
});
return response;
};
/**
* Wrapper for creating a callback that either resolves or rejects a promise
* based on input
*
* @param {Function} resolve Function to run if callback is called
* @param {Function} reject Function to run if callback ends with an error
*/
module.exports.callbackPromise = (resolve, reject) => function() {
const args = Array.from(arguments);
const err = args.shift();
if (err) reject(err);
else resolve(...args);
};
module.exports.parseDataURI = (uri) => {
if (typeof uri !== "string") return null;
if (!uri.startsWith("data:")) return null;
const commaPos = uri.indexOf(",");
if (commaPos === -1) return null;
const data = uri.substring(commaPos + 1);
const metaStr = uri.substring(5, commaPos);
let encoding;
const metaEntries = metaStr.split(";");
if (metaEntries.length > 0) {
const lastEntry = metaEntries[metaEntries.length - 1].toLowerCase().trim();
if ([
"base64",
"utf8",
"utf-8"
].includes(lastEntry) && lastEntry.indexOf("=") === -1) {
encoding = lastEntry;
metaEntries.pop();
}
}
const contentType = metaEntries.length > 0 ? metaEntries.shift() : "application/octet-stream";
const params = {};
for (let i = 0; i < metaEntries.length; i++) {
const entry = metaEntries[i];
const sepPos = entry.indexOf("=");
if (sepPos > 0) {
const key = entry.substring(0, sepPos).trim();
const value = entry.substring(sepPos + 1).trim();
if (key) params[key] = value;
}
}
let bufferData;
try {
if (encoding === "base64") bufferData = Buffer.from(data, "base64");
else try {
bufferData = Buffer.from(decodeURIComponent(data));
} catch (_decodeError) {
bufferData = Buffer.from(data);
}
} catch (_bufferError) {
bufferData = Buffer.alloc(0);
}
return {
data: bufferData,
encoding: encoding || null,
contentType: contentType || "application/octet-stream",
params
};
};
/**
* Resolves a String or a Buffer value for content value. Useful if the value
* is a Stream or a file or an URL. If the value is a Stream, overwrites
* the stream object with the resolved value (you can't stream a value twice).
*
* This is useful when you want to create a plugin that needs a content value,
* for example the `html` or `text` value as a String or a Buffer but not as
* a file path or an URL.
*
* @param {Object} data An object or an Array you want to resolve an element for
* @param {String|Number} key Property name or an Array index
* @param {Object} [options] Optional access policy: { disableFileAccess, disableUrlAccess }
* @param {Function} callback Callback function with (err, value)
*/
module.exports.resolveContent = (data, key, options, callback) => {
if (!callback && typeof options === "function") {
callback = options;
options = false;
}
options = options || {};
let promise;
if (!callback) promise = new Promise((resolve, reject) => {
callback = module.exports.callbackPromise(resolve, reject);
});
resolveContentValue(data, key, options, callback);
return promise;
};
function resolveContentValue(data, key, options, callback) {
let content = data && data[key] && data[key].content || data[key];
const encoding = (typeof data[key] === "object" && data[key].encoding || "utf8").toString().toLowerCase().replace(/[-_\s]/g, "");
if (!content) return callback(null, content);
if (typeof content === "object") {
if (typeof content.pipe === "function") return resolveStream(content, (err, value) => {
if (err) return callback(err);
if (data[key].content) data[key].content = value;
else data[key] = value;
callback(null, value);
});
else if (/^https?:\/\//i.test(content.path || content.href)) {
if (options.disableUrlAccess) return setImmediate(() => {
const err = /* @__PURE__ */ new Error("Url access rejected for " + (content.path || content.href));
err.code = errors.EURLACCESS;
callback(err);
});
return resolveStream(nmfetch(content.path || content.href, {
headers: content.httpHeaders,
tls: content.tls
}), callback);
} else if (/^data:/i.test(content.path || content.href)) {
const parsedDataUri = module.exports.parseDataURI(content.path || content.href);
return callback(null, parsedDataUri && parsedDataUri.data ? parsedDataUri.data : Buffer.alloc(0));
} else if (content.path) {
if (options.disableFileAccess) return setImmediate(() => {
const err = /* @__PURE__ */ new Error("File access rejected for " + content.path);
err.code = errors.EFILEACCESS;
callback(err);
});
return resolveStream(fs$2.createReadStream(content.path), callback);
}
}
if (typeof data[key].content === "string" && ![
"utf8",
"usascii",
"ascii"
].includes(encoding)) content = Buffer.from(data[key].content, encoding);
setImmediate(() => callback(null, content));
}
/**
* Copies properties from source objects to target objects
*/
module.exports.assign = function() {
const args = Array.from(arguments);
const target = args.shift() || {};
args.forEach((source) => {
Object.keys(source || {}).forEach((key) => {
if (["tls", "auth"].includes(key) && source[key] && typeof source[key] === "object") target[key] = Object.assign(target[key] || {}, source[key]);
else target[key] = source[key];
});
});
return target;
};
module.exports.encodeXText = (str) => {
if (!/[^\x21-\x2A\x2C-\x3C\x3E-\x7E]/.test(str)) return str;
const buf = Buffer.from(str);
let result = "";
for (let i = 0, len = buf.length; i < len; i++) {
const c = buf[i];
if (c < 33 || c > 126 || c === 43 || c === 61) result += "+" + (c < 16 ? "0" : "") + c.toString(16).toUpperCase();
else result += String.fromCharCode(c);
}
return result;
};
/**
* Streams a stream value into a Buffer
*
* @param {Object} stream Readable stream
* @param {Function} callback Callback function with (err, value)
*/
function resolveStream(stream, callback) {
let responded = false;
const chunks = [];
let chunklen = 0;
stream.on("error", (err) => {
if (responded) return;
responded = true;
callback(err);
});
stream.on("readable", () => {
let chunk;
while ((chunk = stream.read()) !== null) {
chunks.push(chunk);
chunklen += chunk.length;
}
});
stream.on("end", () => {
if (responded) return;
responded = true;
let value;
try {
value = Buffer.concat(chunks, chunklen);
} catch (E) {
return callback(E);
}
callback(null, value);
});
}
/**
* Generates a bunyan-like logger that prints to console
*
* @returns {Object} Bunyan logger instance
*/
function createDefaultLogger(levels) {
const levelMaxLen = levels.reduce((max, level) => Math.max(max, level.length), 0);
const levelNames = /* @__PURE__ */ new Map();
levels.forEach((level) => {
let levelName = level.toUpperCase();
if (levelName.length < levelMaxLen) levelName += " ".repeat(levelMaxLen - levelName.length);
levelNames.set(level, levelName);
});
const print = (level, entry, message, ...args) => {
let prefix = "";
if (entry) {
if (entry.tnx === "server") prefix = "S: ";
else if (entry.tnx === "client") prefix = "C: ";
if (entry.sid) prefix = "[" + entry.sid + "] " + prefix;
if (entry.cid) prefix = "[#" + entry.cid + "] " + prefix;
}
message = util$1.format(message, ...args);
message.split(/\r?\n/).forEach((line) => {
console.log("[%s] %s %s", (/* @__PURE__ */ new Date()).toISOString().substr(0, 19).replace(/T/, " "), levelNames.get(level), prefix + line);
});
};
const logger = {};
levels.forEach((level) => {
logger[level] = print.bind(null, level);
});
return logger;
}
}));
//#endregion
//#region ../../../../node_modules/nodemailer/lib/mime-funcs/mime-types.js
var require_mime_types = /* @__PURE__ */ __commonJSMin(((exports, module) => {
const path$1 = __require("path");
const defaultMimeType = "application/octet-stream";
const defaultExtension = "bin";
const mimeTypes = /* @__PURE__ */ new Map([
["application/acad", "dwg"],
["application/applixware", "aw"],
["application/arj", "arj"],
["application/atom+xml", "xml"],
["application/atomcat+xml", "atomcat"],
["application/atomsvc+xml", "atomsvc"],
["application/base64", ["mm", "mme"]],
["application/binhex", "hqx"],
["application/binhex4", "hqx"],
["application/book", ["book", "boo"]],
["application/ccxml+xml,", "ccxml"],
["application/cdf", "cdf"],
["application/cdmi-capability", "cdmia"],
["application/cdmi-container", "cdmic"],
["application/cdmi-domain", "cdmid"],
["application/cdmi-object", "cdmio"],
["application/cdmi-queue", "cdmiq"],
["application/clariscad", "ccad"],
["application/commonground", "dp"],
["application/cu-seeme", "cu"],
["application/davmount+xml", "davmount"],
["application/drafting", "drw"],
["application/dsptype", "tsp"],
["application/dssc+der", "dssc"],
["application/dssc+xml", "xdssc"],
["application/dxf", "dxf"],
["application/ecmascript", ["js", "es"]],
["application/emma+xml", "emma"],
["application/envoy", "evy"],
["application/epub+zip", "epub"],
["application/excel", [
"xls",
"xl",
"xla",
"xlb",
"xlc",
"xld",
"xlk",
"xll",
"xlm",
"xlt",
"xlv",
"xlw"
]],
["application/exi", "exi"],
["application/font-tdpfr", "pfr"],
["application/fractals", "fif"],
["application/freeloader", "frl"],
["application/futuresplash", "spl"],
["application/geo+json", "geojson"],
["application/gnutar", "tgz"],
["application/groupwise", "vew"],
["application/hlp", "hlp"],
["application/hta", "hta"],
["application/hyperstudio", "stk"],
["application/i-deas", "unv"],
["application/iges", ["iges", "igs"]],
["application/inf", "inf"],
["application/internet-property-stream", "acx"],
["application/ipfix", "ipfix"],
["application/java", "class"],
["application/java-archive", "jar"],
["application/java-byte-code", "class"],
["application/java-serialized-object", "ser"],
["application/java-vm", "class"],
["application/javascript", "js"],
["application/json", "json"],
["application/lha", "lha"],
["application/lzx", "lzx"],
["application/mac-binary", "bin"],
["application/mac-binhex", "hqx"],
["application/mac-binhex40", "hqx"],
["application/mac-compactpro", "cpt"],
["application/macbinary", "bin"],
["application/mads+xml", "mads"],
["application/marc", "mrc"],
["application/marcxml+xml", "mrcx"],
["application/mathematica", "ma"],
["application/mathml+xml", "mathml"],
["application/mbedlet", "mbd"],
["application/mbox", "mbox"],
["application/mcad", "mcd"],
["application/mediaservercontrol+xml", "mscml"],
["application/metalink4+xml", "meta4"],
["application/mets+xml", "mets"],
["application/mime", "aps"],
["application/mods+xml", "mods"],
["application/mp21", "m21"],
["application/mp4", "mp4"],
["application/mspowerpoint", [
"ppt",
"pot",
"pps",
"ppz"
]],
["application/msword", [
"doc",
"dot",
"w6w",
"wiz",
"word"
]],
["application/mswrite", "wri"],
["application/mxf", "mxf"],
["application/netmc", "mcp"],
["application/octet-stream", ["*"]],
["application/oda", "oda"],
["application/oebps-package+xml", "opf"],
["application/ogg", "ogx"],
["application/olescript", "axs"],
["application/onenote", "onetoc"],
["application/patch-ops-error+xml", "xer"],
["application/pdf", "pdf"],
["application/pgp-encrypted", "asc"],
["application/pgp-signature", "pgp"],
["application/pics-rules", "prf"],
["application/pkcs-12", "p12"],
["application/pkcs-crl", "crl"],
["application/pkcs10", "p10"],
["application/pkcs7-mime", ["p7c", "p7m"]],
["application/pkcs7-signature", "p7s"],
["application/pkcs8", "p8"],
["application/pkix-attr-cert", "ac"],
["application/pkix-cert", ["cer", "crt"]],
["application/pkix-crl", "crl"],
["application/pkix-pkipath", "pkipath"],
["application/pkixcmp", "pki"],
["application/plain", "text"],
["application/pls+xml", "pls"],
["application/postscript", [
"ps",