emdash-smtp-core 0.3.3 → 0.3.4
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/index.d.mts +1 -1
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +206 -102
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -371,7 +371,7 @@ declare function isDeliveryReady(args: {
|
|
|
371
371
|
//#endregion
|
|
372
372
|
//#region src/admin.d.ts
|
|
373
373
|
declare const SMTP_PLUGIN_ID = "emdash-smtp";
|
|
374
|
-
declare const SMTP_PLUGIN_VERSION = "0.3.
|
|
374
|
+
declare const SMTP_PLUGIN_VERSION = "0.3.4";
|
|
375
375
|
declare const SMTP_ADMIN_PAGES: readonly [{
|
|
376
376
|
readonly path: "/providers";
|
|
377
377
|
readonly label: "SMTP Providers";
|
package/dist/index.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/types.ts","../src/providers.ts","../src/storage.ts","../src/delivery.ts","../src/admin.ts"],"mappings":"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
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/types.ts","../src/providers.ts","../src/storage.ts","../src/delivery.ts","../src/admin.ts"],"mappings":"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"}
|
package/dist/index.mjs
CHANGED
|
@@ -41,13 +41,14 @@ async function getGlobalSettings(ctx) {
|
|
|
41
41
|
};
|
|
42
42
|
}
|
|
43
43
|
async function saveGlobalSettingsFromValues(ctx, values) {
|
|
44
|
+
const current = await getGlobalSettings(ctx);
|
|
44
45
|
const next = {
|
|
45
|
-
primaryProviderId: trimString(values.primaryProviderId),
|
|
46
|
-
fallbackProviderId: trimString(values.fallbackProviderId),
|
|
47
|
-
fromEmail: trimString(values.fromEmail),
|
|
48
|
-
fromName: trimString(values.fromName),
|
|
49
|
-
replyTo: trimString(values.replyTo),
|
|
50
|
-
logLevel: normalizeLogLevel(values.logLevel)
|
|
46
|
+
primaryProviderId: values.primaryProviderId === void 0 ? current.primaryProviderId : trimString(values.primaryProviderId),
|
|
47
|
+
fallbackProviderId: values.fallbackProviderId === void 0 ? current.fallbackProviderId : trimString(values.fallbackProviderId),
|
|
48
|
+
fromEmail: values.fromEmail === void 0 ? current.fromEmail : trimString(values.fromEmail),
|
|
49
|
+
fromName: values.fromName === void 0 ? current.fromName : trimString(values.fromName),
|
|
50
|
+
replyTo: values.replyTo === void 0 ? current.replyTo : trimString(values.replyTo),
|
|
51
|
+
logLevel: values.logLevel === void 0 ? current.logLevel : normalizeLogLevel(values.logLevel)
|
|
51
52
|
};
|
|
52
53
|
await ctx.kv.set(GLOBAL_SETTINGS_KEY, next);
|
|
53
54
|
return next;
|
|
@@ -1571,7 +1572,14 @@ async function isDeliveryReady(args) {
|
|
|
1571
1572
|
//#endregion
|
|
1572
1573
|
//#region src/admin.ts
|
|
1573
1574
|
const SMTP_PLUGIN_ID = "emdash-smtp";
|
|
1574
|
-
const SMTP_PLUGIN_VERSION = "0.3.
|
|
1575
|
+
const SMTP_PLUGIN_VERSION = "0.3.4";
|
|
1576
|
+
const RECOMMENDED_PROVIDER_IDS = [
|
|
1577
|
+
"resend",
|
|
1578
|
+
"postmark",
|
|
1579
|
+
"sendgrid",
|
|
1580
|
+
"mailgun",
|
|
1581
|
+
"generic"
|
|
1582
|
+
];
|
|
1575
1583
|
const SMTP_ADMIN_PAGES = [{
|
|
1576
1584
|
path: "/providers",
|
|
1577
1585
|
label: "SMTP Providers",
|
|
@@ -1718,14 +1726,17 @@ async function buildSummary(ctx) {
|
|
|
1718
1726
|
failedCount
|
|
1719
1727
|
};
|
|
1720
1728
|
}
|
|
1721
|
-
async function getCurrentProvider(ctx, variant) {
|
|
1729
|
+
async function getCurrentProvider(ctx, variant, primaryProviderId) {
|
|
1722
1730
|
const selected = await getSelectedProviderId(ctx);
|
|
1723
|
-
const preferred = selected ? getProviderById(selected) : void 0;
|
|
1731
|
+
const preferred = selected ? getProviderById(selected) : primaryProviderId ? getProviderById(primaryProviderId) : void 0;
|
|
1724
1732
|
if (preferred) return preferred;
|
|
1733
|
+
for (const providerId of RECOMMENDED_PROVIDER_IDS) {
|
|
1734
|
+
const recommended = getProviderById(providerId);
|
|
1735
|
+
if (recommended && isProviderAvailable(recommended, variant)) return recommended;
|
|
1736
|
+
}
|
|
1725
1737
|
return SMTP_PROVIDER_DEFINITIONS.find((provider) => isProviderAvailable(provider, variant)) ?? SMTP_PROVIDER_DEFINITIONS[0];
|
|
1726
1738
|
}
|
|
1727
|
-
function
|
|
1728
|
-
const availableOptions = getAvailableProviderSelectOptions(variant);
|
|
1739
|
+
function buildSenderSettingsForm(settings) {
|
|
1729
1740
|
const logLevelOptions = [
|
|
1730
1741
|
{
|
|
1731
1742
|
label: "All deliveries",
|
|
@@ -1744,24 +1755,6 @@ function buildGlobalSettingsForm(settings, variant) {
|
|
|
1744
1755
|
type: "form",
|
|
1745
1756
|
block_id: "global-settings",
|
|
1746
1757
|
fields: [
|
|
1747
|
-
selectField({
|
|
1748
|
-
key: "primaryProviderId",
|
|
1749
|
-
label: "Primary Provider",
|
|
1750
|
-
type: "select",
|
|
1751
|
-
options: availableOptions
|
|
1752
|
-
}, settings.primaryProviderId, availableOptions),
|
|
1753
|
-
selectField({
|
|
1754
|
-
key: "fallbackProviderId",
|
|
1755
|
-
label: "Fallback Provider",
|
|
1756
|
-
type: "select",
|
|
1757
|
-
options: [{
|
|
1758
|
-
label: "None",
|
|
1759
|
-
value: ""
|
|
1760
|
-
}, ...availableOptions]
|
|
1761
|
-
}, settings.fallbackProviderId, [{
|
|
1762
|
-
label: "None",
|
|
1763
|
-
value: ""
|
|
1764
|
-
}, ...availableOptions]),
|
|
1765
1758
|
textField({
|
|
1766
1759
|
key: "fromEmail",
|
|
1767
1760
|
label: "Default From Email",
|
|
@@ -1789,7 +1782,7 @@ function buildGlobalSettingsForm(settings, variant) {
|
|
|
1789
1782
|
}, settings.logLevel ?? "all", logLevelOptions)
|
|
1790
1783
|
],
|
|
1791
1784
|
submit: {
|
|
1792
|
-
label: "Save
|
|
1785
|
+
label: "Save Sender Settings",
|
|
1793
1786
|
action_id: "save_global"
|
|
1794
1787
|
}
|
|
1795
1788
|
};
|
|
@@ -1798,42 +1791,123 @@ function buildProviderPickerForm(providerId, variant) {
|
|
|
1798
1791
|
const options = getProviderPickerOptions(variant);
|
|
1799
1792
|
return {
|
|
1800
1793
|
type: "form",
|
|
1801
|
-
block_id: "provider-
|
|
1794
|
+
block_id: "provider-browser",
|
|
1802
1795
|
fields: [selectField({
|
|
1803
1796
|
key: "providerId",
|
|
1804
|
-
label: "
|
|
1797
|
+
label: "Browse every provider",
|
|
1805
1798
|
type: "select",
|
|
1806
1799
|
options
|
|
1807
1800
|
}, providerId, options)],
|
|
1808
1801
|
submit: {
|
|
1809
|
-
label: "
|
|
1802
|
+
label: "Switch Provider",
|
|
1810
1803
|
action_id: "select_provider"
|
|
1811
1804
|
}
|
|
1812
1805
|
};
|
|
1813
1806
|
}
|
|
1814
|
-
function
|
|
1815
|
-
|
|
1807
|
+
function getProviderRoutingRole(provider, settings) {
|
|
1808
|
+
if (settings.primaryProviderId === provider.id) return "primary";
|
|
1809
|
+
if (settings.fallbackProviderId === provider.id) return "fallback";
|
|
1810
|
+
return "none";
|
|
1811
|
+
}
|
|
1812
|
+
function setupNextStep(settings, configured, routingRole) {
|
|
1813
|
+
if (!configured) return "Add credentials";
|
|
1814
|
+
if (routingRole === "none") return "Set delivery route";
|
|
1815
|
+
if (!settings.fromEmail) return "Add sender";
|
|
1816
|
+
return "Ready to test";
|
|
1817
|
+
}
|
|
1818
|
+
function routeSummary(provider, routingRole) {
|
|
1819
|
+
if (routingRole === "primary") return `${provider.label} handles delivery`;
|
|
1820
|
+
if (routingRole === "fallback") return `${provider.label} is the fallback`;
|
|
1821
|
+
return "Not routed";
|
|
1822
|
+
}
|
|
1823
|
+
async function buildProviderCatalogEntries(ctx, variant, settings, currentProvider) {
|
|
1824
|
+
return Promise.all(SMTP_PROVIDER_DEFINITIONS.map(async (provider) => {
|
|
1825
|
+
const providerSettings = await getProviderSettings(ctx, provider.id);
|
|
1826
|
+
return {
|
|
1827
|
+
provider,
|
|
1828
|
+
available: isProviderAvailable(provider, variant),
|
|
1829
|
+
configured: isProviderConfigured(provider, providerSettings),
|
|
1830
|
+
selected: provider.id === currentProvider.id,
|
|
1831
|
+
routingRole: getProviderRoutingRole(provider, settings)
|
|
1832
|
+
};
|
|
1833
|
+
}));
|
|
1834
|
+
}
|
|
1835
|
+
function buildProviderQuickPicks(entries) {
|
|
1836
|
+
const quickPicks = RECOMMENDED_PROVIDER_IDS.map((providerId) => entries.find((entry) => entry.provider.id === providerId && entry.available)).filter((entry) => Boolean(entry));
|
|
1837
|
+
const blocks = [{
|
|
1838
|
+
type: "section",
|
|
1839
|
+
text: "Provider"
|
|
1840
|
+
}];
|
|
1841
|
+
if (quickPicks.length > 0) blocks.push(actions(quickPicks.map((entry) => button(`select_provider:${entry.provider.id}`, entry.provider.label, {
|
|
1842
|
+
style: entry.selected ? "primary" : "secondary",
|
|
1843
|
+
value: entry.provider.id
|
|
1844
|
+
}))));
|
|
1845
|
+
return blocks;
|
|
1846
|
+
}
|
|
1847
|
+
function buildRoutingActions(settings, currentProvider) {
|
|
1848
|
+
const elements = [];
|
|
1849
|
+
if (settings.primaryProviderId !== currentProvider.id) elements.push(button("set_primary_provider", `Use ${currentProvider.label} for delivery`, {
|
|
1850
|
+
style: "primary",
|
|
1851
|
+
value: currentProvider.id
|
|
1852
|
+
}));
|
|
1853
|
+
else elements.push(button("set_primary_provider", "Primary provider", {
|
|
1854
|
+
style: "secondary",
|
|
1855
|
+
value: currentProvider.id
|
|
1856
|
+
}));
|
|
1857
|
+
if (settings.fallbackProviderId === currentProvider.id) elements.push(button("clear_fallback_provider", "Remove fallback", { style: "secondary" }));
|
|
1858
|
+
else if (settings.primaryProviderId && settings.primaryProviderId !== currentProvider.id) elements.push(button("set_fallback_provider", "Use as fallback", {
|
|
1859
|
+
style: "secondary",
|
|
1860
|
+
value: currentProvider.id
|
|
1861
|
+
}));
|
|
1862
|
+
else if (settings.fallbackProviderId) elements.push(button("clear_fallback_provider", "Clear fallback", { style: "secondary" }));
|
|
1863
|
+
return elements.length ? [actions(elements)] : [];
|
|
1864
|
+
}
|
|
1865
|
+
function buildSetupOverview(settings, currentProvider, configured, routingRole) {
|
|
1816
1866
|
return [{
|
|
1817
|
-
type: "
|
|
1818
|
-
|
|
1867
|
+
type: "section",
|
|
1868
|
+
text: "Current setup"
|
|
1869
|
+
}, {
|
|
1870
|
+
type: "table",
|
|
1871
|
+
page_action_id: "go_providers",
|
|
1872
|
+
columns: [
|
|
1819
1873
|
{
|
|
1820
|
-
|
|
1821
|
-
|
|
1874
|
+
key: "area",
|
|
1875
|
+
label: "Area"
|
|
1822
1876
|
},
|
|
1823
1877
|
{
|
|
1824
|
-
|
|
1825
|
-
|
|
1878
|
+
key: "status",
|
|
1879
|
+
label: "Status"
|
|
1826
1880
|
},
|
|
1827
1881
|
{
|
|
1828
|
-
|
|
1829
|
-
|
|
1882
|
+
key: "next",
|
|
1883
|
+
label: "Next"
|
|
1884
|
+
}
|
|
1885
|
+
],
|
|
1886
|
+
rows: [
|
|
1887
|
+
{
|
|
1888
|
+
area: currentProvider.label,
|
|
1889
|
+
status: configured ? "Ready" : "Needs setup",
|
|
1890
|
+
next: setupNextStep(settings, configured, routingRole)
|
|
1891
|
+
},
|
|
1892
|
+
{
|
|
1893
|
+
area: "Delivery route",
|
|
1894
|
+
status: routeSummary(currentProvider, routingRole),
|
|
1895
|
+
next: routingRole === "none" ? `Use ${currentProvider.label}` : "Set"
|
|
1830
1896
|
},
|
|
1831
1897
|
{
|
|
1832
|
-
|
|
1833
|
-
|
|
1898
|
+
area: "Sender",
|
|
1899
|
+
status: settings.fromEmail ?? "Not set",
|
|
1900
|
+
next: settings.fromEmail ? "Saved" : "Add default"
|
|
1834
1901
|
}
|
|
1835
1902
|
]
|
|
1836
|
-
}
|
|
1903
|
+
}];
|
|
1904
|
+
}
|
|
1905
|
+
function buildProviderDetails(provider, variant, configured, routingRole) {
|
|
1906
|
+
return [context([
|
|
1907
|
+
isProviderAvailable(provider, variant) ? "Available" : "Trusted only",
|
|
1908
|
+
configured ? "settings ready" : "needs credentials",
|
|
1909
|
+
routeSummary(provider, routingRole)
|
|
1910
|
+
].join(" · ")), context(provider.description)];
|
|
1837
1911
|
}
|
|
1838
1912
|
function buildProviderSettingsForm(provider, settings) {
|
|
1839
1913
|
return {
|
|
@@ -1951,69 +2025,43 @@ async function buildLogsTable(ctx) {
|
|
|
1951
2025
|
async function buildProvidersPage(ctx, variant, runtime, toast) {
|
|
1952
2026
|
const summary = await buildSummary(ctx);
|
|
1953
2027
|
const settings = await getGlobalSettings(ctx);
|
|
1954
|
-
const currentProvider = await getCurrentProvider(ctx, variant);
|
|
2028
|
+
const currentProvider = await getCurrentProvider(ctx, variant, settings.primaryProviderId);
|
|
1955
2029
|
const currentProviderSettings = await getProviderSettings(ctx, currentProvider.id);
|
|
1956
2030
|
const configured = isProviderConfigured(currentProvider, currentProviderSettings);
|
|
2031
|
+
const currentRoutingRole = getProviderRoutingRole(currentProvider, settings);
|
|
2032
|
+
const catalogEntries = await buildProviderCatalogEntries(ctx, variant, settings, currentProvider);
|
|
1957
2033
|
const lastTestResult = await getLastTestResult(ctx);
|
|
1958
2034
|
const secretActions = buildProviderSecretActions(currentProvider, currentProviderSettings);
|
|
1959
|
-
const
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
|
|
1965
|
-
configured: isProviderConfigured(provider, providerSettings) ? "yes" : "no",
|
|
1966
|
-
selected: provider.id === currentProvider.id ? "current" : ""
|
|
1967
|
-
};
|
|
1968
|
-
}));
|
|
1969
|
-
const blocks = [
|
|
1970
|
-
header("SMTP Providers"),
|
|
1971
|
-
banner(variant === "marketplace" ? "Marketplace-safe variant" : "Trusted variant", variant === "marketplace" ? "This install can use HTTP API providers. Generic SMTP and local sendmail remain visible for parity but are not available here." : `This install can use all providers, including Generic SMTP and local sendmail. Allowed hosts: ${collectAllowedHosts("trusted").join(", ")}`, variant === "marketplace" ? "alert" : "default"),
|
|
1972
|
-
stats(summary),
|
|
1973
|
-
actions([button("go_providers", "Providers", { style: "secondary" }), button("go_logs", "View Logs", { style: "primary" })]),
|
|
1974
|
-
{
|
|
1975
|
-
type: "table",
|
|
1976
|
-
page_action_id: "go_providers",
|
|
1977
|
-
empty_text: "No providers available.",
|
|
1978
|
-
columns: [
|
|
1979
|
-
{
|
|
1980
|
-
key: "provider",
|
|
1981
|
-
label: "Provider"
|
|
1982
|
-
},
|
|
1983
|
-
{
|
|
1984
|
-
key: "id",
|
|
1985
|
-
label: "ID",
|
|
1986
|
-
format: "code"
|
|
1987
|
-
},
|
|
1988
|
-
{
|
|
1989
|
-
key: "availability",
|
|
1990
|
-
label: "Availability",
|
|
1991
|
-
format: "badge"
|
|
1992
|
-
},
|
|
1993
|
-
{
|
|
1994
|
-
key: "configured",
|
|
1995
|
-
label: "Configured",
|
|
1996
|
-
format: "badge"
|
|
1997
|
-
},
|
|
1998
|
-
{
|
|
1999
|
-
key: "selected",
|
|
2000
|
-
label: "Selected",
|
|
2001
|
-
format: "badge"
|
|
2002
|
-
}
|
|
2003
|
-
],
|
|
2004
|
-
rows: providerRows
|
|
2005
|
-
},
|
|
2006
|
-
divider(),
|
|
2007
|
-
buildProviderPickerForm(currentProvider.id, variant),
|
|
2008
|
-
...buildProviderDetails(currentProvider, variant, configured),
|
|
2009
|
-
buildGlobalSettingsForm(settings, variant)
|
|
2010
|
-
];
|
|
2035
|
+
const blocks = [header("SMTP Providers")];
|
|
2036
|
+
if (variant === "marketplace") blocks.push(banner("Marketplace install", "HTTP API providers are available.", "alert"));
|
|
2037
|
+
blocks.push(stats(summary), actions([button("go_providers", "Providers", { style: "secondary" }), button("go_logs", "View Logs", { style: "primary" })]), ...buildSetupOverview(settings, currentProvider, configured, currentRoutingRole), ...buildProviderQuickPicks(catalogEntries), divider(), {
|
|
2038
|
+
type: "section",
|
|
2039
|
+
text: `${currentProvider.label} setup`
|
|
2040
|
+
}, ...buildProviderDetails(currentProvider, variant, configured, currentRoutingRole));
|
|
2011
2041
|
if (!isProviderAvailable(currentProvider, variant)) blocks.push(banner(`${currentProvider.label} is not available in the marketplace variant`, "Use the trusted emdash-smtp package in astro.config.mjs if you need this transport.", "alert"));
|
|
2012
2042
|
else {
|
|
2013
2043
|
blocks.push(buildProviderSettingsForm(currentProvider, currentProviderSettings));
|
|
2014
2044
|
if (secretActions) blocks.push(secretActions);
|
|
2015
|
-
blocks.push(...buildTestSendForm(lastTestResult));
|
|
2016
2045
|
}
|
|
2046
|
+
blocks.push(divider());
|
|
2047
|
+
blocks.push({
|
|
2048
|
+
type: "section",
|
|
2049
|
+
text: "Sender identity"
|
|
2050
|
+
});
|
|
2051
|
+
blocks.push(...buildRoutingActions(settings, currentProvider));
|
|
2052
|
+
blocks.push(buildSenderSettingsForm(settings));
|
|
2053
|
+
blocks.push(divider());
|
|
2054
|
+
blocks.push({
|
|
2055
|
+
type: "section",
|
|
2056
|
+
text: "Need a different provider?"
|
|
2057
|
+
});
|
|
2058
|
+
blocks.push(buildProviderPickerForm(currentProvider.id, variant));
|
|
2059
|
+
blocks.push(divider());
|
|
2060
|
+
blocks.push({
|
|
2061
|
+
type: "section",
|
|
2062
|
+
text: "Test delivery"
|
|
2063
|
+
});
|
|
2064
|
+
blocks.push(...buildTestSendForm(lastTestResult));
|
|
2017
2065
|
return {
|
|
2018
2066
|
blocks,
|
|
2019
2067
|
...toast ? { toast } : {}
|
|
@@ -2044,6 +2092,62 @@ async function handleAdminInteraction(args) {
|
|
|
2044
2092
|
if (interaction.type === "block_action" || interaction.type === "action") {
|
|
2045
2093
|
if (interaction.action_id === "go_logs") return buildLogsPage(ctx);
|
|
2046
2094
|
if (interaction.action_id === "go_providers") return buildProvidersPage(ctx, variant, runtime);
|
|
2095
|
+
if (interaction.action_id === "select_provider" || interaction.action_id.startsWith("select_provider:")) {
|
|
2096
|
+
const providerId = stringValue(interaction.value) ?? (interaction.action_id.startsWith("select_provider:") ? stringValue(interaction.action_id.split(":")[1]) : void 0);
|
|
2097
|
+
if (providerId && getProviderById(providerId)) {
|
|
2098
|
+
await setSelectedProviderId(ctx, providerId);
|
|
2099
|
+
return buildProvidersPage(ctx, variant, runtime, {
|
|
2100
|
+
message: `Editing ${getProviderLabel(providerId)}.`,
|
|
2101
|
+
type: "info"
|
|
2102
|
+
});
|
|
2103
|
+
}
|
|
2104
|
+
return buildProvidersPage(ctx, variant, runtime, {
|
|
2105
|
+
message: "Provider could not be selected.",
|
|
2106
|
+
type: "error"
|
|
2107
|
+
});
|
|
2108
|
+
}
|
|
2109
|
+
if (interaction.action_id === "set_primary_provider") {
|
|
2110
|
+
const providerId = stringValue(interaction.value);
|
|
2111
|
+
const provider = providerId ? getProviderById(providerId) : void 0;
|
|
2112
|
+
if (provider && isProviderAvailable(provider, variant)) {
|
|
2113
|
+
const settings = await getGlobalSettings(ctx);
|
|
2114
|
+
await saveGlobalSettingsFromValues(ctx, {
|
|
2115
|
+
primaryProviderId: provider.id,
|
|
2116
|
+
...settings.fallbackProviderId === provider.id ? { fallbackProviderId: "" } : {}
|
|
2117
|
+
});
|
|
2118
|
+
return buildProvidersPage(ctx, variant, runtime, {
|
|
2119
|
+
message: `${provider.label} is now the delivery provider.`,
|
|
2120
|
+
type: "success"
|
|
2121
|
+
});
|
|
2122
|
+
}
|
|
2123
|
+
return buildProvidersPage(ctx, variant, runtime, {
|
|
2124
|
+
message: "Provider could not be routed.",
|
|
2125
|
+
type: "error"
|
|
2126
|
+
});
|
|
2127
|
+
}
|
|
2128
|
+
if (interaction.action_id === "set_fallback_provider") {
|
|
2129
|
+
const providerId = stringValue(interaction.value);
|
|
2130
|
+
const provider = providerId ? getProviderById(providerId) : void 0;
|
|
2131
|
+
const settings = await getGlobalSettings(ctx);
|
|
2132
|
+
if (provider && isProviderAvailable(provider, variant) && settings.primaryProviderId !== provider.id) {
|
|
2133
|
+
await saveGlobalSettingsFromValues(ctx, { fallbackProviderId: provider.id });
|
|
2134
|
+
return buildProvidersPage(ctx, variant, runtime, {
|
|
2135
|
+
message: `${provider.label} is now the fallback provider.`,
|
|
2136
|
+
type: "success"
|
|
2137
|
+
});
|
|
2138
|
+
}
|
|
2139
|
+
return buildProvidersPage(ctx, variant, runtime, {
|
|
2140
|
+
message: "Fallback provider could not be routed.",
|
|
2141
|
+
type: "error"
|
|
2142
|
+
});
|
|
2143
|
+
}
|
|
2144
|
+
if (interaction.action_id === "clear_fallback_provider") {
|
|
2145
|
+
await saveGlobalSettingsFromValues(ctx, { fallbackProviderId: "" });
|
|
2146
|
+
return buildProvidersPage(ctx, variant, runtime, {
|
|
2147
|
+
message: "Fallback provider cleared.",
|
|
2148
|
+
type: "success"
|
|
2149
|
+
});
|
|
2150
|
+
}
|
|
2047
2151
|
if (interaction.action_id.startsWith("clear_secret:")) {
|
|
2048
2152
|
const [, providerId, fieldKey] = interaction.action_id.split(":");
|
|
2049
2153
|
if (providerId && fieldKey) {
|
|
@@ -2060,7 +2164,7 @@ async function handleAdminInteraction(args) {
|
|
|
2060
2164
|
if (interaction.action_id === "save_global") {
|
|
2061
2165
|
await saveGlobalSettingsFromValues(ctx, interaction.values);
|
|
2062
2166
|
return buildProvidersPage(ctx, variant, runtime, {
|
|
2063
|
-
message: "
|
|
2167
|
+
message: "Sender settings saved.",
|
|
2064
2168
|
type: "success"
|
|
2065
2169
|
});
|
|
2066
2170
|
}
|
|
@@ -2073,7 +2177,7 @@ async function handleAdminInteraction(args) {
|
|
|
2073
2177
|
});
|
|
2074
2178
|
}
|
|
2075
2179
|
if (interaction.action_id === "save_provider") {
|
|
2076
|
-
const provider = await getCurrentProvider(ctx, variant);
|
|
2180
|
+
const provider = await getCurrentProvider(ctx, variant, (await getGlobalSettings(ctx)).primaryProviderId);
|
|
2077
2181
|
await saveProviderSettingsFromValues(ctx, provider, interaction.values);
|
|
2078
2182
|
return buildProvidersPage(ctx, variant, runtime, {
|
|
2079
2183
|
message: `${provider.label} settings saved.`,
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":["numberValue","booleanValue","stringValue","numberValue","stripHtml"],"sources":["../src/storage.ts","../src/providers.ts","../src/delivery.ts","../src/admin.ts"],"sourcesContent":["import type {\n\tAdminInteraction,\n\tDeliveryLogRecord,\n\tGlobalSettings,\n\tLastTestResult,\n\tLogLevel,\n\tProviderDefinition,\n\tSmtpPluginContextLike,\n} from \"./types.js\";\n\nexport const GLOBAL_SETTINGS_KEY = \"settings:global\";\nexport const SELECTED_PROVIDER_KEY = \"state:selectedProviderId\";\nexport const LAST_TEST_RESULT_KEY = \"state:lastTestResult\";\n\nfunction providerSettingsKey(providerId: string): string {\n\treturn `settings:provider:${providerId}`;\n}\n\nfunction trimString(value: unknown): string | undefined {\n\tif (typeof value !== \"string\") return undefined;\n\tconst next = value.trim();\n\treturn next === \"\" ? undefined : next;\n}\n\nfunction numberValue(value: unknown): number | undefined {\n\tif (typeof value === \"number\" && Number.isFinite(value)) return value;\n\tif (typeof value === \"string\" && value.trim() !== \"\") {\n\t\tconst next = Number(value);\n\t\tif (Number.isFinite(next)) return next;\n\t}\n\treturn undefined;\n}\n\nfunction booleanValue(value: unknown): boolean {\n\tif (typeof value === \"boolean\") return value;\n\tif (typeof value === \"string\") {\n\t\treturn value === \"true\" || value === \"1\" || value === \"on\";\n\t}\n\treturn Boolean(value);\n}\n\nfunction normalizeLogLevel(value: unknown): LogLevel {\n\tif (value === \"errors\" || value === \"off\") return value;\n\treturn \"all\";\n}\n\nfunction cleanRecord(record: Record<string, unknown>): Record<string, unknown> {\n\treturn Object.fromEntries(Object.entries(record).filter(([, value]) => value !== undefined));\n}\n\nexport async function getGlobalSettings(ctx: SmtpPluginContextLike): Promise<GlobalSettings> {\n\tconst saved = (await ctx.kv.get<GlobalSettings>(GLOBAL_SETTINGS_KEY)) ?? {};\n\treturn {\n\t\tprimaryProviderId: trimString(saved.primaryProviderId),\n\t\tfallbackProviderId: trimString(saved.fallbackProviderId),\n\t\tfromEmail: trimString(saved.fromEmail),\n\t\tfromName: trimString(saved.fromName),\n\t\treplyTo: trimString(saved.replyTo),\n\t\tlogLevel: normalizeLogLevel(saved.logLevel),\n\t};\n}\n\nexport async function saveGlobalSettingsFromValues(\n\tctx: SmtpPluginContextLike,\n\tvalues: Record<string, unknown>,\n): Promise<GlobalSettings> {\n\tconst next: GlobalSettings = {\n\t\tprimaryProviderId: trimString(values.primaryProviderId),\n\t\tfallbackProviderId: trimString(values.fallbackProviderId),\n\t\tfromEmail: trimString(values.fromEmail),\n\t\tfromName: trimString(values.fromName),\n\t\treplyTo: trimString(values.replyTo),\n\t\tlogLevel: normalizeLogLevel(values.logLevel),\n\t};\n\tawait ctx.kv.set(GLOBAL_SETTINGS_KEY, next);\n\treturn next;\n}\n\nexport async function getProviderSettings(\n\tctx: SmtpPluginContextLike,\n\tproviderId: string,\n): Promise<Record<string, unknown>> {\n\treturn ((await ctx.kv.get<Record<string, unknown>>(providerSettingsKey(providerId))) ?? {}) as Record<\n\t\tstring,\n\t\tunknown\n\t>;\n}\n\nexport async function patchProviderSettings(\n\tctx: SmtpPluginContextLike,\n\tproviderId: string,\n\tpatch: Record<string, unknown>,\n): Promise<Record<string, unknown>> {\n\tconst current = await getProviderSettings(ctx, providerId);\n\tconst cleaned = cleanRecord({ ...current, ...patch });\n\tawait ctx.kv.set(providerSettingsKey(providerId), cleaned);\n\treturn cleaned;\n}\n\nexport async function saveProviderSettingsFromValues(\n\tctx: SmtpPluginContextLike,\n\tprovider: ProviderDefinition,\n\tvalues: Record<string, unknown>,\n): Promise<Record<string, unknown>> {\n\tconst existing = await getProviderSettings(ctx, provider.id);\n\tconst next: Record<string, unknown> = {};\n\n\tfor (const field of provider.fields) {\n\t\tconst raw = values[field.key];\n\t\tif (field.type === \"secret\") {\n\t\t\tconst secret = trimString(raw);\n\t\t\tif (secret !== undefined) {\n\t\t\t\tnext[field.key] = secret;\n\t\t\t} else if (existing[field.key] !== undefined) {\n\t\t\t\tnext[field.key] = existing[field.key];\n\t\t\t}\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (field.type === \"number\") {\n\t\t\tconst numeric = numberValue(raw);\n\t\t\tif (numeric !== undefined) next[field.key] = numeric;\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (field.type === \"toggle\") {\n\t\t\tnext[field.key] = booleanValue(raw);\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst text = trimString(raw);\n\t\tif (text !== undefined) next[field.key] = text;\n\t}\n\n\tconst cleaned = cleanRecord(next);\n\tawait ctx.kv.set(providerSettingsKey(provider.id), cleaned);\n\treturn cleaned;\n}\n\nexport async function clearProviderSecret(\n\tctx: SmtpPluginContextLike,\n\tproviderId: string,\n\tfieldKey: string,\n): Promise<void> {\n\tconst current = await getProviderSettings(ctx, providerId);\n\tconst next = { ...current };\n\tdelete next[fieldKey];\n\tawait ctx.kv.set(providerSettingsKey(providerId), cleanRecord(next));\n}\n\nexport async function getSelectedProviderId(\n\tctx: SmtpPluginContextLike,\n): Promise<string | undefined> {\n\treturn trimString(await ctx.kv.get<string>(SELECTED_PROVIDER_KEY));\n}\n\nexport async function setSelectedProviderId(\n\tctx: SmtpPluginContextLike,\n\tproviderId: string,\n): Promise<void> {\n\tawait ctx.kv.set(SELECTED_PROVIDER_KEY, providerId);\n}\n\nexport async function getLastTestResult(\n\tctx: SmtpPluginContextLike,\n): Promise<LastTestResult | null> {\n\treturn await ctx.kv.get<LastTestResult>(LAST_TEST_RESULT_KEY);\n}\n\nexport async function setLastTestResult(\n\tctx: SmtpPluginContextLike,\n\tresult: LastTestResult,\n): Promise<void> {\n\tawait ctx.kv.set(LAST_TEST_RESULT_KEY, result);\n}\n\nexport function createDeliveryLogRecord(\n\tinput: Omit<DeliveryLogRecord, \"createdAt\"> & { createdAt?: string },\n): DeliveryLogRecord {\n\treturn {\n\t\t...input,\n\t\tcreatedAt: input.createdAt ?? new Date().toISOString(),\n\t};\n}\n\nfunction createLogId(record: DeliveryLogRecord): string {\n\tconst base = record.createdAt.replace(/[^0-9]/g, \"\").slice(0, 14);\n\tconst random = Math.random().toString(36).slice(2, 10);\n\treturn `${base}-${record.providerId}-${random}`;\n}\n\nexport async function writeDeliveryLog(\n\tctx: SmtpPluginContextLike,\n\trecord: DeliveryLogRecord,\n): Promise<void> {\n\tconst collection = ctx.storage?.deliveryLogs;\n\tif (!collection?.put) return;\n\n\tconst settings = await getGlobalSettings(ctx);\n\tconst logLevel = settings.logLevel ?? \"all\";\n\tif (logLevel === \"off\") return;\n\tif (logLevel === \"errors\" && record.status !== \"failed\") return;\n\n\tconst id = record.id ?? createLogId(record);\n\tawait collection.put(id, { ...record, id });\n}\n\nexport async function queryRecentDeliveryLogs(\n\tctx: SmtpPluginContextLike,\n\tlimit = 25,\n): Promise<Array<{ id: string; data: DeliveryLogRecord }>> {\n\tconst collection = ctx.storage?.deliveryLogs;\n\tif (!collection?.query) return [];\n\tconst result = await collection.query({ orderBy: { createdAt: \"desc\" }, limit });\n\treturn result.items ?? [];\n}\n\nexport async function countDeliveryLogs(\n\tctx: SmtpPluginContextLike,\n\tstatus: \"sent\" | \"failed\",\n): Promise<number> {\n\tconst collection = ctx.storage?.deliveryLogs;\n\tif (collection?.count) {\n\t\treturn collection.count({ status });\n\t}\n\tif (!collection?.query) return 0;\n\tconst result = await collection.query({ where: { status }, limit: 1000 });\n\treturn result.items.length;\n}\n","import { patchProviderSettings } from \"./storage.js\";\nimport type {\n\tDeliveryMessage,\n\tDeliveryRuntime,\n\tPluginVariant,\n\tProviderDefinition,\n\tProviderFieldDefinition,\n\tProviderSendArgs,\n} from \"./types.js\";\n\nfunction unique(values: string[]): string[] {\n\treturn [...new Set(values.filter(Boolean))].sort();\n}\n\nfunction stringValue(settings: Record<string, unknown>, key: string): string | undefined {\n\tconst value = settings[key];\n\tif (typeof value !== \"string\") return undefined;\n\tconst trimmed = value.trim();\n\treturn trimmed === \"\" ? undefined : trimmed;\n}\n\nfunction numberValue(settings: Record<string, unknown>, key: string, fallback?: number): number | undefined {\n\tconst value = settings[key];\n\tif (typeof value === \"number\" && Number.isFinite(value)) return value;\n\tif (typeof value === \"string\" && value.trim() !== \"\") {\n\t\tconst parsed = Number(value);\n\t\tif (Number.isFinite(parsed)) return parsed;\n\t}\n\treturn fallback;\n}\n\nfunction requireString(settings: Record<string, unknown>, key: string, label: string): string {\n\tconst value = stringValue(settings, key);\n\tif (!value) {\n\t\tthrow new Error(`${label} is required.`);\n\t}\n\treturn value;\n}\n\nfunction sanitizeHeaderText(value: string): string {\n\treturn value.replace(/[\\r\\n]+/g, \" \").replace(/\\s+/g, \" \").trim();\n}\n\nfunction sanitizeEmailAddress(value: string, label: string): string {\n\tconst trimmed = value.trim();\n\tif (!trimmed) {\n\t\tthrow new Error(`${label} is required.`);\n\t}\n\tif (/[\\r\\n]/.test(trimmed)) {\n\t\tthrow new Error(`${label} contains invalid newline characters.`);\n\t}\n\treturn trimmed;\n}\n\nfunction encodeHeaderValue(value: string): string {\n\tconst sanitized = sanitizeHeaderText(value);\n\tif (/^[\\x20-\\x7E]*$/.test(sanitized) && !/[\",]/.test(sanitized)) {\n\t\treturn sanitized;\n\t}\n\treturn `=?UTF-8?B?${toBase64(new TextEncoder().encode(sanitized))}?=`;\n}\n\nfunction formatAddress(email: string, name?: string): string {\n\tconst safeEmail = sanitizeEmailAddress(email, \"Email address\");\n\tconst safeName = name ? encodeHeaderValue(name) : undefined;\n\treturn safeName ? `${safeName} <${safeEmail}>` : safeEmail;\n}\n\nfunction ensureFetch(runtime: DeliveryRuntime): NonNullable<DeliveryRuntime[\"fetch\"]> {\n\tif (!runtime.fetch) {\n\t\tthrow new Error(\"This provider requires network fetch support in the current runtime.\");\n\t}\n\treturn runtime.fetch;\n}\n\nfunction ensureSmtp(runtime: DeliveryRuntime): NonNullable<DeliveryRuntime[\"smtpSend\"]> {\n\tif (!runtime.smtpSend) {\n\t\tthrow new Error(\"Custom SMTP is only available in the trusted package.\");\n\t}\n\treturn runtime.smtpSend;\n}\n\nfunction ensureSendmail(runtime: DeliveryRuntime): NonNullable<DeliveryRuntime[\"sendmailSend\"]> {\n\tif (!runtime.sendmailSend) {\n\t\tthrow new Error(\"Local sendmail is only available in the trusted package.\");\n\t}\n\treturn runtime.sendmailSend;\n}\n\nasync function readResponse(response: Response): Promise<{ text: string; json?: unknown }> {\n\tconst text = await response.text();\n\ttry {\n\t\treturn { text, json: text ? JSON.parse(text) : undefined };\n\t} catch {\n\t\treturn { text };\n\t}\n}\n\nfunction asRecord(value: unknown): Record<string, unknown> | undefined {\n\treturn typeof value === \"object\" && value !== null ? (value as Record<string, unknown>) : undefined;\n}\n\nfunction asArray(value: unknown): unknown[] | undefined {\n\treturn Array.isArray(value) ? value : undefined;\n}\n\nfunction asString(value: unknown): string | undefined {\n\treturn typeof value === \"string\" ? value : undefined;\n}\n\nfunction getPath(value: unknown, ...path: Array<string | number>): unknown {\n\tlet current: unknown = value;\n\tfor (const segment of path) {\n\t\tif (typeof segment === \"number\") {\n\t\t\tconst items = asArray(current);\n\t\t\tif (!items) return undefined;\n\t\t\tcurrent = items[segment];\n\t\t\tcontinue;\n\t\t}\n\t\tconst record = asRecord(current);\n\t\tif (!record) return undefined;\n\t\tcurrent = record[segment];\n\t}\n\treturn current;\n}\n\nclass HttpError extends Error {\n\tstatus: number;\n\tbodyText: string;\n\tbodyJson?: unknown;\n\n\tconstructor(status: number, bodyText: string, bodyJson?: unknown) {\n\t\tsuper(bodyText || `HTTP ${status}`);\n\t\tthis.name = \"HttpError\";\n\t\tthis.status = status;\n\t\tthis.bodyText = bodyText;\n\t\tthis.bodyJson = bodyJson;\n\t}\n}\n\nfunction hasAllSettings(settings: Record<string, unknown>, keys: string[]): boolean {\n\treturn keys.every((key) => Boolean(stringValue(settings, key)));\n}\n\nfunction shouldRetryAfterRefresh(error: unknown): error is HttpError {\n\treturn error instanceof HttpError && (error.status === 401 || error.status === 403);\n}\n\nasync function refreshProviderAccessToken(\n\targs: ProviderSendArgs,\n\ttokenUrl: string,\n\tbody: URLSearchParams,\n\tlabel: string,\n): Promise<string> {\n\tconst { json } = await requestJson({\n\t\turl: tokenUrl,\n\t\truntime: args.runtime,\n\t\tok: [200],\n\t\tinit: {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: {\n\t\t\t\taccept: \"application/json\",\n\t\t\t\t\"content-type\": \"application/x-www-form-urlencoded\",\n\t\t\t},\n\t\t\tbody: body.toString(),\n\t\t},\n\t});\n\tconst accessToken = asString(getPath(json, \"access_token\"));\n\tif (!accessToken) {\n\t\tthrow new Error(`${label} refresh did not return an access token.`);\n\t}\n\tconst refreshToken = asString(getPath(json, \"refresh_token\"));\n\tawait patchProviderSettings(args.ctx, args.providerId, {\n\t\taccessToken,\n\t\t...(refreshToken ? { refreshToken } : {}),\n\t});\n\treturn accessToken;\n}\n\nasync function requestJson(opts: {\n\turl: string;\n\tinit: RequestInit;\n\truntime: DeliveryRuntime;\n\tok?: number[];\n}): Promise<{ response: Response; text: string; json?: unknown }> {\n\tconst fetchFn = ensureFetch(opts.runtime);\n\tconst response = await fetchFn(opts.url, opts.init);\n\tconst result = await readResponse(response);\n\tconst ok = opts.ok ?? [200, 201, 202];\n\tif (!ok.includes(response.status)) {\n\t\tthrow new HttpError(response.status, result.text || `HTTP ${response.status}`, result.json);\n\t}\n\treturn { response, ...result };\n}\n\nfunction toBase64(bytes: Uint8Array): string {\n\tif (typeof Buffer !== \"undefined\") {\n\t\treturn Buffer.from(bytes).toString(\"base64\");\n\t}\n\tlet binary = \"\";\n\tfor (const byte of bytes) binary += String.fromCharCode(byte);\n\treturn btoa(binary);\n}\n\nfunction toBase64Url(text: string): string {\n\tconst bytes = new TextEncoder().encode(text);\n\treturn toBase64(bytes).replace(/\\+/g, \"-\").replace(/\\//g, \"_\").replace(/=+$/g, \"\");\n}\n\nfunction toHex(bytes: Uint8Array): string {\n\treturn Array.from(bytes)\n\t\t.map((byte) => byte.toString(16).padStart(2, \"0\"))\n\t\t.join(\"\");\n}\n\nasync function sha256Hex(payload: string): Promise<string> {\n\tconst digest = await crypto.subtle.digest(\"SHA-256\", new TextEncoder().encode(payload));\n\treturn toHex(new Uint8Array(digest));\n}\n\nasync function hmacSha256Raw(key: string | Uint8Array, data: string): Promise<Uint8Array> {\n\tconst rawKey = typeof key === \"string\" ? new TextEncoder().encode(key) : Uint8Array.from(key);\n\tconst imported = await crypto.subtle.importKey(\n\t\t\"raw\",\n\t\trawKey.buffer,\n\t\t{ name: \"HMAC\", hash: \"SHA-256\" },\n\t\tfalse,\n\t\t[\"sign\"],\n\t);\n\tconst signature = await crypto.subtle.sign(\"HMAC\", imported, new TextEncoder().encode(data));\n\treturn new Uint8Array(signature);\n}\n\nfunction stripHtml(html: string): string {\n\treturn html\n\t\t.replace(/<style[\\s\\S]*?<\\/style>/gi, \"\")\n\t\t.replace(/<script[\\s\\S]*?<\\/script>/gi, \"\")\n\t\t.replace(/<[^>]+>/g, \" \")\n\t\t.replace(/\\s+/g, \" \")\n\t\t.trim();\n}\n\nfunction buildMimeMessage(message: DeliveryMessage): string {\n\tconst from = formatAddress(message.fromEmail || \"\", message.fromName);\n\tconst to = message.to.map((email) => sanitizeEmailAddress(email, \"Recipient email address\")).join(\", \");\n\tconst replyTo = message.replyTo?.length\n\t\t? message.replyTo.map((email) => sanitizeEmailAddress(email, \"Reply-to email address\")).join(\", \")\n\t\t: undefined;\n\tconst subject = encodeHeaderValue(message.subject);\n\tconst headers = [\n\t\t`From: ${from}`,\n\t\t`To: ${to}`,\n\t\t`Subject: ${subject}`,\n\t\t...(replyTo ? [`Reply-To: ${replyTo}`] : []),\n\t\t\"MIME-Version: 1.0\",\n\t];\n\n\tif (message.html) {\n\t\tconst boundary = `emdash-${Math.random().toString(36).slice(2, 12)}`;\n\t\treturn [\n\t\t\t...headers,\n\t\t\t`Content-Type: multipart/alternative; boundary=\"${boundary}\"`,\n\t\t\t\"\",\n\t\t\t`--${boundary}`,\n\t\t\t'Content-Type: text/plain; charset=\"UTF-8\"',\n\t\t\t\"\",\n\t\t\tmessage.text,\n\t\t\t\"\",\n\t\t\t`--${boundary}`,\n\t\t\t'Content-Type: text/html; charset=\"UTF-8\"',\n\t\t\t\"\",\n\t\t\tmessage.html,\n\t\t\t\"\",\n\t\t\t`--${boundary}--`,\n\t\t\t\"\",\n\t\t].join(\"\\r\\n\");\n\t}\n\n\treturn [\n\t\t...headers,\n\t\t'Content-Type: text/plain; charset=\"UTF-8\"',\n\t\t\"\",\n\t\tmessage.text,\n\t\t\"\",\n\t].join(\"\\r\\n\");\n}\n\nasync function signAwsRequest(opts: {\n\taccessKeyId: string;\n\tsecretAccessKey: string;\n\tregion: string;\n\turl: URL;\n\tmethod: string;\n\tpayload: string;\n\theaders?: Record<string, string>;\n}): Promise<Record<string, string>> {\n\tconst now = new Date();\n\tconst amzDate = now.toISOString().replace(/[:-]|\\.\\d{3}/g, \"\");\n\tconst dateStamp = amzDate.slice(0, 8);\n\tconst service = \"ses\";\n\tconst payloadHash = await sha256Hex(opts.payload);\n\tconst baseHeaders: Record<string, string> = {\n\t\t\"content-type\": \"application/x-www-form-urlencoded; charset=utf-8\",\n\t\t\"host\": opts.url.host,\n\t\t\"x-amz-content-sha256\": payloadHash,\n\t\t\"x-amz-date\": amzDate,\n\t\t...(opts.headers ?? {}),\n\t};\n\tconst sortedHeaderKeys = Object.keys(baseHeaders).sort();\n\tconst canonicalHeaders = sortedHeaderKeys\n\t\t.map((key) => `${key}:${(baseHeaders[key] ?? \"\").trim()}\\n`)\n\t\t.join(\"\");\n\tconst signedHeaders = sortedHeaderKeys.join(\";\");\n\tconst canonicalRequest = [\n\t\topts.method,\n\t\topts.url.pathname || \"/\",\n\t\topts.url.search.startsWith(\"?\") ? opts.url.search.slice(1) : opts.url.search,\n\t\tcanonicalHeaders,\n\t\tsignedHeaders,\n\t\tpayloadHash,\n\t].join(\"\\n\");\n\tconst credentialScope = `${dateStamp}/${opts.region}/${service}/aws4_request`;\n\tconst stringToSign = [\n\t\t\"AWS4-HMAC-SHA256\",\n\t\tamzDate,\n\t\tcredentialScope,\n\t\tawait sha256Hex(canonicalRequest),\n\t].join(\"\\n\");\n\tconst kDate = await hmacSha256Raw(`AWS4${opts.secretAccessKey}`, dateStamp);\n\tconst kRegion = await hmacSha256Raw(kDate, opts.region);\n\tconst kService = await hmacSha256Raw(kRegion, service);\n\tconst kSigning = await hmacSha256Raw(kService, \"aws4_request\");\n\tconst signature = toHex(await hmacSha256Raw(kSigning, stringToSign));\n\treturn {\n\t\t...baseHeaders,\n\t\tAuthorization: `AWS4-HMAC-SHA256 Credential=${opts.accessKeyId}/${credentialScope}, SignedHeaders=${signedHeaders}, Signature=${signature}`,\n\t};\n}\n\nfunction getMessageText(message: DeliveryMessage): string {\n\treturn message.text || (message.html ? stripHtml(message.html) : \"\");\n}\n\nasync function sendViaAmazon(args: ProviderSendArgs): Promise<{ remoteMessageId?: string }> {\n\tconst accessKeyId = requireString(args.settings, \"accessKeyId\", \"Access Key ID\");\n\tconst secretAccessKey = requireString(args.settings, \"secretAccessKey\", \"Secret Access Key\");\n\tconst region = requireString(args.settings, \"region\", \"Region\");\n\tconst payload = new URLSearchParams({\n\t\tAction: \"SendRawEmail\",\n\t\tVersion: \"2010-12-01\",\n\t\t\"RawMessage.Data\": toBase64(new TextEncoder().encode(buildMimeMessage(args.message))),\n\t}).toString();\n\tconst url = new URL(`https://email.${region}.amazonaws.com/`);\n\tconst headers = await signAwsRequest({\n\t\taccessKeyId,\n\t\tsecretAccessKey,\n\t\tregion,\n\t\turl,\n\t\tmethod: \"POST\",\n\t\tpayload,\n\t});\n\tconst { text } = await requestJson({\n\t\turl: url.toString(),\n\t\truntime: args.runtime,\n\t\tok: [200],\n\t\tinit: { method: \"POST\", headers, body: payload },\n\t});\n\tconst match = text.match(/<MessageId>([^<]+)<\\/MessageId>/i);\n\treturn { remoteMessageId: match?.[1] };\n}\n\nasync function sendViaBrevo(args: ProviderSendArgs): Promise<{ remoteMessageId?: string }> {\n\tconst apiKey = requireString(args.settings, \"apiKey\", \"API Key\");\n\tconst body: Record<string, unknown> = {\n\t\tsender: {\n\t\t\temail: args.message.fromEmail,\n\t\t\t...(args.message.fromName ? { name: args.message.fromName } : {}),\n\t\t},\n\t\tto: args.message.to.map((email) => ({ email })),\n\t\tsubject: args.message.subject,\n\t\t...(args.message.html ? { htmlContent: args.message.html } : { textContent: args.message.text }),\n\t\t...(args.message.replyTo?.[0] ? { replyTo: { email: args.message.replyTo[0] } } : {}),\n\t};\n\tconst { json } = await requestJson({\n\t\turl: \"https://api.brevo.com/v3/smtp/email\",\n\t\truntime: args.runtime,\n\t\tinit: {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: {\n\t\t\t\taccept: \"application/json\",\n\t\t\t\t\"content-type\": \"application/json\",\n\t\t\t\t\"api-key\": apiKey,\n\t\t\t},\n\t\t\tbody: JSON.stringify(body),\n\t\t},\n\t});\n\tconst record = asRecord(json);\n\treturn { remoteMessageId: asString(record?.messageId) };\n}\n\nasync function sendViaElasticEmail(args: ProviderSendArgs): Promise<{ remoteMessageId?: string }> {\n\tconst apiKey = requireString(args.settings, \"apiKey\", \"API Key\");\n\tconst body: Record<string, unknown> = {\n\t\tRecipients: { To: [...args.message.to] },\n\t\tContent: {\n\t\t\tFrom: formatAddress(args.message.fromEmail || \"\", args.message.fromName),\n\t\t\tSubject: args.message.subject,\n\t\t\tBody: [\n\t\t\t\t{\n\t\t\t\t\tCharset: \"utf-8\",\n\t\t\t\t\tContent: args.message.html || args.message.text,\n\t\t\t\t\tContentType: args.message.html ? \"HTML\" : \"PlainText\",\n\t\t\t\t},\n\t\t\t],\n\t\t\t...(args.message.replyTo?.[0] ? { ReplyTo: args.message.replyTo[0] } : {}),\n\t\t},\n\t};\n\tconst { json } = await requestJson({\n\t\turl: \"https://api.elasticemail.com/v4/emails/transactional\",\n\t\truntime: args.runtime,\n\t\tinit: {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: {\n\t\t\t\taccept: \"application/json\",\n\t\t\t\t\"content-type\": \"application/json\",\n\t\t\t\t\"X-ElasticEmail-ApiKey\": apiKey,\n\t\t\t},\n\t\t\tbody: JSON.stringify(body),\n\t\t},\n\t});\n\tconst record = asRecord(json);\n\treturn { remoteMessageId: asString(record?.TransactionID) ?? asString(record?.MessageID) };\n}\n\nasync function sendViaEmailit(args: ProviderSendArgs): Promise<{ remoteMessageId?: string }> {\n\tconst apiKey = requireString(args.settings, \"apiKey\", \"API Key\");\n\tconst body: Record<string, unknown> = {\n\t\tto: args.message.to.join(\", \"),\n\t\tfrom: formatAddress(args.message.fromEmail || \"\", args.message.fromName),\n\t\tsubject: args.message.subject,\n\t\theaders: {\n\t\t\t...(args.message.replyTo?.[0] ? { \"reply-to\": args.message.replyTo[0] } : {}),\n\t\t},\n\t\t...(args.message.html\n\t\t\t? { html: args.message.html, text: getMessageText(args.message) }\n\t\t\t: { text: args.message.text }),\n\t};\n\tconst { json } = await requestJson({\n\t\turl: \"https://api.emailit.com/v1/emails\",\n\t\truntime: args.runtime,\n\t\tinit: {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: {\n\t\t\t\taccept: \"application/json\",\n\t\t\t\t\"content-type\": \"application/json\",\n\t\t\t\tAuthorization: `Bearer ${apiKey}`,\n\t\t\t},\n\t\t\tbody: JSON.stringify(body),\n\t\t},\n\t});\n\tconst record = asRecord(json);\n\treturn { remoteMessageId: asString(record?.id) ?? asString(record?.message_id) };\n}\n\nasync function sendViaGenericSmtp(args: ProviderSendArgs): Promise<{ remoteMessageId?: string }> {\n\tconst smtpSend = ensureSmtp(args.runtime);\n\tconst host = requireString(args.settings, \"host\", \"SMTP Hostname\");\n\tconst port = numberValue(args.settings, \"port\", 587) ?? 587;\n\tconst security = stringValue(args.settings, \"security\") ?? \"starttls\";\n\treturn smtpSend(\n\t\t{\n\t\t\thost,\n\t\t\tport,\n\t\t\tsecure: security === \"ssl\",\n\t\t\tusername: stringValue(args.settings, \"username\"),\n\t\t\tpassword: stringValue(args.settings, \"password\"),\n\t\t},\n\t\targs.message,\n\t);\n}\n\nasync function resolveGoogleAccessToken(args: ProviderSendArgs, forceRefresh = false): Promise<string> {\n\tconst storedAccessToken = forceRefresh ? undefined : stringValue(args.settings, \"accessToken\");\n\tif (storedAccessToken) return storedAccessToken;\n\tif (!hasAllSettings(args.settings, [\"clientId\", \"clientSecret\", \"refreshToken\"])) {\n\t\tthrow new Error(\"Google requires an access token or client ID, client secret, and refresh token.\");\n\t}\n\treturn refreshProviderAccessToken(\n\t\targs,\n\t\t\"https://oauth2.googleapis.com/token\",\n\t\tnew URLSearchParams({\n\t\t\tclient_id: requireString(args.settings, \"clientId\", \"Client ID\"),\n\t\t\tclient_secret: requireString(args.settings, \"clientSecret\", \"Client Secret\"),\n\t\t\trefresh_token: requireString(args.settings, \"refreshToken\", \"Refresh Token\"),\n\t\t\tgrant_type: \"refresh_token\",\n\t\t}),\n\t\t\"Google\",\n\t);\n}\n\nasync function resolveMicrosoftAccessToken(args: ProviderSendArgs, forceRefresh = false): Promise<string> {\n\tconst storedAccessToken = forceRefresh ? undefined : stringValue(args.settings, \"accessToken\");\n\tif (storedAccessToken) return storedAccessToken;\n\tif (!hasAllSettings(args.settings, [\"clientId\", \"clientSecret\", \"refreshToken\"])) {\n\t\tthrow new Error(\"Microsoft requires an access token or application ID, client secret, and refresh token.\");\n\t}\n\tconst tenantId = stringValue(args.settings, \"tenantId\") ?? \"common\";\n\treturn refreshProviderAccessToken(\n\t\targs,\n\t\t`https://login.microsoftonline.com/${tenantId}/oauth2/v2.0/token`,\n\t\tnew URLSearchParams({\n\t\t\tclient_id: requireString(args.settings, \"clientId\", \"Application ID\"),\n\t\t\tclient_secret: requireString(args.settings, \"clientSecret\", \"Client Secret\"),\n\t\t\trefresh_token: requireString(args.settings, \"refreshToken\", \"Refresh Token\"),\n\t\t\tgrant_type: \"refresh_token\",\n\t\t\tscope: \"email Mail.Send User.Read profile openid offline_access\",\n\t\t}),\n\t\t\"Microsoft\",\n\t);\n}\n\nasync function resolveZohoAccessToken(args: ProviderSendArgs, forceRefresh = false): Promise<string> {\n\tconst storedAccessToken = forceRefresh ? undefined : stringValue(args.settings, \"accessToken\");\n\tif (storedAccessToken) return storedAccessToken;\n\tif (!hasAllSettings(args.settings, [\"clientId\", \"clientSecret\", \"refreshToken\"])) {\n\t\tthrow new Error(\"Zoho requires an access token or client ID, client secret, and refresh token.\");\n\t}\n\tconst body = new URLSearchParams({\n\t\tclient_id: requireString(args.settings, \"clientId\", \"Client ID\"),\n\t\tclient_secret: requireString(args.settings, \"clientSecret\", \"Client Secret\"),\n\t\trefresh_token: requireString(args.settings, \"refreshToken\", \"Refresh Token\"),\n\t\tgrant_type: \"refresh_token\",\n\t});\n\tconst redirectUri = stringValue(args.settings, \"redirectUri\");\n\tif (redirectUri) body.set(\"redirect_uri\", redirectUri);\n\treturn refreshProviderAccessToken(args, \"https://accounts.zoho.com/oauth/v2/token\", body, \"Zoho\");\n}\n\nasync function sendViaGoogle(args: ProviderSendArgs): Promise<{ remoteMessageId?: string }> {\n\tconst raw = toBase64Url(buildMimeMessage(args.message));\n\tconst sendRequest = async (accessToken: string) => {\n\t\tconst { json } = await requestJson({\n\t\t\turl: \"https://gmail.googleapis.com/gmail/v1/users/me/messages/send\",\n\t\t\truntime: args.runtime,\n\t\t\tinit: {\n\t\t\t\tmethod: \"POST\",\n\t\t\t\theaders: {\n\t\t\t\t\tAuthorization: `Bearer ${accessToken}`,\n\t\t\t\t\t\"Content-Type\": \"application/json\",\n\t\t\t\t},\n\t\t\t\tbody: JSON.stringify({ raw }),\n\t\t\t},\n\t\t\tok: [200],\n\t\t});\n\t\tconst record = asRecord(json);\n\t\treturn { remoteMessageId: asString(record?.id) };\n\t};\n\tconst canRefresh = hasAllSettings(args.settings, [\"clientId\", \"clientSecret\", \"refreshToken\"]);\n\ttry {\n\t\treturn await sendRequest(await resolveGoogleAccessToken(args));\n\t} catch (error) {\n\t\tif (!canRefresh || !shouldRetryAfterRefresh(error)) throw error;\n\t\treturn sendRequest(await resolveGoogleAccessToken(args, true));\n\t}\n}\n\nasync function sendViaMailchimp(args: ProviderSendArgs): Promise<{ remoteMessageId?: string }> {\n\tconst apiKey = requireString(args.settings, \"apiKey\", \"API Key\");\n\tconst body = {\n\t\tkey: apiKey,\n\t\tmessage: {\n\t\t\tsubject: args.message.subject,\n\t\t\tfrom_email: args.message.fromEmail,\n\t\t\t...(args.message.fromName ? { from_name: args.message.fromName } : {}),\n\t\t\tto: args.message.to.map((email) => ({ email, type: \"to\" })),\n\t\t\t...(args.message.html\n\t\t\t\t? { html: args.message.html, text: getMessageText(args.message) }\n\t\t\t\t: { text: args.message.text }),\n\t\t\t...(args.message.replyTo?.[0] ? { headers: { \"reply-to\": args.message.replyTo[0] } } : {}),\n\t\t},\n\t};\n\tconst { json } = await requestJson({\n\t\turl: \"https://mandrillapp.com/api/1.0/messages/send\",\n\t\truntime: args.runtime,\n\t\tinit: {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: { \"Content-Type\": \"application/json\" },\n\t\t\tbody: JSON.stringify(body),\n\t\t},\n\t});\n\tconst data = Array.isArray(json) ? json[0] : json;\n\tconst record = asRecord(data);\n\treturn { remoteMessageId: asString(record?._id) ?? asString(record?.id) };\n}\n\nasync function sendViaMailerSend(args: ProviderSendArgs): Promise<{ remoteMessageId?: string }> {\n\tconst apiKey = requireString(args.settings, \"apiKey\", \"API Key\");\n\tconst body: Record<string, unknown> = {\n\t\tsubject: args.message.subject,\n\t\tfrom: {\n\t\t\temail: args.message.fromEmail,\n\t\t\t...(args.message.fromName ? { name: args.message.fromName } : {}),\n\t\t},\n\t\tto: args.message.to.map((email) => ({ email })),\n\t\t...(args.message.html ? { html: args.message.html } : { text: args.message.text }),\n\t\t...(args.message.replyTo?.[0] ? { reply_to: { email: args.message.replyTo[0] } } : {}),\n\t};\n\tconst { json } = await requestJson({\n\t\turl: \"https://api.mailersend.com/v1/email\",\n\t\truntime: args.runtime,\n\t\tinit: {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: {\n\t\t\t\taccept: \"application/json\",\n\t\t\t\t\"content-type\": \"application/json\",\n\t\t\t\tAuthorization: `Bearer ${apiKey}`,\n\t\t\t},\n\t\t\tbody: JSON.stringify(body),\n\t\t},\n\t});\n\tconst record = asRecord(json);\n\treturn { remoteMessageId: asString(record?.message_id) ?? asString(record?.id) };\n}\n\nasync function sendViaMailgun(args: ProviderSendArgs): Promise<{ remoteMessageId?: string }> {\n\tconst apiKey = requireString(args.settings, \"apiKey\", \"Mailgun API Key\");\n\tconst domain = requireString(args.settings, \"domain\", \"Sending Domain\");\n\tconst region = stringValue(args.settings, \"region\") ?? \"us\";\n\tconst base = region === \"eu\" ? \"https://api.eu.mailgun.net/v3\" : \"https://api.mailgun.net/v3\";\n\tconst body = new URLSearchParams({\n\t\tfrom: formatAddress(args.message.fromEmail || \"\", args.message.fromName),\n\t\tto: args.message.to.join(\", \"),\n\t\tsubject: args.message.subject,\n\t\t...(args.message.html ? { html: args.message.html } : {}),\n\t\ttext: getMessageText(args.message),\n\t});\n\tif (args.message.replyTo?.[0]) body.set(\"h:Reply-To\", args.message.replyTo[0]);\n\tconst basic = toBase64(new TextEncoder().encode(`api:${apiKey}`));\n\tconst { json } = await requestJson({\n\t\turl: `${base}/${domain}/messages`,\n\t\truntime: args.runtime,\n\t\tinit: {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: { Authorization: `Basic ${basic}` },\n\t\t\tbody: body,\n\t\t},\n\t\tok: [200],\n\t});\n\tconst record = asRecord(json);\n\treturn { remoteMessageId: asString(record?.id) };\n}\n\nasync function sendViaMailjet(args: ProviderSendArgs): Promise<{ remoteMessageId?: string }> {\n\tconst apiKey = requireString(args.settings, \"apiKey\", \"API Key\");\n\tconst apiSecret = requireString(args.settings, \"apiSecret\", \"API Secret Key\");\n\tconst body = {\n\t\tMessages: [\n\t\t\t{\n\t\t\t\tTo: args.message.to.map((email) => ({ Email: email })),\n\t\t\t\tFrom: {\n\t\t\t\t\tEmail: args.message.fromEmail,\n\t\t\t\t\t...(args.message.fromName ? { Name: args.message.fromName } : {}),\n\t\t\t\t},\n\t\t\t\tSubject: args.message.subject,\n\t\t\t\t...(args.message.html\n\t\t\t\t\t? { HTMLPart: args.message.html, TextPart: getMessageText(args.message) }\n\t\t\t\t\t: { TextPart: args.message.text }),\n\t\t\t\t...(args.message.replyTo?.[0]\n\t\t\t\t\t? { Headers: { \"Reply-To\": args.message.replyTo[0] } }\n\t\t\t\t\t: {}),\n\t\t\t},\n\t\t],\n\t};\n\tconst basic = toBase64(new TextEncoder().encode(`${apiKey}:${apiSecret}`));\n\tconst { json } = await requestJson({\n\t\turl: \"https://api.mailjet.com/v3.1/send\",\n\t\truntime: args.runtime,\n\t\tinit: {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: {\n\t\t\t\taccept: \"application/json\",\n\t\t\t\t\"content-type\": \"application/json\",\n\t\t\t\tAuthorization: `Basic ${basic}`,\n\t\t\t},\n\t\t\tbody: JSON.stringify(body),\n\t\t},\n\t});\n\tconst record = asRecord(json);\n\treturn { remoteMessageId: asString(getPath(record, \"Messages\", 0, \"To\", 0, \"MessageUUID\")) };\n}\n\nasync function sendViaMicrosoft(args: ProviderSendArgs): Promise<{ remoteMessageId?: string }> {\n\tconst sendRequest = async (accessToken: string) => {\n\t\tawait requestJson({\n\t\t\turl: \"https://graph.microsoft.com/v1.0/me/sendMail\",\n\t\t\truntime: args.runtime,\n\t\t\tok: [202],\n\t\t\tinit: {\n\t\t\t\tmethod: \"POST\",\n\t\t\t\theaders: {\n\t\t\t\t\tAuthorization: `Bearer ${accessToken}`,\n\t\t\t\t\t\"content-type\": \"application/json\",\n\t\t\t\t},\n\t\t\t\tbody: JSON.stringify({\n\t\t\t\t\tmessage: {\n\t\t\t\t\t\tsubject: args.message.subject,\n\t\t\t\t\t\tbody: {\n\t\t\t\t\t\t\tcontentType: args.message.html ? \"HTML\" : \"Text\",\n\t\t\t\t\t\t\tcontent: args.message.html || args.message.text,\n\t\t\t\t\t\t},\n\t\t\t\t\t\ttoRecipients: args.message.to.map((email) => ({ emailAddress: { address: email } })),\n\t\t\t\t\t\t...(args.message.replyTo?.[0]\n\t\t\t\t\t\t\t? { replyTo: [{ emailAddress: { address: args.message.replyTo[0] } }] }\n\t\t\t\t\t\t\t: {}),\n\t\t\t\t\t},\n\t\t\t\t\tsaveToSentItems: false,\n\t\t\t\t}),\n\t\t\t},\n\t\t});\n\t\treturn {};\n\t};\n\tconst canRefresh = hasAllSettings(args.settings, [\"clientId\", \"clientSecret\", \"refreshToken\"]);\n\ttry {\n\t\treturn await sendRequest(await resolveMicrosoftAccessToken(args));\n\t} catch (error) {\n\t\tif (!canRefresh || !shouldRetryAfterRefresh(error)) throw error;\n\t\treturn sendRequest(await resolveMicrosoftAccessToken(args, true));\n\t}\n}\n\nasync function sendViaPhpMail(args: ProviderSendArgs): Promise<{ remoteMessageId?: string }> {\n\tconst sendmailSend = ensureSendmail(args.runtime);\n\treturn sendmailSend(\n\t\t{\n\t\t\tsendmailPath: stringValue(args.settings, \"sendmailPath\") ?? \"sendmail\",\n\t\t\tfromEmail: args.message.fromEmail || \"\",\n\t\t\tfromName: args.message.fromName,\n\t\t},\n\t\targs.message,\n\t);\n}\n\nasync function sendViaPostmark(args: ProviderSendArgs): Promise<{ remoteMessageId?: string }> {\n\tconst serverApiToken = requireString(args.settings, \"serverApiToken\", \"Server API Token\");\n\tconst body: Record<string, unknown> = {\n\t\tfrom: formatAddress(args.message.fromEmail || \"\", args.message.fromName),\n\t\tto: args.message.to.join(\",\"),\n\t\tsubject: args.message.subject,\n\t\ttextBody: getMessageText(args.message),\n\t\t...(args.message.html ? { htmlBody: args.message.html } : {}),\n\t\t...(args.message.replyTo?.[0] ? { ReplyTo: args.message.replyTo[0] } : {}),\n\t};\n\tconst { json } = await requestJson({\n\t\turl: \"https://api.postmarkapp.com/email\",\n\t\truntime: args.runtime,\n\t\tok: [200],\n\t\tinit: {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: {\n\t\t\t\tAccept: \"application/json\",\n\t\t\t\t\"Content-Type\": \"application/json\",\n\t\t\t\t\"X-Postmark-Server-Token\": serverApiToken,\n\t\t\t},\n\t\t\tbody: JSON.stringify(body),\n\t\t},\n\t});\n\tconst record = asRecord(json);\n\treturn { remoteMessageId: asString(record?.MessageID) };\n}\n\nasync function sendViaResend(args: ProviderSendArgs): Promise<{ remoteMessageId?: string }> {\n\tconst apiKey = requireString(args.settings, \"apiKey\", \"API Key\");\n\tconst body: Record<string, unknown> = {\n\t\tto: [...args.message.to],\n\t\tfrom: formatAddress(args.message.fromEmail || \"\", args.message.fromName),\n\t\tsubject: args.message.subject,\n\t\t...(args.message.html\n\t\t\t? { html: args.message.html, text: getMessageText(args.message) }\n\t\t\t: { text: args.message.text }),\n\t\t...(args.message.replyTo?.[0] ? { reply_to: args.message.replyTo[0] } : {}),\n\t};\n\tconst { json } = await requestJson({\n\t\turl: \"https://api.resend.com/emails\",\n\t\truntime: args.runtime,\n\t\tinit: {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: {\n\t\t\t\taccept: \"application/json\",\n\t\t\t\t\"content-type\": \"application/json\",\n\t\t\t\tAuthorization: `Bearer ${apiKey}`,\n\t\t\t},\n\t\t\tbody: JSON.stringify(body),\n\t\t},\n\t});\n\tconst record = asRecord(json);\n\treturn { remoteMessageId: asString(record?.id) };\n}\n\nasync function sendViaSendgrid(args: ProviderSendArgs): Promise<{ remoteMessageId?: string }> {\n\tconst apiKey = requireString(args.settings, \"apiKey\", \"SendGrid API Key\");\n\tawait requestJson({\n\t\turl: \"https://api.sendgrid.com/v3/mail/send\",\n\t\truntime: args.runtime,\n\t\tok: [202],\n\t\tinit: {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: {\n\t\t\t\tAuthorization: `Bearer ${apiKey}`,\n\t\t\t\t\"Content-Type\": \"application/json\",\n\t\t\t},\n\t\t\tbody: JSON.stringify({\n\t\t\t\tfrom: {\n\t\t\t\t\temail: args.message.fromEmail,\n\t\t\t\t\t...(args.message.fromName ? { name: args.message.fromName } : {}),\n\t\t\t\t},\n\t\t\t\tpersonalizations: [\n\t\t\t\t\t{\n\t\t\t\t\t\tto: args.message.to.map((email) => ({ email })),\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\tsubject: args.message.subject,\n\t\t\t\tcontent: [\n\t\t\t\t\t{\n\t\t\t\t\t\ttype: args.message.html ? \"text/html\" : \"text/plain\",\n\t\t\t\t\t\tvalue: args.message.html || args.message.text,\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\t...(args.message.replyTo?.length\n\t\t\t\t\t? { reply_to_list: args.message.replyTo.map((email) => ({ email })) }\n\t\t\t\t\t: {}),\n\t\t\t}),\n\t\t},\n\t});\n\treturn {};\n}\n\nasync function sendViaSmtp2go(args: ProviderSendArgs): Promise<{ remoteMessageId?: string }> {\n\tconst apiKey = requireString(args.settings, \"apiKey\", \"API Key\");\n\tconst body: Record<string, unknown> = {\n\t\tsender: formatAddress(args.message.fromEmail || \"\", args.message.fromName),\n\t\tsubject: args.message.subject,\n\t\tto: [...args.message.to],\n\t\t...(args.message.html ? { html_body: args.message.html } : { text_body: args.message.text }),\n\t};\n\tif (args.message.replyTo?.[0]) {\n\t\tbody.custom_headers = [{ header: \"Reply-To\", value: args.message.replyTo[0] }];\n\t}\n\tconst { json } = await requestJson({\n\t\turl: \"https://api.smtp2go.com/v3/email/send\",\n\t\truntime: args.runtime,\n\t\tinit: {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: {\n\t\t\t\taccept: \"application/json\",\n\t\t\t\t\"content-type\": \"application/json\",\n\t\t\t\t\"X-Smtp2go-Api-Key\": apiKey,\n\t\t\t},\n\t\t\tbody: JSON.stringify(body),\n\t\t},\n\t});\n\tconst record = asRecord(json);\n\treturn { remoteMessageId: asString(getPath(record, \"data\", \"email_id\")) ?? asString(record?.request_id) };\n}\n\nasync function sendViaSparkpost(args: ProviderSendArgs): Promise<{ remoteMessageId?: string }> {\n\tconst apiKey = requireString(args.settings, \"apiKey\", \"API Key\");\n\tconst accountLocation = stringValue(args.settings, \"accountLocation\") ?? \"us\";\n\tconst base = accountLocation === \"eu\"\n\t\t? \"https://api.eu.sparkpost.com/api/v1\"\n\t\t: \"https://api.sparkpost.com/api/v1\";\n\tconst body: Record<string, unknown> = {\n\t\trecipients: args.message.to.map((email) => ({ address: { email } })),\n\t\tcontent: {\n\t\t\tfrom: {\n\t\t\t\temail: args.message.fromEmail,\n\t\t\t\t...(args.message.fromName ? { name: args.message.fromName } : {}),\n\t\t\t},\n\t\t\tsubject: args.message.subject,\n\t\t\t...(args.message.html ? { html: args.message.html } : { text: args.message.text }),\n\t\t\t...(args.message.replyTo?.[0] ? { reply_to: args.message.replyTo[0] } : {}),\n\t\t},\n\t\toptions: { transactional: true },\n\t};\n\tconst { json } = await requestJson({\n\t\turl: `${base}/transmissions/`,\n\t\truntime: args.runtime,\n\t\tinit: {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: {\n\t\t\t\taccept: \"application/json\",\n\t\t\t\t\"content-type\": \"application/json\",\n\t\t\t\tAuthorization: apiKey,\n\t\t\t},\n\t\t\tbody: JSON.stringify(body),\n\t\t},\n\t});\n\tconst record = asRecord(json);\n\treturn { remoteMessageId: asString(getPath(record, \"results\", \"id\")) };\n}\n\nfunction getZohoBaseUrl(region: string): string {\n\tswitch (region) {\n\t\tcase \"eu\":\n\t\t\treturn \"https://mail.zoho.eu\";\n\t\tcase \"in\":\n\t\t\treturn \"https://mail.zoho.in\";\n\t\tcase \"com.au\":\n\t\t\treturn \"https://mail.zoho.com.au\";\n\t\tcase \"jp\":\n\t\t\treturn \"https://mail.zoho.jp\";\n\t\tcase \"sa\":\n\t\t\treturn \"https://mail.zoho.sa\";\n\t\tcase \"ca\":\n\t\t\treturn \"https://mail.zohocloud.ca\";\n\t\tcase \"us\":\n\t\tdefault:\n\t\t\treturn \"https://mail.zoho.com\";\n\t}\n}\n\nasync function sendViaZoho(args: ProviderSendArgs): Promise<{ remoteMessageId?: string }> {\n\tconst accountId = requireString(args.settings, \"accountId\", \"Account ID\");\n\tconst region = stringValue(args.settings, \"dataCenterRegion\") ?? \"us\";\n\tconst body: Record<string, unknown> = {\n\t\tfromAddress: args.message.fromEmail,\n\t\ttoAddress: args.message.to.join(\",\"),\n\t\tsubject: args.message.subject,\n\t\tcontent: args.message.html || args.message.text,\n\t\tencoding: \"UTF-8\",\n\t\tmailFormat: args.message.html ? \"html\" : \"plaintext\",\n\t\t...(args.message.replyTo?.[0] ? { replyToAddress: args.message.replyTo[0] } : {}),\n\t};\n\tconst sendRequest = async (accessToken: string) => {\n\t\tconst { json } = await requestJson({\n\t\t\turl: `${getZohoBaseUrl(region)}/api/accounts/${accountId}/messages`,\n\t\t\truntime: args.runtime,\n\t\t\tinit: {\n\t\t\t\tmethod: \"POST\",\n\t\t\t\theaders: {\n\t\t\t\t\tAuthorization: `Zoho-oauthtoken ${accessToken}`,\n\t\t\t\t\t\"Content-Type\": \"application/json\",\n\t\t\t\t},\n\t\t\t\tbody: JSON.stringify(body),\n\t\t\t},\n\t\t});\n\t\tconst record = asRecord(json);\n\t\treturn {\n\t\t\tremoteMessageId:\n\t\t\t\tasString(getPath(record, \"data\", \"messageId\")) ?? asString(getPath(record, \"data\", \"message_id\")),\n\t\t};\n\t};\n\tconst canRefresh = hasAllSettings(args.settings, [\"clientId\", \"clientSecret\", \"refreshToken\"]);\n\ttry {\n\t\treturn await sendRequest(await resolveZohoAccessToken(args));\n\t} catch (error) {\n\t\tif (!canRefresh || !shouldRetryAfterRefresh(error)) throw error;\n\t\treturn sendRequest(await resolveZohoAccessToken(args, true));\n\t}\n}\n\nfunction option(label: string, value: string): { label: string; value: string } {\n\treturn { label, value };\n}\n\nfunction fields(...defs: ProviderFieldDefinition[]): ProviderFieldDefinition[] {\n\treturn defs;\n}\n\nexport const SMTP_PROVIDER_DEFINITIONS: ProviderDefinition[] = [\n\t{\n\t\tid: \"amazon\",\n\t\tlabel: \"Amazon SES\",\n\t\tdescription: \"Amazon Simple Email Service using signed AWS API requests.\",\n\t\tavailability: { trusted: true, marketplace: true },\n\t\tallowedHosts: [\"*.amazonaws.com\"],\n\t\tfields: fields(\n\t\t\t{ key: \"accessKeyId\", label: \"Access Key ID\", type: \"secret\", required: true },\n\t\t\t{ key: \"secretAccessKey\", label: \"Secret Access Key\", type: \"secret\", required: true },\n\t\t\t{\n\t\t\t\tkey: \"region\",\n\t\t\t\tlabel: \"Region\",\n\t\t\t\ttype: \"select\",\n\t\t\t\trequired: true,\n\t\t\t\tdefaultValue: \"us-east-1\",\n\t\t\t\toptions: [\n\t\t\t\t\toption(\"US East (N. Virginia)\", \"us-east-1\"),\n\t\t\t\t\toption(\"US East (Ohio)\", \"us-east-2\"),\n\t\t\t\t\toption(\"US West (N. California)\", \"us-west-1\"),\n\t\t\t\t\toption(\"US West (Oregon)\", \"us-west-2\"),\n\t\t\t\t\toption(\"Europe (Ireland)\", \"eu-west-1\"),\n\t\t\t\t\toption(\"Europe (Frankfurt)\", \"eu-central-1\"),\n\t\t\t\t\toption(\"Europe (London)\", \"eu-west-2\"),\n\t\t\t\t\toption(\"Asia Pacific (Sydney)\", \"ap-southeast-2\"),\n\t\t\t\t\toption(\"Asia Pacific (Singapore)\", \"ap-southeast-1\"),\n\t\t\t\t],\n\t\t\t},\n\t\t),\n\t\tsend: sendViaAmazon,\n\t},\n\t{\n\t\tid: \"brevo\",\n\t\tlabel: \"Brevo\",\n\t\tdescription: \"Transactional email via the Brevo SMTP API.\",\n\t\tavailability: { trusted: true, marketplace: true },\n\t\tallowedHosts: [\"api.brevo.com\"],\n\t\tfields: fields({ key: \"apiKey\", label: \"API Key\", type: \"secret\", required: true }),\n\t\tsend: sendViaBrevo,\n\t},\n\t{\n\t\tid: \"elastic_email\",\n\t\tlabel: \"Elastic Email\",\n\t\tdescription: \"Transactional email via the Elastic Email v4 API.\",\n\t\tavailability: { trusted: true, marketplace: true },\n\t\tallowedHosts: [\"api.elasticemail.com\"],\n\t\tfields: fields({ key: \"apiKey\", label: \"API Key\", type: \"secret\", required: true }),\n\t\tsend: sendViaElasticEmail,\n\t},\n\t{\n\t\tid: \"emailit\",\n\t\tlabel: \"Emailit\",\n\t\tdescription: \"Transactional email via the Emailit API.\",\n\t\tavailability: { trusted: true, marketplace: true },\n\t\tallowedHosts: [\"api.emailit.com\"],\n\t\tfields: fields({ key: \"apiKey\", label: \"API Key\", type: \"secret\", required: true }),\n\t\tsend: sendViaEmailit,\n\t},\n\t{\n\t\tid: \"generic\",\n\t\tlabel: \"Generic SMTP\",\n\t\tdescription: \"Custom SMTP server using Nodemailer in the trusted package.\",\n\t\tavailability: { trusted: true, marketplace: false },\n\t\tallowedHosts: [],\n\t\tfields: fields(\n\t\t\t{ key: \"host\", label: \"SMTP Hostname\", type: \"text\", required: true, placeholder: \"smtp.example.com\" },\n\t\t\t{ key: \"port\", label: \"SMTP Port\", type: \"number\", required: true, defaultValue: 587 },\n\t\t\t{\n\t\t\t\tkey: \"security\",\n\t\t\t\tlabel: \"Encryption\",\n\t\t\t\ttype: \"select\",\n\t\t\t\tdefaultValue: \"starttls\",\n\t\t\t\toptions: [option(\"STARTTLS / Auto\", \"starttls\"), option(\"SSL/TLS\", \"ssl\"), option(\"None\", \"none\")],\n\t\t\t},\n\t\t\t{ key: \"username\", label: \"Authentication Username\", type: \"text\" },\n\t\t\t{ key: \"password\", label: \"Authentication Password\", type: \"secret\" },\n\t\t),\n\t\tsend: sendViaGenericSmtp,\n\t},\n\t{\n\t\tid: \"google\",\n\t\tlabel: \"Google / Gmail\",\n\t\tdescription: \"Gmail API delivery using an access token or refresh-token credentials.\",\n\t\tavailability: { trusted: true, marketplace: true },\n\t\tallowedHosts: [\"gmail.googleapis.com\", \"oauth2.googleapis.com\"],\n\t\tfields: fields(\n\t\t\t{ key: \"accessToken\", label: \"Access Token\", type: \"secret\" },\n\t\t\t{ key: \"refreshToken\", label: \"Refresh Token\", type: \"secret\" },\n\t\t\t{ key: \"clientId\", label: \"Client ID\", type: \"text\" },\n\t\t\t{ key: \"clientSecret\", label: \"Client Secret\", type: \"secret\" },\n\t\t),\n\t\tisConfigured: (settings) =>\n\t\t\tBoolean(stringValue(settings, \"accessToken\")) ||\n\t\t\thasAllSettings(settings, [\"clientId\", \"clientSecret\", \"refreshToken\"]),\n\t\tsend: sendViaGoogle,\n\t},\n\t{\n\t\tid: \"mailchimp\",\n\t\tlabel: \"Mailchimp Transactional\",\n\t\tdescription: \"Mandrill/Mailchimp Transactional email delivery.\",\n\t\tavailability: { trusted: true, marketplace: true },\n\t\tallowedHosts: [\"mandrillapp.com\"],\n\t\tfields: fields({ key: \"apiKey\", label: \"API Key\", type: \"secret\", required: true }),\n\t\tsend: sendViaMailchimp,\n\t},\n\t{\n\t\tid: \"mailersend\",\n\t\tlabel: \"MailerSend\",\n\t\tdescription: \"Transactional email via the MailerSend API.\",\n\t\tavailability: { trusted: true, marketplace: true },\n\t\tallowedHosts: [\"api.mailersend.com\"],\n\t\tfields: fields({ key: \"apiKey\", label: \"API Key\", type: \"secret\", required: true }),\n\t\tsend: sendViaMailerSend,\n\t},\n\t{\n\t\tid: \"mailgun\",\n\t\tlabel: \"Mailgun\",\n\t\tdescription: \"Transactional email via the Mailgun Messages API.\",\n\t\tavailability: { trusted: true, marketplace: true },\n\t\tallowedHosts: [\"api.mailgun.net\", \"api.eu.mailgun.net\"],\n\t\tfields: fields(\n\t\t\t{ key: \"apiKey\", label: \"Mailgun API Key\", type: \"secret\", required: true },\n\t\t\t{ key: \"domain\", label: \"Sending Domain\", type: \"text\", required: true, placeholder: \"mg.example.com\" },\n\t\t\t{\n\t\t\t\tkey: \"region\",\n\t\t\t\tlabel: \"Region\",\n\t\t\t\ttype: \"select\",\n\t\t\t\tdefaultValue: \"us\",\n\t\t\t\toptions: [option(\"US\", \"us\"), option(\"EU\", \"eu\")],\n\t\t\t},\n\t\t),\n\t\tsend: sendViaMailgun,\n\t},\n\t{\n\t\tid: \"mailjet\",\n\t\tlabel: \"Mailjet\",\n\t\tdescription: \"Transactional email via the Mailjet v3.1 API.\",\n\t\tavailability: { trusted: true, marketplace: true },\n\t\tallowedHosts: [\"api.mailjet.com\"],\n\t\tfields: fields(\n\t\t\t{ key: \"apiKey\", label: \"API Key\", type: \"secret\", required: true },\n\t\t\t{ key: \"apiSecret\", label: \"API Secret Key\", type: \"secret\", required: true },\n\t\t),\n\t\tsend: sendViaMailjet,\n\t},\n\t{\n\t\tid: \"microsoft\",\n\t\tlabel: \"365 / Outlook\",\n\t\tdescription: \"Microsoft Graph delivery using an access token or refresh-token credentials.\",\n\t\tavailability: { trusted: true, marketplace: true },\n\t\tallowedHosts: [\"graph.microsoft.com\", \"login.microsoftonline.com\"],\n\t\tfields: fields(\n\t\t\t{ key: \"accessToken\", label: \"Access Token\", type: \"secret\" },\n\t\t\t{ key: \"refreshToken\", label: \"Refresh Token\", type: \"secret\" },\n\t\t\t{ key: \"clientId\", label: \"Application ID\", type: \"text\" },\n\t\t\t{ key: \"clientSecret\", label: \"Client Secret\", type: \"secret\" },\n\t\t\t{ key: \"tenantId\", label: \"Tenant ID\", type: \"text\", defaultValue: \"common\", placeholder: \"common\" },\n\t\t),\n\t\tisConfigured: (settings) =>\n\t\t\tBoolean(stringValue(settings, \"accessToken\")) ||\n\t\t\thasAllSettings(settings, [\"clientId\", \"clientSecret\", \"refreshToken\"]),\n\t\tsend: sendViaMicrosoft,\n\t},\n\t{\n\t\tid: \"phpmail\",\n\t\tlabel: \"PHP Mail / local sendmail\",\n\t\tdescription: \"Local sendmail transport for trusted installs.\",\n\t\tavailability: { trusted: true, marketplace: false },\n\t\tallowedHosts: [],\n\t\tfields: fields({ key: \"sendmailPath\", label: \"Sendmail Path\", type: \"text\", defaultValue: \"sendmail\" }),\n\t\tsend: sendViaPhpMail,\n\t},\n\t{\n\t\tid: \"postmark\",\n\t\tlabel: \"Postmark\",\n\t\tdescription: \"Transactional email via the Postmark send email endpoint.\",\n\t\tavailability: { trusted: true, marketplace: true },\n\t\tallowedHosts: [\"api.postmarkapp.com\"],\n\t\tfields: fields({ key: \"serverApiToken\", label: \"Server API Token\", type: \"secret\", required: true }),\n\t\tsend: sendViaPostmark,\n\t},\n\t{\n\t\tid: \"resend\",\n\t\tlabel: \"Resend\",\n\t\tdescription: \"Transactional email via the Resend API.\",\n\t\tavailability: { trusted: true, marketplace: true },\n\t\tallowedHosts: [\"api.resend.com\"],\n\t\tfields: fields({ key: \"apiKey\", label: \"API Key\", type: \"secret\", required: true }),\n\t\tsend: sendViaResend,\n\t},\n\t{\n\t\tid: \"sendgrid\",\n\t\tlabel: \"SendGrid\",\n\t\tdescription: \"Transactional email via Twilio SendGrid.\",\n\t\tavailability: { trusted: true, marketplace: true },\n\t\tallowedHosts: [\"api.sendgrid.com\"],\n\t\tfields: fields({ key: \"apiKey\", label: \"SendGrid API Key\", type: \"secret\", required: true }),\n\t\tsend: sendViaSendgrid,\n\t},\n\t{\n\t\tid: \"smtp2go\",\n\t\tlabel: \"SMTP2GO\",\n\t\tdescription: \"Transactional email via SMTP2GO's HTTP API.\",\n\t\tavailability: { trusted: true, marketplace: true },\n\t\tallowedHosts: [\"api.smtp2go.com\"],\n\t\tfields: fields({ key: \"apiKey\", label: \"API Key\", type: \"secret\", required: true }),\n\t\tsend: sendViaSmtp2go,\n\t},\n\t{\n\t\tid: \"sparkpost\",\n\t\tlabel: \"SparkPost\",\n\t\tdescription: \"Transactional email via the SparkPost Transmissions API.\",\n\t\tavailability: { trusted: true, marketplace: true },\n\t\tallowedHosts: [\"api.sparkpost.com\", \"api.eu.sparkpost.com\"],\n\t\tfields: fields(\n\t\t\t{\n\t\t\t\tkey: \"accountLocation\",\n\t\t\t\tlabel: \"Account Location\",\n\t\t\t\ttype: \"select\",\n\t\t\t\tdefaultValue: \"us\",\n\t\t\t\toptions: [option(\"United States\", \"us\"), option(\"Europe\", \"eu\")],\n\t\t\t},\n\t\t\t{ key: \"apiKey\", label: \"API Key\", type: \"secret\", required: true },\n\t\t),\n\t\tsend: sendViaSparkpost,\n\t},\n\t{\n\t\tid: \"zoho\",\n\t\tlabel: \"Zoho Mail\",\n\t\tdescription: \"Zoho Mail API delivery using an access token or refresh-token credentials.\",\n\t\tavailability: { trusted: true, marketplace: true },\n\t\tallowedHosts: [\n\t\t\t\"mail.zoho.com\",\n\t\t\t\"mail.zoho.eu\",\n\t\t\t\"mail.zoho.in\",\n\t\t\t\"mail.zoho.com.au\",\n\t\t\t\"mail.zoho.jp\",\n\t\t\t\"mail.zoho.sa\",\n\t\t\t\"mail.zohocloud.ca\",\n\t\t\t\"accounts.zoho.com\",\n\t\t],\n\t\tfields: fields(\n\t\t\t{\n\t\t\t\tkey: \"dataCenterRegion\",\n\t\t\t\tlabel: \"Datacenter Region\",\n\t\t\t\ttype: \"select\",\n\t\t\t\tdefaultValue: \"us\",\n\t\t\t\toptions: [\n\t\t\t\t\toption(\"United States\", \"us\"),\n\t\t\t\t\toption(\"Europe\", \"eu\"),\n\t\t\t\t\toption(\"India\", \"in\"),\n\t\t\t\t\toption(\"Australia\", \"com.au\"),\n\t\t\t\t\toption(\"Japan\", \"jp\"),\n\t\t\t\t\toption(\"Saudi Arabia\", \"sa\"),\n\t\t\t\t\toption(\"Canada\", \"ca\"),\n\t\t\t\t],\n\t\t\t},\n\t\t\t{ key: \"clientId\", label: \"Client ID\", type: \"text\" },\n\t\t\t{ key: \"clientSecret\", label: \"Client Secret\", type: \"secret\" },\n\t\t\t{ key: \"refreshToken\", label: \"Refresh Token\", type: \"secret\" },\n\t\t\t{ key: \"accessToken\", label: \"Access Token\", type: \"secret\" },\n\t\t\t{ key: \"redirectUri\", label: \"Redirect URI\", type: \"text\", placeholder: \"Optional unless required by your token setup\" },\n\t\t\t{ key: \"accountId\", label: \"Account ID\", type: \"text\", required: true },\n\t\t),\n\t\tisConfigured: (settings) =>\n\t\t\tBoolean(stringValue(settings, \"accountId\")) &&\n\t\t\t(Boolean(stringValue(settings, \"accessToken\")) ||\n\t\t\t\thasAllSettings(settings, [\"clientId\", \"clientSecret\", \"refreshToken\"])),\n\t\tsend: sendViaZoho,\n\t},\n];\n\nexport function getProviderById(providerId: string): ProviderDefinition | undefined {\n\treturn SMTP_PROVIDER_DEFINITIONS.find((provider) => provider.id === providerId);\n}\n\nexport function isProviderAvailable(provider: ProviderDefinition, variant: PluginVariant): boolean {\n\treturn provider.availability[variant];\n}\n\nexport function isProviderConfigured(\n\tprovider: ProviderDefinition,\n\tsettings: Record<string, unknown>,\n): boolean {\n\tif (provider.isConfigured) {\n\t\treturn provider.isConfigured(settings);\n\t}\n\treturn provider.fields.every((field) => {\n\t\tif (!field.required) return true;\n\t\tif (field.type === \"number\") return numberValue(settings, field.key) !== undefined;\n\t\tif (field.type === \"toggle\") return settings[field.key] !== undefined;\n\t\treturn Boolean(stringValue(settings, field.key));\n\t});\n}\n\nexport function getProviderLabel(providerId: string | undefined): string {\n\tif (!providerId) return \"Not configured\";\n\treturn getProviderById(providerId)?.label ?? providerId;\n}\n\nexport function getAvailableProviderSelectOptions(variant: PluginVariant): Array<{ label: string; value: string }> {\n\treturn SMTP_PROVIDER_DEFINITIONS.filter((provider) => isProviderAvailable(provider, variant)).map((provider) => ({\n\t\tlabel: provider.label,\n\t\tvalue: provider.id,\n\t}));\n}\n\nexport function getProviderPickerOptions(variant: PluginVariant): Array<{ label: string; value: string }> {\n\treturn SMTP_PROVIDER_DEFINITIONS.map((provider) => ({\n\t\tlabel: isProviderAvailable(provider, variant) ? provider.label : `${provider.label} (trusted-only)`,\n\t\tvalue: provider.id,\n\t}));\n}\n\nexport function collectAllowedHosts(variant: PluginVariant): string[] {\n\treturn unique(\n\t\tSMTP_PROVIDER_DEFINITIONS.filter((provider) => isProviderAvailable(provider, variant)).flatMap(\n\t\t\t(provider) => provider.allowedHosts,\n\t\t),\n\t);\n}\n","import {\n\tgetAvailableProviderSelectOptions,\n\tgetProviderById,\n\tisProviderAvailable,\n\tisProviderConfigured,\n\tSMTP_PROVIDER_DEFINITIONS,\n} from \"./providers.js\";\nimport { getGlobalSettings, getProviderSettings } from \"./storage.js\";\nimport type {\n\tDeliveryMessage,\n\tDeliveryResult,\n\tDeliveryRuntime,\n\tGlobalSettings,\n\tProviderDefinition,\n\tSmtpPluginContextLike,\n} from \"./types.js\";\n\nfunction trimmed(value: string | undefined): string | undefined {\n\tif (!value) return undefined;\n\tconst next = value.trim();\n\treturn next === \"\" ? undefined : next;\n}\n\nfunction stripHtml(html: string): string {\n\treturn html\n\t\t.replace(/<style[\\s\\S]*?<\\/style>/gi, \"\")\n\t\t.replace(/<script[\\s\\S]*?<\\/script>/gi, \"\")\n\t\t.replace(/<[^>]+>/g, \" \")\n\t\t.replace(/\\s+/g, \" \")\n\t\t.trim();\n}\n\nfunction normalizeMessageInput(\n\tmessage: {\n\t\tto: string | string[];\n\t\tsubject: string;\n\t\ttext: string;\n\t\thtml?: string;\n\t},\n\tsettings: GlobalSettings,\n): DeliveryMessage {\n\tconst to = (Array.isArray(message.to) ? message.to : String(message.to).split(\",\"))\n\t\t.map((entry) => entry.trim())\n\t\t.filter(Boolean);\n\tif (to.length === 0) {\n\t\tthrow new Error(\"At least one recipient email address is required.\");\n\t}\n\tconst fromEmail = trimmed(settings.fromEmail);\n\tif (!fromEmail) {\n\t\tthrow new Error(\"A default from email must be configured before sending.\");\n\t}\n\tconst text = trimmed(message.text) ?? (message.html ? stripHtml(message.html) : \"\");\n\tif (!text && !trimmed(message.html)) {\n\t\tthrow new Error(\"A message body is required.\");\n\t}\n\treturn {\n\t\tto,\n\t\tsubject: message.subject,\n\t\ttext,\n\t\thtml: trimmed(message.html),\n\t\tfromEmail,\n\t\tfromName: trimmed(settings.fromName),\n\t\treplyTo: trimmed(settings.replyTo) ? [settings.replyTo!.trim()] : undefined,\n\t};\n}\n\nasync function resolvePrimaryProvider(\n\tctx: SmtpPluginContextLike,\n\truntime: DeliveryRuntime,\n\tsettings: GlobalSettings,\n): Promise<{ provider: ProviderDefinition; providerSettings: Record<string, unknown> }> {\n\tconst preferred = settings.primaryProviderId ? getProviderById(settings.primaryProviderId) : undefined;\n\tif (preferred && isProviderAvailable(preferred, runtime.variant)) {\n\t\tconst providerSettings = await getProviderSettings(ctx, preferred.id);\n\t\tif (isProviderConfigured(preferred, providerSettings)) {\n\t\t\treturn { provider: preferred, providerSettings };\n\t\t}\n\t}\n\n\tfor (const provider of SMTP_PROVIDER_DEFINITIONS) {\n\t\tif (!isProviderAvailable(provider, runtime.variant)) continue;\n\t\tconst providerSettings = await getProviderSettings(ctx, provider.id);\n\t\tif (isProviderConfigured(provider, providerSettings)) {\n\t\t\treturn { provider, providerSettings };\n\t\t}\n\t}\n\n\tconst variantLabel = runtime.variant === \"marketplace\" ? \"marketplace-compatible\" : \"trusted\";\n\tthrow new Error(`No configured ${variantLabel} SMTP provider is available.`);\n}\n\nasync function resolveFallbackProvider(\n\tctx: SmtpPluginContextLike,\n\truntime: DeliveryRuntime,\n\tsettings: GlobalSettings,\n\tprimaryProviderId: string,\n): Promise<{ provider: ProviderDefinition; providerSettings: Record<string, unknown> } | undefined> {\n\tif (!settings.fallbackProviderId || settings.fallbackProviderId === primaryProviderId) return undefined;\n\tconst provider = getProviderById(settings.fallbackProviderId);\n\tif (!provider || !isProviderAvailable(provider, runtime.variant)) return undefined;\n\tconst providerSettings = await getProviderSettings(ctx, provider.id);\n\tif (!isProviderConfigured(provider, providerSettings)) return undefined;\n\treturn { provider, providerSettings };\n}\n\nasync function sendWithProvider(\n\tctx: SmtpPluginContextLike,\n\tprovider: ProviderDefinition,\n\tproviderSettings: Record<string, unknown>,\n\tmessage: DeliveryMessage,\n\truntime: DeliveryRuntime,\n): Promise<DeliveryResult> {\n\tconst start = Date.now();\n\tconst result = await provider.send({\n\t\tctx,\n\t\tproviderId: provider.id,\n\t\tsettings: providerSettings,\n\t\tmessage,\n\t\truntime,\n\t});\n\treturn {\n\t\tproviderId: provider.id,\n\t\tremoteMessageId: result.remoteMessageId,\n\t\tdurationMs: Date.now() - start,\n\t};\n}\n\nexport async function deliverWithConfiguredProvider(args: {\n\tctx: SmtpPluginContextLike;\n\truntime: DeliveryRuntime;\n\tmessage: {\n\t\tto: string | string[];\n\t\tsubject: string;\n\t\ttext: string;\n\t\thtml?: string;\n\t};\n\tsource: string;\n}): Promise<DeliveryResult> {\n\tconst settings = await getGlobalSettings(args.ctx);\n\tconst normalizedMessage = normalizeMessageInput(args.message, settings);\n\tconst primary = await resolvePrimaryProvider(args.ctx, args.runtime, settings);\n\tconst fallback = await resolveFallbackProvider(args.ctx, args.runtime, settings, primary.provider.id);\n\n\ttry {\n\t\treturn await sendWithProvider(args.ctx, primary.provider, primary.providerSettings, normalizedMessage, args.runtime);\n\t} catch (primaryError) {\n\t\tif (!fallback) {\n\t\t\tthrow primaryError;\n\t\t}\n\t\targs.ctx.log?.warn(\"Primary SMTP provider failed, attempting fallback provider.\", {\n\t\t\tprimaryProviderId: primary.provider.id,\n\t\t\tfallbackProviderId: fallback.provider.id,\n\t\t\terror: primaryError instanceof Error ? primaryError.message : String(primaryError),\n\t\t});\n\t\treturn sendWithProvider(args.ctx, fallback.provider, fallback.providerSettings, normalizedMessage, args.runtime);\n\t}\n}\n\nexport async function isDeliveryReady(args: {\n\tctx: SmtpPluginContextLike;\n\truntime: DeliveryRuntime;\n}): Promise<boolean> {\n\tconst settings = await getGlobalSettings(args.ctx);\n\tif (!trimmed(settings.fromEmail)) {\n\t\treturn false;\n\t}\n\n\ttry {\n\t\tawait resolvePrimaryProvider(args.ctx, args.runtime, settings);\n\t\treturn true;\n\t} catch {\n\t\treturn false;\n\t}\n}\n","import {\n\tcollectAllowedHosts,\n\tgetAvailableProviderSelectOptions,\n\tgetProviderById,\n\tgetProviderLabel,\n\tgetProviderPickerOptions,\n\tisProviderAvailable,\n\tisProviderConfigured,\n\tSMTP_PROVIDER_DEFINITIONS,\n} from \"./providers.js\";\nimport {\n\tcountDeliveryLogs,\n\tcreateDeliveryLogRecord,\n\tgetGlobalSettings,\n\tgetLastTestResult,\n\tgetProviderSettings,\n\tgetSelectedProviderId,\n\tqueryRecentDeliveryLogs,\n\tsaveGlobalSettingsFromValues,\n\tsaveProviderSettingsFromValues,\n\tsetLastTestResult,\n\tsetSelectedProviderId,\n\twriteDeliveryLog,\n\tclearProviderSecret,\n} from \"./storage.js\";\nimport { deliverWithConfiguredProvider } from \"./delivery.js\";\nimport type {\n\tActionsBlock,\n\tAdminInteraction,\n\tBlock,\n\tBlockElement,\n\tBlockResponse,\n\tContextBlock,\n\tCountSummary,\n\tDeliveryRuntime,\n\tFormBlock,\n\tGlobalSettings,\n\tLastTestResult,\n\tPluginVariant,\n\tProviderDefinition,\n\tProviderFieldDefinition,\n\tSmtpPluginContextLike,\n\tTableBlock,\n} from \"./types.js\";\n\nexport const SMTP_PLUGIN_ID = \"emdash-smtp\";\nexport const SMTP_PLUGIN_VERSION = \"0.3.3\";\n\nexport const SMTP_ADMIN_PAGES = [\n\t{ path: \"/providers\", label: \"SMTP Providers\", icon: \"mail\" },\n\t{ path: \"/logs\", label: \"SMTP Logs\", icon: \"activity\" },\n] as const;\n\nexport const SMTP_ADMIN_WIDGETS = [{ id: \"smtp-overview\", title: \"SMTP\", size: \"third\" }] as const;\n\nfunction header(text: string): Block {\n\treturn { type: \"header\", text };\n}\n\nfunction divider(): Block {\n\treturn { type: \"divider\" };\n}\n\nfunction context(text: string): ContextBlock {\n\treturn { type: \"context\", text };\n}\n\nfunction banner(title: string, description: string, variant: \"default\" | \"alert\" | \"error\" = \"default\"): Block {\n\treturn { type: \"banner\", title, description, variant };\n}\n\nfunction stats(summary: CountSummary): Block {\n\treturn {\n\t\ttype: \"stats\",\n\t\titems: [\n\t\t\t{ label: \"Active provider\", value: summary.activeProviderLabel },\n\t\t\t{ label: \"Sent\", value: summary.sentCount, trend: summary.sentCount > 0 ? \"up\" : \"neutral\" },\n\t\t\t{ label: \"Failed\", value: summary.failedCount, trend: summary.failedCount > 0 ? \"down\" : \"neutral\" },\n\t\t],\n\t};\n}\n\nfunction actions(elements: BlockElement[]): ActionsBlock {\n\treturn { type: \"actions\", elements };\n}\n\nfunction button(\n\tactionId: string,\n\tlabel: string,\n\topts?: {\n\t\tstyle?: \"primary\" | \"danger\" | \"secondary\";\n\t\tvalue?: unknown;\n\t\tconfirm?: { title: string; text: string; confirm: string; deny: string; style?: \"danger\" };\n\t},\n): BlockElement {\n\treturn {\n\t\ttype: \"button\",\n\t\taction_id: actionId,\n\t\tlabel,\n\t\t...(opts?.style ? { style: opts.style } : {}),\n\t\t...(opts?.value !== undefined ? { value: opts.value } : {}),\n\t\t...(opts?.confirm ? { confirm: opts.confirm } : {}),\n\t};\n}\n\nfunction textField(field: ProviderFieldDefinition, value?: string): FormBlock[\"fields\"][number] {\n\treturn {\n\t\ttype: \"text_input\",\n\t\taction_id: field.key,\n\t\tlabel: field.label,\n\t\t...(field.placeholder ? { placeholder: field.placeholder } : {}),\n\t\t...(value !== undefined ? { initial_value: value } : {}),\n\t\t...(field.type === \"textarea\" || field.multiline ? { multiline: true } : {}),\n\t};\n}\n\nfunction secretField(field: ProviderFieldDefinition, hasValue: boolean): FormBlock[\"fields\"][number] {\n\treturn {\n\t\ttype: \"secret_input\",\n\t\taction_id: field.key,\n\t\tlabel: field.label,\n\t\t...(field.placeholder ? { placeholder: field.placeholder } : {}),\n\t\thas_value: hasValue,\n\t};\n}\n\nfunction numberField(field: ProviderFieldDefinition, value?: number): FormBlock[\"fields\"][number] {\n\treturn {\n\t\ttype: \"number_input\",\n\t\taction_id: field.key,\n\t\tlabel: field.label,\n\t\t...(value !== undefined ? { initial_value: value } : {}),\n\t};\n}\n\nfunction selectField(\n\tfield: ProviderFieldDefinition,\n\tvalue?: string,\n\toverrideOptions?: Array<{ label: string; value: string }>,\n): FormBlock[\"fields\"][number] {\n\treturn {\n\t\ttype: \"select\",\n\t\taction_id: field.key,\n\t\tlabel: field.label,\n\t\toptions: overrideOptions ?? field.options ?? [],\n\t\t...(value !== undefined ? { initial_value: value } : {}),\n\t};\n}\n\nfunction toggleField(field: ProviderFieldDefinition, value?: boolean): FormBlock[\"fields\"][number] {\n\treturn {\n\t\ttype: \"toggle\",\n\t\taction_id: field.key,\n\t\tlabel: field.label,\n\t\t...(field.description ? { description: field.description } : {}),\n\t\t...(value !== undefined ? { initial_value: value } : {}),\n\t};\n}\n\nfunction stringValue(value: unknown): string | undefined {\n\tif (typeof value !== \"string\") return undefined;\n\tconst next = value.trim();\n\treturn next === \"\" ? undefined : next;\n}\n\nfunction numberValue(value: unknown): number | undefined {\n\tif (typeof value === \"number\" && Number.isFinite(value)) return value;\n\tif (typeof value === \"string\" && value.trim() !== \"\") {\n\t\tconst parsed = Number(value);\n\t\tif (Number.isFinite(parsed)) return parsed;\n\t}\n\treturn undefined;\n}\n\nfunction booleanValue(value: unknown): boolean {\n\tif (typeof value === \"boolean\") return value;\n\tif (typeof value === \"string\") return value === \"true\" || value === \"1\" || value === \"on\";\n\treturn Boolean(value);\n}\n\nasync function buildSummary(ctx: SmtpPluginContextLike): Promise<CountSummary> {\n\tconst settings = await getGlobalSettings(ctx);\n\tconst sentCount = await countDeliveryLogs(ctx, \"sent\");\n\tconst failedCount = await countDeliveryLogs(ctx, \"failed\");\n\treturn {\n\t\tactiveProviderLabel: getProviderLabel(settings.primaryProviderId),\n\t\tsentCount,\n\t\tfailedCount,\n\t};\n}\n\nasync function getCurrentProvider(\n\tctx: SmtpPluginContextLike,\n\tvariant: PluginVariant,\n): Promise<ProviderDefinition> {\n\tconst selected = await getSelectedProviderId(ctx);\n\tconst preferred = selected ? getProviderById(selected) : undefined;\n\tif (preferred) return preferred;\n\treturn (\n\t\tSMTP_PROVIDER_DEFINITIONS.find((provider) => isProviderAvailable(provider, variant)) ??\n\t\tSMTP_PROVIDER_DEFINITIONS[0]!\n\t);\n}\n\nfunction buildGlobalSettingsForm(settings: GlobalSettings, variant: PluginVariant): FormBlock {\n\tconst availableOptions = getAvailableProviderSelectOptions(variant);\n\tconst logLevelOptions = [\n\t\t{ label: \"All deliveries\", value: \"all\" },\n\t\t{ label: \"Errors only\", value: \"errors\" },\n\t\t{ label: \"Disabled\", value: \"off\" },\n\t];\n\treturn {\n\t\ttype: \"form\",\n\t\tblock_id: \"global-settings\",\n\t\tfields: [\n\t\t\tselectField(\n\t\t\t\t{ key: \"primaryProviderId\", label: \"Primary Provider\", type: \"select\", options: availableOptions },\n\t\t\t\tsettings.primaryProviderId,\n\t\t\t\tavailableOptions,\n\t\t\t),\n\t\t\tselectField(\n\t\t\t\t{\n\t\t\t\t\tkey: \"fallbackProviderId\",\n\t\t\t\t\tlabel: \"Fallback Provider\",\n\t\t\t\t\ttype: \"select\",\n\t\t\t\t\toptions: [{ label: \"None\", value: \"\" }, ...availableOptions],\n\t\t\t\t},\n\t\t\t\tsettings.fallbackProviderId,\n\t\t\t\t[{ label: \"None\", value: \"\" }, ...availableOptions],\n\t\t\t),\n\t\t\ttextField({ key: \"fromEmail\", label: \"Default From Email\", type: \"text\", required: true, placeholder: \"noreply@example.com\" }, settings.fromEmail),\n\t\t\ttextField({ key: \"fromName\", label: \"Default From Name\", type: \"text\", placeholder: \"Example Site\" }, settings.fromName),\n\t\t\ttextField({ key: \"replyTo\", label: \"Default Reply-To Email\", type: \"text\", placeholder: \"support@example.com\" }, settings.replyTo),\n\t\t\tselectField({ key: \"logLevel\", label: \"Log Level\", type: \"select\", options: logLevelOptions }, settings.logLevel ?? \"all\", logLevelOptions),\n\t\t],\n\t\tsubmit: { label: \"Save Global Settings\", action_id: \"save_global\" },\n\t};\n}\n\nfunction buildProviderPickerForm(providerId: string, variant: PluginVariant): FormBlock {\n\tconst options = getProviderPickerOptions(variant);\n\treturn {\n\t\ttype: \"form\",\n\t\tblock_id: \"provider-picker\",\n\t\tfields: [selectField({ key: \"providerId\", label: \"Provider\", type: \"select\", options }, providerId, options)],\n\t\tsubmit: { label: \"Load Provider\", action_id: \"select_provider\" },\n\t};\n}\n\nfunction buildProviderDetails(provider: ProviderDefinition, variant: PluginVariant, configured: boolean): Block[] {\n\tconst available = isProviderAvailable(provider, variant);\n\treturn [\n\t\t{\n\t\t\ttype: \"fields\",\n\t\t\tfields: [\n\t\t\t\t{ label: \"Provider\", value: provider.label },\n\t\t\t\t{ label: \"Availability\", value: available ? \"Available\" : \"Trusted-only\" },\n\t\t\t\t{ label: \"Configured\", value: configured ? \"Yes\" : \"No\" },\n\t\t\t\t{ label: \"Allowed Hosts\", value: provider.allowedHosts.length ? provider.allowedHosts.join(\", \") : \"None\" },\n\t\t\t],\n\t\t},\n\t\tcontext(provider.description),\n\t];\n}\n\nfunction buildProviderSettingsForm(\n\tprovider: ProviderDefinition,\n\tsettings: Record<string, unknown>,\n): FormBlock {\n\tconst fields = provider.fields.map((field) => {\n\t\tif (field.type === \"secret\") return secretField(field, Boolean(stringValue(settings[field.key])));\n\t\tif (field.type === \"number\") return numberField(field, numberValue(settings[field.key]) ?? (typeof field.defaultValue === \"number\" ? field.defaultValue : undefined));\n\t\tif (field.type === \"select\") return selectField(field, stringValue(settings[field.key]) ?? (typeof field.defaultValue === \"string\" ? field.defaultValue : undefined));\n\t\tif (field.type === \"toggle\") return toggleField(field, typeof settings[field.key] === \"boolean\" ? booleanValue(settings[field.key]) : (typeof field.defaultValue === \"boolean\" ? field.defaultValue : undefined));\n\t\treturn textField(field, stringValue(settings[field.key]) ?? (typeof field.defaultValue === \"string\" ? field.defaultValue : undefined));\n\t});\n\treturn {\n\t\ttype: \"form\",\n\t\tblock_id: \"provider-settings\",\n\t\tfields,\n\t\tsubmit: { label: \"Save Provider Settings\", action_id: \"save_provider\" },\n\t};\n}\n\nfunction buildProviderSecretActions(\n\tprovider: ProviderDefinition,\n\tsettings: Record<string, unknown>,\n): ActionsBlock | null {\n\tconst elements = provider.fields\n\t\t.filter((field) => field.type === \"secret\" && Boolean(stringValue(settings[field.key])))\n\t\t.map((field) =>\n\t\t\tbutton(`clear_secret:${provider.id}:${field.key}`, `Clear ${field.label}`, {\n\t\t\t\tstyle: \"danger\",\n\t\t\t\tconfirm: {\n\t\t\t\t\ttitle: `Clear ${field.label}?`,\n\t\t\t\t\ttext: `This will remove the stored ${field.label.toLowerCase()} from ${provider.label}.`,\n\t\t\t\t\tconfirm: \"Clear\",\n\t\t\t\t\tdeny: \"Cancel\",\n\t\t\t\t\tstyle: \"danger\",\n\t\t\t\t},\n\t\t\t}),\n\t\t);\n\treturn elements.length ? actions(elements) : null;\n}\n\nfunction buildTestSendForm(lastResult: LastTestResult | null): Block[] {\n\tconst blocks: Block[] = [\n\t\t{\n\t\t\ttype: \"form\",\n\t\t\tblock_id: \"test-send\",\n\t\t\tfields: [\n\t\t\t\t{ type: \"text_input\", action_id: \"to\", label: \"Recipient Email\", placeholder: \"you@example.com\" },\n\t\t\t\t{ type: \"text_input\", action_id: \"subject\", label: \"Subject\", initial_value: \"EmDash SMTP test email\" },\n\t\t\t\t{ type: \"text_input\", action_id: \"text\", label: \"Message\", multiline: true, initial_value: \"This is a test email sent from EmDash SMTP.\" },\n\t\t\t],\n\t\t\tsubmit: { label: \"Send Test Email\", action_id: \"send_test\" },\n\t\t},\n\t];\n\tif (lastResult) {\n\t\tblocks.push(\n\t\t\tbanner(\n\t\t\t\tlastResult.status === \"sent\" ? \"Last test succeeded\" : \"Last test failed\",\n\t\t\t\t`${lastResult.createdAt}: ${lastResult.message}`,\n\t\t\t\tlastResult.status === \"sent\" ? \"default\" : \"error\",\n\t\t\t),\n\t\t);\n\t}\n\treturn blocks;\n}\n\nasync function buildLogsTable(ctx: SmtpPluginContextLike): Promise<TableBlock> {\n\tconst logs = await queryRecentDeliveryLogs(ctx, 25);\n\treturn {\n\t\ttype: \"table\",\n\t\tpage_action_id: \"go_logs\",\n\t\tempty_text: \"No delivery logs yet.\",\n\t\tcolumns: [\n\t\t\t{ key: \"createdAt\", label: \"Created\", format: \"relative_time\", sortable: true },\n\t\t\t{ key: \"status\", label: \"Status\", format: \"badge\" },\n\t\t\t{ key: \"provider\", label: \"Provider\" },\n\t\t\t{ key: \"to\", label: \"To\" },\n\t\t\t{ key: \"subject\", label: \"Subject\" },\n\t\t\t{ key: \"source\", label: \"Source\" },\n\t\t\t{ key: \"details\", label: \"Details\", format: \"code\" },\n\t\t],\n\t\trows: logs.map(({ data }) => ({\n\t\t\tcreatedAt: data.createdAt,\n\t\t\tstatus: data.status,\n\t\t\tprovider: getProviderLabel(data.providerId),\n\t\t\tto: data.message.to,\n\t\t\tsubject: data.message.subject,\n\t\t\tsource: data.source,\n\t\t\tdetails: data.errorMessage ?? data.remoteMessageId ?? \"—\",\n\t\t})),\n\t};\n}\n\nasync function buildProvidersPage(\n\tctx: SmtpPluginContextLike,\n\tvariant: PluginVariant,\n\truntime: DeliveryRuntime,\n\ttoast?: BlockResponse[\"toast\"],\n): Promise<BlockResponse> {\n\tconst summary = await buildSummary(ctx);\n\tconst settings = await getGlobalSettings(ctx);\n\tconst currentProvider = await getCurrentProvider(ctx, variant);\n\tconst currentProviderSettings = await getProviderSettings(ctx, currentProvider.id);\n\tconst configured = isProviderConfigured(currentProvider, currentProviderSettings);\n\tconst lastTestResult = await getLastTestResult(ctx);\n\tconst secretActions = buildProviderSecretActions(currentProvider, currentProviderSettings);\n\n\tconst providerRows = await Promise.all(\n\t\tSMTP_PROVIDER_DEFINITIONS.map(async (provider) => {\n\t\t\tconst providerSettings = await getProviderSettings(ctx, provider.id);\n\t\t\treturn {\n\t\t\t\tprovider: provider.label,\n\t\t\t\tid: provider.id,\n\t\t\t\tavailability: isProviderAvailable(provider, variant) ? \"available\" : \"trusted-only\",\n\t\t\t\tconfigured: isProviderConfigured(provider, providerSettings) ? \"yes\" : \"no\",\n\t\t\t\tselected: provider.id === currentProvider.id ? \"current\" : \"\",\n\t\t\t};\n\t\t}),\n\t);\n\n\tconst blocks: Block[] = [\n\t\theader(\"SMTP Providers\"),\n\t\tbanner(\n\t\t\tvariant === \"marketplace\" ? \"Marketplace-safe variant\" : \"Trusted variant\",\n\t\t\tvariant === \"marketplace\"\n\t\t\t\t? \"This install can use HTTP API providers. Generic SMTP and local sendmail remain visible for parity but are not available here.\"\n\t\t\t\t: `This install can use all providers, including Generic SMTP and local sendmail. Allowed hosts: ${collectAllowedHosts(\"trusted\").join(\", \")}`,\n\t\t\tvariant === \"marketplace\" ? \"alert\" : \"default\",\n\t\t),\n\t\tstats(summary),\n\t\tactions([\n\t\t\tbutton(\"go_providers\", \"Providers\", { style: \"secondary\" }),\n\t\t\tbutton(\"go_logs\", \"View Logs\", { style: \"primary\" }),\n\t\t]),\n\t\t{\n\t\t\ttype: \"table\",\n\t\t\tpage_action_id: \"go_providers\",\n\t\t\tempty_text: \"No providers available.\",\n\t\t\tcolumns: [\n\t\t\t\t{ key: \"provider\", label: \"Provider\" },\n\t\t\t\t{ key: \"id\", label: \"ID\", format: \"code\" },\n\t\t\t\t{ key: \"availability\", label: \"Availability\", format: \"badge\" },\n\t\t\t\t{ key: \"configured\", label: \"Configured\", format: \"badge\" },\n\t\t\t\t{ key: \"selected\", label: \"Selected\", format: \"badge\" },\n\t\t\t],\n\t\t\trows: providerRows,\n\t\t},\n\t\tdivider(),\n\t\tbuildProviderPickerForm(currentProvider.id, variant),\n\t\t...buildProviderDetails(currentProvider, variant, configured),\n\t\tbuildGlobalSettingsForm(settings, variant),\n\t];\n\n\tif (!isProviderAvailable(currentProvider, variant)) {\n\t\tblocks.push(\n\t\t\tbanner(\n\t\t\t\t`${currentProvider.label} is not available in the marketplace variant`,\n\t\t\t\t\"Use the trusted emdash-smtp package in astro.config.mjs if you need this transport.\",\n\t\t\t\t\"alert\",\n\t\t\t),\n\t\t);\n\t} else {\n\t\tblocks.push(buildProviderSettingsForm(currentProvider, currentProviderSettings));\n\t\tif (secretActions) blocks.push(secretActions);\n\t\tblocks.push(...buildTestSendForm(lastTestResult));\n\t}\n\n\treturn { blocks, ...(toast ? { toast } : {}) };\n}\n\nasync function buildLogsPage(\n\tctx: SmtpPluginContextLike,\n\ttoast?: BlockResponse[\"toast\"],\n): Promise<BlockResponse> {\n\tconst summary = await buildSummary(ctx);\n\treturn {\n\t\tblocks: [\n\t\t\theader(\"SMTP Logs\"),\n\t\t\tstats(summary),\n\t\t\tactions([\n\t\t\t\tbutton(\"go_providers\", \"Providers\", { style: \"primary\" }),\n\t\t\t\tbutton(\"go_logs\", \"Refresh Logs\", { style: \"secondary\" }),\n\t\t\t]),\n\t\t\tawait buildLogsTable(ctx),\n\t\t],\n\t\t...(toast ? { toast } : {}),\n\t};\n}\n\nasync function buildWidgetPage(ctx: SmtpPluginContextLike): Promise<BlockResponse> {\n\tconst summary = await buildSummary(ctx);\n\treturn {\n\t\tblocks: [\n\t\t\tstats(summary),\n\t\t\tcontext(\"EmDash SMTP monitors the active provider and recent delivery outcomes.\"),\n\t\t],\n\t};\n}\n\nexport async function handleAdminInteraction(args: {\n\tctx: SmtpPluginContextLike;\n\tvariant: PluginVariant;\n\truntime: DeliveryRuntime;\n\tinteraction: AdminInteraction;\n}): Promise<BlockResponse> {\n\tconst { ctx, interaction, variant, runtime } = args;\n\n\tif (interaction.type === \"page_load\") {\n\t\tif (interaction.page === \"/logs\") return buildLogsPage(ctx);\n\t\tif (interaction.page === \"widget:smtp-overview\") return buildWidgetPage(ctx);\n\t\treturn buildProvidersPage(ctx, variant, runtime);\n\t}\n\n\tif (interaction.type === \"block_action\" || interaction.type === \"action\") {\n\t\tif (interaction.action_id === \"go_logs\") return buildLogsPage(ctx);\n\t\tif (interaction.action_id === \"go_providers\") return buildProvidersPage(ctx, variant, runtime);\n\t\tif (interaction.action_id.startsWith(\"clear_secret:\")) {\n\t\t\tconst [, providerId, fieldKey] = interaction.action_id.split(\":\");\n\t\t\tif (providerId && fieldKey) {\n\t\t\t\tawait clearProviderSecret(ctx, providerId, fieldKey);\n\t\t\t\treturn buildProvidersPage(ctx, variant, runtime, {\n\t\t\t\t\tmessage: `Cleared stored secret for ${fieldKey}.`,\n\t\t\t\t\ttype: \"success\",\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t\treturn buildProvidersPage(ctx, variant, runtime);\n\t}\n\n\tif (interaction.type === \"form_submit\") {\n\t\tif (interaction.action_id === \"save_global\") {\n\t\t\tawait saveGlobalSettingsFromValues(ctx, interaction.values);\n\t\t\treturn buildProvidersPage(ctx, variant, runtime, {\n\t\t\t\tmessage: \"Global SMTP settings saved.\",\n\t\t\t\ttype: \"success\",\n\t\t\t});\n\t\t}\n\n\t\tif (interaction.action_id === \"select_provider\") {\n\t\t\tconst providerId = stringValue(interaction.values.providerId);\n\t\t\tif (providerId) {\n\t\t\t\tawait setSelectedProviderId(ctx, providerId);\n\t\t\t}\n\t\t\treturn buildProvidersPage(ctx, variant, runtime, {\n\t\t\t\tmessage: \"Provider selection updated.\",\n\t\t\t\ttype: \"info\",\n\t\t\t});\n\t\t}\n\n\t\tif (interaction.action_id === \"save_provider\") {\n\t\t\tconst provider = await getCurrentProvider(ctx, variant);\n\t\t\tawait saveProviderSettingsFromValues(ctx, provider, interaction.values);\n\t\t\treturn buildProvidersPage(ctx, variant, runtime, {\n\t\t\t\tmessage: `${provider.label} settings saved.`,\n\t\t\t\ttype: \"success\",\n\t\t\t});\n\t\t}\n\n\t\tif (interaction.action_id === \"send_test\") {\n\t\t\tconst to = stringValue(interaction.values.to);\n\t\t\tconst subject = stringValue(interaction.values.subject) ?? \"EmDash SMTP test email\";\n\t\t\tconst text = stringValue(interaction.values.text) ?? \"This is a test email sent from EmDash SMTP.\";\n\t\t\tif (!to) {\n\t\t\t\treturn buildProvidersPage(ctx, variant, runtime, {\n\t\t\t\t\tmessage: \"A recipient email address is required for test sends.\",\n\t\t\t\t\ttype: \"error\",\n\t\t\t\t});\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tconst result = await deliverWithConfiguredProvider({\n\t\t\t\t\tctx,\n\t\t\t\t\truntime,\n\t\t\t\t\tmessage: { to, subject, text },\n\t\t\t\t\tsource: `${ctx.plugin.id}:test`,\n\t\t\t\t});\n\t\t\t\tawait writeDeliveryLog(\n\t\t\t\t\tctx,\n\t\t\t\t\tcreateDeliveryLogRecord({\n\t\t\t\t\t\tproviderId: result.providerId,\n\t\t\t\t\t\tstatus: \"sent\",\n\t\t\t\t\t\tsource: `${ctx.plugin.id}:test`,\n\t\t\t\t\t\tdurationMs: result.durationMs,\n\t\t\t\t\t\tmessage: { to, subject },\n\t\t\t\t\t\tremoteMessageId: result.remoteMessageId,\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t\tawait setLastTestResult(ctx, {\n\t\t\t\t\tstatus: \"sent\",\n\t\t\t\t\tproviderId: result.providerId,\n\t\t\t\t\tmessage: `Sent with ${getProviderLabel(result.providerId)}${result.remoteMessageId ? ` (${result.remoteMessageId})` : \"\"}.`,\n\t\t\t\t\tcreatedAt: new Date().toISOString(),\n\t\t\t\t});\n\t\t\t\treturn buildProvidersPage(ctx, variant, runtime, {\n\t\t\t\t\tmessage: `Test email sent with ${getProviderLabel(result.providerId)}.`,\n\t\t\t\t\ttype: \"success\",\n\t\t\t\t});\n\t\t\t} catch (error) {\n\t\t\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\t\t\tawait writeDeliveryLog(\n\t\t\t\t\tctx,\n\t\t\t\t\tcreateDeliveryLogRecord({\n\t\t\t\t\t\tproviderId: \"unknown\",\n\t\t\t\t\t\tstatus: \"failed\",\n\t\t\t\t\t\tsource: `${ctx.plugin.id}:test`,\n\t\t\t\t\t\tdurationMs: 0,\n\t\t\t\t\t\tmessage: { to, subject },\n\t\t\t\t\t\terrorMessage: message,\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t\tawait setLastTestResult(ctx, {\n\t\t\t\t\tstatus: \"failed\",\n\t\t\t\t\tmessage,\n\t\t\t\t\tcreatedAt: new Date().toISOString(),\n\t\t\t\t});\n\t\t\t\treturn buildProvidersPage(ctx, variant, runtime, {\n\t\t\t\t\tmessage,\n\t\t\t\t\ttype: \"error\",\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n\n\treturn buildProvidersPage(ctx, variant, runtime);\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.mjs","names":["numberValue","booleanValue","stringValue","numberValue","stripHtml"],"sources":["../src/storage.ts","../src/providers.ts","../src/delivery.ts","../src/admin.ts"],"sourcesContent":["import type {\n\tAdminInteraction,\n\tDeliveryLogRecord,\n\tGlobalSettings,\n\tLastTestResult,\n\tLogLevel,\n\tProviderDefinition,\n\tSmtpPluginContextLike,\n} from \"./types.js\";\n\nexport const GLOBAL_SETTINGS_KEY = \"settings:global\";\nexport const SELECTED_PROVIDER_KEY = \"state:selectedProviderId\";\nexport const LAST_TEST_RESULT_KEY = \"state:lastTestResult\";\n\nfunction providerSettingsKey(providerId: string): string {\n\treturn `settings:provider:${providerId}`;\n}\n\nfunction trimString(value: unknown): string | undefined {\n\tif (typeof value !== \"string\") return undefined;\n\tconst next = value.trim();\n\treturn next === \"\" ? undefined : next;\n}\n\nfunction numberValue(value: unknown): number | undefined {\n\tif (typeof value === \"number\" && Number.isFinite(value)) return value;\n\tif (typeof value === \"string\" && value.trim() !== \"\") {\n\t\tconst next = Number(value);\n\t\tif (Number.isFinite(next)) return next;\n\t}\n\treturn undefined;\n}\n\nfunction booleanValue(value: unknown): boolean {\n\tif (typeof value === \"boolean\") return value;\n\tif (typeof value === \"string\") {\n\t\treturn value === \"true\" || value === \"1\" || value === \"on\";\n\t}\n\treturn Boolean(value);\n}\n\nfunction normalizeLogLevel(value: unknown): LogLevel {\n\tif (value === \"errors\" || value === \"off\") return value;\n\treturn \"all\";\n}\n\nfunction cleanRecord(record: Record<string, unknown>): Record<string, unknown> {\n\treturn Object.fromEntries(Object.entries(record).filter(([, value]) => value !== undefined));\n}\n\nexport async function getGlobalSettings(ctx: SmtpPluginContextLike): Promise<GlobalSettings> {\n\tconst saved = (await ctx.kv.get<GlobalSettings>(GLOBAL_SETTINGS_KEY)) ?? {};\n\treturn {\n\t\tprimaryProviderId: trimString(saved.primaryProviderId),\n\t\tfallbackProviderId: trimString(saved.fallbackProviderId),\n\t\tfromEmail: trimString(saved.fromEmail),\n\t\tfromName: trimString(saved.fromName),\n\t\treplyTo: trimString(saved.replyTo),\n\t\tlogLevel: normalizeLogLevel(saved.logLevel),\n\t};\n}\n\nexport async function saveGlobalSettingsFromValues(\n\tctx: SmtpPluginContextLike,\n\tvalues: Record<string, unknown>,\n): Promise<GlobalSettings> {\n\tconst current = await getGlobalSettings(ctx);\n\tconst next: GlobalSettings = {\n\t\tprimaryProviderId:\n\t\t\tvalues.primaryProviderId === undefined\n\t\t\t\t? current.primaryProviderId\n\t\t\t\t: trimString(values.primaryProviderId),\n\t\tfallbackProviderId:\n\t\t\tvalues.fallbackProviderId === undefined\n\t\t\t\t? current.fallbackProviderId\n\t\t\t\t: trimString(values.fallbackProviderId),\n\t\tfromEmail: values.fromEmail === undefined ? current.fromEmail : trimString(values.fromEmail),\n\t\tfromName: values.fromName === undefined ? current.fromName : trimString(values.fromName),\n\t\treplyTo: values.replyTo === undefined ? current.replyTo : trimString(values.replyTo),\n\t\tlogLevel: values.logLevel === undefined ? current.logLevel : normalizeLogLevel(values.logLevel),\n\t};\n\tawait ctx.kv.set(GLOBAL_SETTINGS_KEY, next);\n\treturn next;\n}\n\nexport async function getProviderSettings(\n\tctx: SmtpPluginContextLike,\n\tproviderId: string,\n): Promise<Record<string, unknown>> {\n\treturn ((await ctx.kv.get<Record<string, unknown>>(providerSettingsKey(providerId))) ?? {}) as Record<\n\t\tstring,\n\t\tunknown\n\t>;\n}\n\nexport async function patchProviderSettings(\n\tctx: SmtpPluginContextLike,\n\tproviderId: string,\n\tpatch: Record<string, unknown>,\n): Promise<Record<string, unknown>> {\n\tconst current = await getProviderSettings(ctx, providerId);\n\tconst cleaned = cleanRecord({ ...current, ...patch });\n\tawait ctx.kv.set(providerSettingsKey(providerId), cleaned);\n\treturn cleaned;\n}\n\nexport async function saveProviderSettingsFromValues(\n\tctx: SmtpPluginContextLike,\n\tprovider: ProviderDefinition,\n\tvalues: Record<string, unknown>,\n): Promise<Record<string, unknown>> {\n\tconst existing = await getProviderSettings(ctx, provider.id);\n\tconst next: Record<string, unknown> = {};\n\n\tfor (const field of provider.fields) {\n\t\tconst raw = values[field.key];\n\t\tif (field.type === \"secret\") {\n\t\t\tconst secret = trimString(raw);\n\t\t\tif (secret !== undefined) {\n\t\t\t\tnext[field.key] = secret;\n\t\t\t} else if (existing[field.key] !== undefined) {\n\t\t\t\tnext[field.key] = existing[field.key];\n\t\t\t}\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (field.type === \"number\") {\n\t\t\tconst numeric = numberValue(raw);\n\t\t\tif (numeric !== undefined) next[field.key] = numeric;\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (field.type === \"toggle\") {\n\t\t\tnext[field.key] = booleanValue(raw);\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst text = trimString(raw);\n\t\tif (text !== undefined) next[field.key] = text;\n\t}\n\n\tconst cleaned = cleanRecord(next);\n\tawait ctx.kv.set(providerSettingsKey(provider.id), cleaned);\n\treturn cleaned;\n}\n\nexport async function clearProviderSecret(\n\tctx: SmtpPluginContextLike,\n\tproviderId: string,\n\tfieldKey: string,\n): Promise<void> {\n\tconst current = await getProviderSettings(ctx, providerId);\n\tconst next = { ...current };\n\tdelete next[fieldKey];\n\tawait ctx.kv.set(providerSettingsKey(providerId), cleanRecord(next));\n}\n\nexport async function getSelectedProviderId(\n\tctx: SmtpPluginContextLike,\n): Promise<string | undefined> {\n\treturn trimString(await ctx.kv.get<string>(SELECTED_PROVIDER_KEY));\n}\n\nexport async function setSelectedProviderId(\n\tctx: SmtpPluginContextLike,\n\tproviderId: string,\n): Promise<void> {\n\tawait ctx.kv.set(SELECTED_PROVIDER_KEY, providerId);\n}\n\nexport async function getLastTestResult(\n\tctx: SmtpPluginContextLike,\n): Promise<LastTestResult | null> {\n\treturn await ctx.kv.get<LastTestResult>(LAST_TEST_RESULT_KEY);\n}\n\nexport async function setLastTestResult(\n\tctx: SmtpPluginContextLike,\n\tresult: LastTestResult,\n): Promise<void> {\n\tawait ctx.kv.set(LAST_TEST_RESULT_KEY, result);\n}\n\nexport function createDeliveryLogRecord(\n\tinput: Omit<DeliveryLogRecord, \"createdAt\"> & { createdAt?: string },\n): DeliveryLogRecord {\n\treturn {\n\t\t...input,\n\t\tcreatedAt: input.createdAt ?? new Date().toISOString(),\n\t};\n}\n\nfunction createLogId(record: DeliveryLogRecord): string {\n\tconst base = record.createdAt.replace(/[^0-9]/g, \"\").slice(0, 14);\n\tconst random = Math.random().toString(36).slice(2, 10);\n\treturn `${base}-${record.providerId}-${random}`;\n}\n\nexport async function writeDeliveryLog(\n\tctx: SmtpPluginContextLike,\n\trecord: DeliveryLogRecord,\n): Promise<void> {\n\tconst collection = ctx.storage?.deliveryLogs;\n\tif (!collection?.put) return;\n\n\tconst settings = await getGlobalSettings(ctx);\n\tconst logLevel = settings.logLevel ?? \"all\";\n\tif (logLevel === \"off\") return;\n\tif (logLevel === \"errors\" && record.status !== \"failed\") return;\n\n\tconst id = record.id ?? createLogId(record);\n\tawait collection.put(id, { ...record, id });\n}\n\nexport async function queryRecentDeliveryLogs(\n\tctx: SmtpPluginContextLike,\n\tlimit = 25,\n): Promise<Array<{ id: string; data: DeliveryLogRecord }>> {\n\tconst collection = ctx.storage?.deliveryLogs;\n\tif (!collection?.query) return [];\n\tconst result = await collection.query({ orderBy: { createdAt: \"desc\" }, limit });\n\treturn result.items ?? [];\n}\n\nexport async function countDeliveryLogs(\n\tctx: SmtpPluginContextLike,\n\tstatus: \"sent\" | \"failed\",\n): Promise<number> {\n\tconst collection = ctx.storage?.deliveryLogs;\n\tif (collection?.count) {\n\t\treturn collection.count({ status });\n\t}\n\tif (!collection?.query) return 0;\n\tconst result = await collection.query({ where: { status }, limit: 1000 });\n\treturn result.items.length;\n}\n","import { patchProviderSettings } from \"./storage.js\";\nimport type {\n\tDeliveryMessage,\n\tDeliveryRuntime,\n\tPluginVariant,\n\tProviderDefinition,\n\tProviderFieldDefinition,\n\tProviderSendArgs,\n} from \"./types.js\";\n\nfunction unique(values: string[]): string[] {\n\treturn [...new Set(values.filter(Boolean))].sort();\n}\n\nfunction stringValue(settings: Record<string, unknown>, key: string): string | undefined {\n\tconst value = settings[key];\n\tif (typeof value !== \"string\") return undefined;\n\tconst trimmed = value.trim();\n\treturn trimmed === \"\" ? undefined : trimmed;\n}\n\nfunction numberValue(settings: Record<string, unknown>, key: string, fallback?: number): number | undefined {\n\tconst value = settings[key];\n\tif (typeof value === \"number\" && Number.isFinite(value)) return value;\n\tif (typeof value === \"string\" && value.trim() !== \"\") {\n\t\tconst parsed = Number(value);\n\t\tif (Number.isFinite(parsed)) return parsed;\n\t}\n\treturn fallback;\n}\n\nfunction requireString(settings: Record<string, unknown>, key: string, label: string): string {\n\tconst value = stringValue(settings, key);\n\tif (!value) {\n\t\tthrow new Error(`${label} is required.`);\n\t}\n\treturn value;\n}\n\nfunction sanitizeHeaderText(value: string): string {\n\treturn value.replace(/[\\r\\n]+/g, \" \").replace(/\\s+/g, \" \").trim();\n}\n\nfunction sanitizeEmailAddress(value: string, label: string): string {\n\tconst trimmed = value.trim();\n\tif (!trimmed) {\n\t\tthrow new Error(`${label} is required.`);\n\t}\n\tif (/[\\r\\n]/.test(trimmed)) {\n\t\tthrow new Error(`${label} contains invalid newline characters.`);\n\t}\n\treturn trimmed;\n}\n\nfunction encodeHeaderValue(value: string): string {\n\tconst sanitized = sanitizeHeaderText(value);\n\tif (/^[\\x20-\\x7E]*$/.test(sanitized) && !/[\",]/.test(sanitized)) {\n\t\treturn sanitized;\n\t}\n\treturn `=?UTF-8?B?${toBase64(new TextEncoder().encode(sanitized))}?=`;\n}\n\nfunction formatAddress(email: string, name?: string): string {\n\tconst safeEmail = sanitizeEmailAddress(email, \"Email address\");\n\tconst safeName = name ? encodeHeaderValue(name) : undefined;\n\treturn safeName ? `${safeName} <${safeEmail}>` : safeEmail;\n}\n\nfunction ensureFetch(runtime: DeliveryRuntime): NonNullable<DeliveryRuntime[\"fetch\"]> {\n\tif (!runtime.fetch) {\n\t\tthrow new Error(\"This provider requires network fetch support in the current runtime.\");\n\t}\n\treturn runtime.fetch;\n}\n\nfunction ensureSmtp(runtime: DeliveryRuntime): NonNullable<DeliveryRuntime[\"smtpSend\"]> {\n\tif (!runtime.smtpSend) {\n\t\tthrow new Error(\"Custom SMTP is only available in the trusted package.\");\n\t}\n\treturn runtime.smtpSend;\n}\n\nfunction ensureSendmail(runtime: DeliveryRuntime): NonNullable<DeliveryRuntime[\"sendmailSend\"]> {\n\tif (!runtime.sendmailSend) {\n\t\tthrow new Error(\"Local sendmail is only available in the trusted package.\");\n\t}\n\treturn runtime.sendmailSend;\n}\n\nasync function readResponse(response: Response): Promise<{ text: string; json?: unknown }> {\n\tconst text = await response.text();\n\ttry {\n\t\treturn { text, json: text ? JSON.parse(text) : undefined };\n\t} catch {\n\t\treturn { text };\n\t}\n}\n\nfunction asRecord(value: unknown): Record<string, unknown> | undefined {\n\treturn typeof value === \"object\" && value !== null ? (value as Record<string, unknown>) : undefined;\n}\n\nfunction asArray(value: unknown): unknown[] | undefined {\n\treturn Array.isArray(value) ? value : undefined;\n}\n\nfunction asString(value: unknown): string | undefined {\n\treturn typeof value === \"string\" ? value : undefined;\n}\n\nfunction getPath(value: unknown, ...path: Array<string | number>): unknown {\n\tlet current: unknown = value;\n\tfor (const segment of path) {\n\t\tif (typeof segment === \"number\") {\n\t\t\tconst items = asArray(current);\n\t\t\tif (!items) return undefined;\n\t\t\tcurrent = items[segment];\n\t\t\tcontinue;\n\t\t}\n\t\tconst record = asRecord(current);\n\t\tif (!record) return undefined;\n\t\tcurrent = record[segment];\n\t}\n\treturn current;\n}\n\nclass HttpError extends Error {\n\tstatus: number;\n\tbodyText: string;\n\tbodyJson?: unknown;\n\n\tconstructor(status: number, bodyText: string, bodyJson?: unknown) {\n\t\tsuper(bodyText || `HTTP ${status}`);\n\t\tthis.name = \"HttpError\";\n\t\tthis.status = status;\n\t\tthis.bodyText = bodyText;\n\t\tthis.bodyJson = bodyJson;\n\t}\n}\n\nfunction hasAllSettings(settings: Record<string, unknown>, keys: string[]): boolean {\n\treturn keys.every((key) => Boolean(stringValue(settings, key)));\n}\n\nfunction shouldRetryAfterRefresh(error: unknown): error is HttpError {\n\treturn error instanceof HttpError && (error.status === 401 || error.status === 403);\n}\n\nasync function refreshProviderAccessToken(\n\targs: ProviderSendArgs,\n\ttokenUrl: string,\n\tbody: URLSearchParams,\n\tlabel: string,\n): Promise<string> {\n\tconst { json } = await requestJson({\n\t\turl: tokenUrl,\n\t\truntime: args.runtime,\n\t\tok: [200],\n\t\tinit: {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: {\n\t\t\t\taccept: \"application/json\",\n\t\t\t\t\"content-type\": \"application/x-www-form-urlencoded\",\n\t\t\t},\n\t\t\tbody: body.toString(),\n\t\t},\n\t});\n\tconst accessToken = asString(getPath(json, \"access_token\"));\n\tif (!accessToken) {\n\t\tthrow new Error(`${label} refresh did not return an access token.`);\n\t}\n\tconst refreshToken = asString(getPath(json, \"refresh_token\"));\n\tawait patchProviderSettings(args.ctx, args.providerId, {\n\t\taccessToken,\n\t\t...(refreshToken ? { refreshToken } : {}),\n\t});\n\treturn accessToken;\n}\n\nasync function requestJson(opts: {\n\turl: string;\n\tinit: RequestInit;\n\truntime: DeliveryRuntime;\n\tok?: number[];\n}): Promise<{ response: Response; text: string; json?: unknown }> {\n\tconst fetchFn = ensureFetch(opts.runtime);\n\tconst response = await fetchFn(opts.url, opts.init);\n\tconst result = await readResponse(response);\n\tconst ok = opts.ok ?? [200, 201, 202];\n\tif (!ok.includes(response.status)) {\n\t\tthrow new HttpError(response.status, result.text || `HTTP ${response.status}`, result.json);\n\t}\n\treturn { response, ...result };\n}\n\nfunction toBase64(bytes: Uint8Array): string {\n\tif (typeof Buffer !== \"undefined\") {\n\t\treturn Buffer.from(bytes).toString(\"base64\");\n\t}\n\tlet binary = \"\";\n\tfor (const byte of bytes) binary += String.fromCharCode(byte);\n\treturn btoa(binary);\n}\n\nfunction toBase64Url(text: string): string {\n\tconst bytes = new TextEncoder().encode(text);\n\treturn toBase64(bytes).replace(/\\+/g, \"-\").replace(/\\//g, \"_\").replace(/=+$/g, \"\");\n}\n\nfunction toHex(bytes: Uint8Array): string {\n\treturn Array.from(bytes)\n\t\t.map((byte) => byte.toString(16).padStart(2, \"0\"))\n\t\t.join(\"\");\n}\n\nasync function sha256Hex(payload: string): Promise<string> {\n\tconst digest = await crypto.subtle.digest(\"SHA-256\", new TextEncoder().encode(payload));\n\treturn toHex(new Uint8Array(digest));\n}\n\nasync function hmacSha256Raw(key: string | Uint8Array, data: string): Promise<Uint8Array> {\n\tconst rawKey = typeof key === \"string\" ? new TextEncoder().encode(key) : Uint8Array.from(key);\n\tconst imported = await crypto.subtle.importKey(\n\t\t\"raw\",\n\t\trawKey.buffer,\n\t\t{ name: \"HMAC\", hash: \"SHA-256\" },\n\t\tfalse,\n\t\t[\"sign\"],\n\t);\n\tconst signature = await crypto.subtle.sign(\"HMAC\", imported, new TextEncoder().encode(data));\n\treturn new Uint8Array(signature);\n}\n\nfunction stripHtml(html: string): string {\n\treturn html\n\t\t.replace(/<style[\\s\\S]*?<\\/style>/gi, \"\")\n\t\t.replace(/<script[\\s\\S]*?<\\/script>/gi, \"\")\n\t\t.replace(/<[^>]+>/g, \" \")\n\t\t.replace(/\\s+/g, \" \")\n\t\t.trim();\n}\n\nfunction buildMimeMessage(message: DeliveryMessage): string {\n\tconst from = formatAddress(message.fromEmail || \"\", message.fromName);\n\tconst to = message.to.map((email) => sanitizeEmailAddress(email, \"Recipient email address\")).join(\", \");\n\tconst replyTo = message.replyTo?.length\n\t\t? message.replyTo.map((email) => sanitizeEmailAddress(email, \"Reply-to email address\")).join(\", \")\n\t\t: undefined;\n\tconst subject = encodeHeaderValue(message.subject);\n\tconst headers = [\n\t\t`From: ${from}`,\n\t\t`To: ${to}`,\n\t\t`Subject: ${subject}`,\n\t\t...(replyTo ? [`Reply-To: ${replyTo}`] : []),\n\t\t\"MIME-Version: 1.0\",\n\t];\n\n\tif (message.html) {\n\t\tconst boundary = `emdash-${Math.random().toString(36).slice(2, 12)}`;\n\t\treturn [\n\t\t\t...headers,\n\t\t\t`Content-Type: multipart/alternative; boundary=\"${boundary}\"`,\n\t\t\t\"\",\n\t\t\t`--${boundary}`,\n\t\t\t'Content-Type: text/plain; charset=\"UTF-8\"',\n\t\t\t\"\",\n\t\t\tmessage.text,\n\t\t\t\"\",\n\t\t\t`--${boundary}`,\n\t\t\t'Content-Type: text/html; charset=\"UTF-8\"',\n\t\t\t\"\",\n\t\t\tmessage.html,\n\t\t\t\"\",\n\t\t\t`--${boundary}--`,\n\t\t\t\"\",\n\t\t].join(\"\\r\\n\");\n\t}\n\n\treturn [\n\t\t...headers,\n\t\t'Content-Type: text/plain; charset=\"UTF-8\"',\n\t\t\"\",\n\t\tmessage.text,\n\t\t\"\",\n\t].join(\"\\r\\n\");\n}\n\nasync function signAwsRequest(opts: {\n\taccessKeyId: string;\n\tsecretAccessKey: string;\n\tregion: string;\n\turl: URL;\n\tmethod: string;\n\tpayload: string;\n\theaders?: Record<string, string>;\n}): Promise<Record<string, string>> {\n\tconst now = new Date();\n\tconst amzDate = now.toISOString().replace(/[:-]|\\.\\d{3}/g, \"\");\n\tconst dateStamp = amzDate.slice(0, 8);\n\tconst service = \"ses\";\n\tconst payloadHash = await sha256Hex(opts.payload);\n\tconst baseHeaders: Record<string, string> = {\n\t\t\"content-type\": \"application/x-www-form-urlencoded; charset=utf-8\",\n\t\t\"host\": opts.url.host,\n\t\t\"x-amz-content-sha256\": payloadHash,\n\t\t\"x-amz-date\": amzDate,\n\t\t...(opts.headers ?? {}),\n\t};\n\tconst sortedHeaderKeys = Object.keys(baseHeaders).sort();\n\tconst canonicalHeaders = sortedHeaderKeys\n\t\t.map((key) => `${key}:${(baseHeaders[key] ?? \"\").trim()}\\n`)\n\t\t.join(\"\");\n\tconst signedHeaders = sortedHeaderKeys.join(\";\");\n\tconst canonicalRequest = [\n\t\topts.method,\n\t\topts.url.pathname || \"/\",\n\t\topts.url.search.startsWith(\"?\") ? opts.url.search.slice(1) : opts.url.search,\n\t\tcanonicalHeaders,\n\t\tsignedHeaders,\n\t\tpayloadHash,\n\t].join(\"\\n\");\n\tconst credentialScope = `${dateStamp}/${opts.region}/${service}/aws4_request`;\n\tconst stringToSign = [\n\t\t\"AWS4-HMAC-SHA256\",\n\t\tamzDate,\n\t\tcredentialScope,\n\t\tawait sha256Hex(canonicalRequest),\n\t].join(\"\\n\");\n\tconst kDate = await hmacSha256Raw(`AWS4${opts.secretAccessKey}`, dateStamp);\n\tconst kRegion = await hmacSha256Raw(kDate, opts.region);\n\tconst kService = await hmacSha256Raw(kRegion, service);\n\tconst kSigning = await hmacSha256Raw(kService, \"aws4_request\");\n\tconst signature = toHex(await hmacSha256Raw(kSigning, stringToSign));\n\treturn {\n\t\t...baseHeaders,\n\t\tAuthorization: `AWS4-HMAC-SHA256 Credential=${opts.accessKeyId}/${credentialScope}, SignedHeaders=${signedHeaders}, Signature=${signature}`,\n\t};\n}\n\nfunction getMessageText(message: DeliveryMessage): string {\n\treturn message.text || (message.html ? stripHtml(message.html) : \"\");\n}\n\nasync function sendViaAmazon(args: ProviderSendArgs): Promise<{ remoteMessageId?: string }> {\n\tconst accessKeyId = requireString(args.settings, \"accessKeyId\", \"Access Key ID\");\n\tconst secretAccessKey = requireString(args.settings, \"secretAccessKey\", \"Secret Access Key\");\n\tconst region = requireString(args.settings, \"region\", \"Region\");\n\tconst payload = new URLSearchParams({\n\t\tAction: \"SendRawEmail\",\n\t\tVersion: \"2010-12-01\",\n\t\t\"RawMessage.Data\": toBase64(new TextEncoder().encode(buildMimeMessage(args.message))),\n\t}).toString();\n\tconst url = new URL(`https://email.${region}.amazonaws.com/`);\n\tconst headers = await signAwsRequest({\n\t\taccessKeyId,\n\t\tsecretAccessKey,\n\t\tregion,\n\t\turl,\n\t\tmethod: \"POST\",\n\t\tpayload,\n\t});\n\tconst { text } = await requestJson({\n\t\turl: url.toString(),\n\t\truntime: args.runtime,\n\t\tok: [200],\n\t\tinit: { method: \"POST\", headers, body: payload },\n\t});\n\tconst match = text.match(/<MessageId>([^<]+)<\\/MessageId>/i);\n\treturn { remoteMessageId: match?.[1] };\n}\n\nasync function sendViaBrevo(args: ProviderSendArgs): Promise<{ remoteMessageId?: string }> {\n\tconst apiKey = requireString(args.settings, \"apiKey\", \"API Key\");\n\tconst body: Record<string, unknown> = {\n\t\tsender: {\n\t\t\temail: args.message.fromEmail,\n\t\t\t...(args.message.fromName ? { name: args.message.fromName } : {}),\n\t\t},\n\t\tto: args.message.to.map((email) => ({ email })),\n\t\tsubject: args.message.subject,\n\t\t...(args.message.html ? { htmlContent: args.message.html } : { textContent: args.message.text }),\n\t\t...(args.message.replyTo?.[0] ? { replyTo: { email: args.message.replyTo[0] } } : {}),\n\t};\n\tconst { json } = await requestJson({\n\t\turl: \"https://api.brevo.com/v3/smtp/email\",\n\t\truntime: args.runtime,\n\t\tinit: {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: {\n\t\t\t\taccept: \"application/json\",\n\t\t\t\t\"content-type\": \"application/json\",\n\t\t\t\t\"api-key\": apiKey,\n\t\t\t},\n\t\t\tbody: JSON.stringify(body),\n\t\t},\n\t});\n\tconst record = asRecord(json);\n\treturn { remoteMessageId: asString(record?.messageId) };\n}\n\nasync function sendViaElasticEmail(args: ProviderSendArgs): Promise<{ remoteMessageId?: string }> {\n\tconst apiKey = requireString(args.settings, \"apiKey\", \"API Key\");\n\tconst body: Record<string, unknown> = {\n\t\tRecipients: { To: [...args.message.to] },\n\t\tContent: {\n\t\t\tFrom: formatAddress(args.message.fromEmail || \"\", args.message.fromName),\n\t\t\tSubject: args.message.subject,\n\t\t\tBody: [\n\t\t\t\t{\n\t\t\t\t\tCharset: \"utf-8\",\n\t\t\t\t\tContent: args.message.html || args.message.text,\n\t\t\t\t\tContentType: args.message.html ? \"HTML\" : \"PlainText\",\n\t\t\t\t},\n\t\t\t],\n\t\t\t...(args.message.replyTo?.[0] ? { ReplyTo: args.message.replyTo[0] } : {}),\n\t\t},\n\t};\n\tconst { json } = await requestJson({\n\t\turl: \"https://api.elasticemail.com/v4/emails/transactional\",\n\t\truntime: args.runtime,\n\t\tinit: {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: {\n\t\t\t\taccept: \"application/json\",\n\t\t\t\t\"content-type\": \"application/json\",\n\t\t\t\t\"X-ElasticEmail-ApiKey\": apiKey,\n\t\t\t},\n\t\t\tbody: JSON.stringify(body),\n\t\t},\n\t});\n\tconst record = asRecord(json);\n\treturn { remoteMessageId: asString(record?.TransactionID) ?? asString(record?.MessageID) };\n}\n\nasync function sendViaEmailit(args: ProviderSendArgs): Promise<{ remoteMessageId?: string }> {\n\tconst apiKey = requireString(args.settings, \"apiKey\", \"API Key\");\n\tconst body: Record<string, unknown> = {\n\t\tto: args.message.to.join(\", \"),\n\t\tfrom: formatAddress(args.message.fromEmail || \"\", args.message.fromName),\n\t\tsubject: args.message.subject,\n\t\theaders: {\n\t\t\t...(args.message.replyTo?.[0] ? { \"reply-to\": args.message.replyTo[0] } : {}),\n\t\t},\n\t\t...(args.message.html\n\t\t\t? { html: args.message.html, text: getMessageText(args.message) }\n\t\t\t: { text: args.message.text }),\n\t};\n\tconst { json } = await requestJson({\n\t\turl: \"https://api.emailit.com/v1/emails\",\n\t\truntime: args.runtime,\n\t\tinit: {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: {\n\t\t\t\taccept: \"application/json\",\n\t\t\t\t\"content-type\": \"application/json\",\n\t\t\t\tAuthorization: `Bearer ${apiKey}`,\n\t\t\t},\n\t\t\tbody: JSON.stringify(body),\n\t\t},\n\t});\n\tconst record = asRecord(json);\n\treturn { remoteMessageId: asString(record?.id) ?? asString(record?.message_id) };\n}\n\nasync function sendViaGenericSmtp(args: ProviderSendArgs): Promise<{ remoteMessageId?: string }> {\n\tconst smtpSend = ensureSmtp(args.runtime);\n\tconst host = requireString(args.settings, \"host\", \"SMTP Hostname\");\n\tconst port = numberValue(args.settings, \"port\", 587) ?? 587;\n\tconst security = stringValue(args.settings, \"security\") ?? \"starttls\";\n\treturn smtpSend(\n\t\t{\n\t\t\thost,\n\t\t\tport,\n\t\t\tsecure: security === \"ssl\",\n\t\t\tusername: stringValue(args.settings, \"username\"),\n\t\t\tpassword: stringValue(args.settings, \"password\"),\n\t\t},\n\t\targs.message,\n\t);\n}\n\nasync function resolveGoogleAccessToken(args: ProviderSendArgs, forceRefresh = false): Promise<string> {\n\tconst storedAccessToken = forceRefresh ? undefined : stringValue(args.settings, \"accessToken\");\n\tif (storedAccessToken) return storedAccessToken;\n\tif (!hasAllSettings(args.settings, [\"clientId\", \"clientSecret\", \"refreshToken\"])) {\n\t\tthrow new Error(\"Google requires an access token or client ID, client secret, and refresh token.\");\n\t}\n\treturn refreshProviderAccessToken(\n\t\targs,\n\t\t\"https://oauth2.googleapis.com/token\",\n\t\tnew URLSearchParams({\n\t\t\tclient_id: requireString(args.settings, \"clientId\", \"Client ID\"),\n\t\t\tclient_secret: requireString(args.settings, \"clientSecret\", \"Client Secret\"),\n\t\t\trefresh_token: requireString(args.settings, \"refreshToken\", \"Refresh Token\"),\n\t\t\tgrant_type: \"refresh_token\",\n\t\t}),\n\t\t\"Google\",\n\t);\n}\n\nasync function resolveMicrosoftAccessToken(args: ProviderSendArgs, forceRefresh = false): Promise<string> {\n\tconst storedAccessToken = forceRefresh ? undefined : stringValue(args.settings, \"accessToken\");\n\tif (storedAccessToken) return storedAccessToken;\n\tif (!hasAllSettings(args.settings, [\"clientId\", \"clientSecret\", \"refreshToken\"])) {\n\t\tthrow new Error(\"Microsoft requires an access token or application ID, client secret, and refresh token.\");\n\t}\n\tconst tenantId = stringValue(args.settings, \"tenantId\") ?? \"common\";\n\treturn refreshProviderAccessToken(\n\t\targs,\n\t\t`https://login.microsoftonline.com/${tenantId}/oauth2/v2.0/token`,\n\t\tnew URLSearchParams({\n\t\t\tclient_id: requireString(args.settings, \"clientId\", \"Application ID\"),\n\t\t\tclient_secret: requireString(args.settings, \"clientSecret\", \"Client Secret\"),\n\t\t\trefresh_token: requireString(args.settings, \"refreshToken\", \"Refresh Token\"),\n\t\t\tgrant_type: \"refresh_token\",\n\t\t\tscope: \"email Mail.Send User.Read profile openid offline_access\",\n\t\t}),\n\t\t\"Microsoft\",\n\t);\n}\n\nasync function resolveZohoAccessToken(args: ProviderSendArgs, forceRefresh = false): Promise<string> {\n\tconst storedAccessToken = forceRefresh ? undefined : stringValue(args.settings, \"accessToken\");\n\tif (storedAccessToken) return storedAccessToken;\n\tif (!hasAllSettings(args.settings, [\"clientId\", \"clientSecret\", \"refreshToken\"])) {\n\t\tthrow new Error(\"Zoho requires an access token or client ID, client secret, and refresh token.\");\n\t}\n\tconst body = new URLSearchParams({\n\t\tclient_id: requireString(args.settings, \"clientId\", \"Client ID\"),\n\t\tclient_secret: requireString(args.settings, \"clientSecret\", \"Client Secret\"),\n\t\trefresh_token: requireString(args.settings, \"refreshToken\", \"Refresh Token\"),\n\t\tgrant_type: \"refresh_token\",\n\t});\n\tconst redirectUri = stringValue(args.settings, \"redirectUri\");\n\tif (redirectUri) body.set(\"redirect_uri\", redirectUri);\n\treturn refreshProviderAccessToken(args, \"https://accounts.zoho.com/oauth/v2/token\", body, \"Zoho\");\n}\n\nasync function sendViaGoogle(args: ProviderSendArgs): Promise<{ remoteMessageId?: string }> {\n\tconst raw = toBase64Url(buildMimeMessage(args.message));\n\tconst sendRequest = async (accessToken: string) => {\n\t\tconst { json } = await requestJson({\n\t\t\turl: \"https://gmail.googleapis.com/gmail/v1/users/me/messages/send\",\n\t\t\truntime: args.runtime,\n\t\t\tinit: {\n\t\t\t\tmethod: \"POST\",\n\t\t\t\theaders: {\n\t\t\t\t\tAuthorization: `Bearer ${accessToken}`,\n\t\t\t\t\t\"Content-Type\": \"application/json\",\n\t\t\t\t},\n\t\t\t\tbody: JSON.stringify({ raw }),\n\t\t\t},\n\t\t\tok: [200],\n\t\t});\n\t\tconst record = asRecord(json);\n\t\treturn { remoteMessageId: asString(record?.id) };\n\t};\n\tconst canRefresh = hasAllSettings(args.settings, [\"clientId\", \"clientSecret\", \"refreshToken\"]);\n\ttry {\n\t\treturn await sendRequest(await resolveGoogleAccessToken(args));\n\t} catch (error) {\n\t\tif (!canRefresh || !shouldRetryAfterRefresh(error)) throw error;\n\t\treturn sendRequest(await resolveGoogleAccessToken(args, true));\n\t}\n}\n\nasync function sendViaMailchimp(args: ProviderSendArgs): Promise<{ remoteMessageId?: string }> {\n\tconst apiKey = requireString(args.settings, \"apiKey\", \"API Key\");\n\tconst body = {\n\t\tkey: apiKey,\n\t\tmessage: {\n\t\t\tsubject: args.message.subject,\n\t\t\tfrom_email: args.message.fromEmail,\n\t\t\t...(args.message.fromName ? { from_name: args.message.fromName } : {}),\n\t\t\tto: args.message.to.map((email) => ({ email, type: \"to\" })),\n\t\t\t...(args.message.html\n\t\t\t\t? { html: args.message.html, text: getMessageText(args.message) }\n\t\t\t\t: { text: args.message.text }),\n\t\t\t...(args.message.replyTo?.[0] ? { headers: { \"reply-to\": args.message.replyTo[0] } } : {}),\n\t\t},\n\t};\n\tconst { json } = await requestJson({\n\t\turl: \"https://mandrillapp.com/api/1.0/messages/send\",\n\t\truntime: args.runtime,\n\t\tinit: {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: { \"Content-Type\": \"application/json\" },\n\t\t\tbody: JSON.stringify(body),\n\t\t},\n\t});\n\tconst data = Array.isArray(json) ? json[0] : json;\n\tconst record = asRecord(data);\n\treturn { remoteMessageId: asString(record?._id) ?? asString(record?.id) };\n}\n\nasync function sendViaMailerSend(args: ProviderSendArgs): Promise<{ remoteMessageId?: string }> {\n\tconst apiKey = requireString(args.settings, \"apiKey\", \"API Key\");\n\tconst body: Record<string, unknown> = {\n\t\tsubject: args.message.subject,\n\t\tfrom: {\n\t\t\temail: args.message.fromEmail,\n\t\t\t...(args.message.fromName ? { name: args.message.fromName } : {}),\n\t\t},\n\t\tto: args.message.to.map((email) => ({ email })),\n\t\t...(args.message.html ? { html: args.message.html } : { text: args.message.text }),\n\t\t...(args.message.replyTo?.[0] ? { reply_to: { email: args.message.replyTo[0] } } : {}),\n\t};\n\tconst { json } = await requestJson({\n\t\turl: \"https://api.mailersend.com/v1/email\",\n\t\truntime: args.runtime,\n\t\tinit: {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: {\n\t\t\t\taccept: \"application/json\",\n\t\t\t\t\"content-type\": \"application/json\",\n\t\t\t\tAuthorization: `Bearer ${apiKey}`,\n\t\t\t},\n\t\t\tbody: JSON.stringify(body),\n\t\t},\n\t});\n\tconst record = asRecord(json);\n\treturn { remoteMessageId: asString(record?.message_id) ?? asString(record?.id) };\n}\n\nasync function sendViaMailgun(args: ProviderSendArgs): Promise<{ remoteMessageId?: string }> {\n\tconst apiKey = requireString(args.settings, \"apiKey\", \"Mailgun API Key\");\n\tconst domain = requireString(args.settings, \"domain\", \"Sending Domain\");\n\tconst region = stringValue(args.settings, \"region\") ?? \"us\";\n\tconst base = region === \"eu\" ? \"https://api.eu.mailgun.net/v3\" : \"https://api.mailgun.net/v3\";\n\tconst body = new URLSearchParams({\n\t\tfrom: formatAddress(args.message.fromEmail || \"\", args.message.fromName),\n\t\tto: args.message.to.join(\", \"),\n\t\tsubject: args.message.subject,\n\t\t...(args.message.html ? { html: args.message.html } : {}),\n\t\ttext: getMessageText(args.message),\n\t});\n\tif (args.message.replyTo?.[0]) body.set(\"h:Reply-To\", args.message.replyTo[0]);\n\tconst basic = toBase64(new TextEncoder().encode(`api:${apiKey}`));\n\tconst { json } = await requestJson({\n\t\turl: `${base}/${domain}/messages`,\n\t\truntime: args.runtime,\n\t\tinit: {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: { Authorization: `Basic ${basic}` },\n\t\t\tbody: body,\n\t\t},\n\t\tok: [200],\n\t});\n\tconst record = asRecord(json);\n\treturn { remoteMessageId: asString(record?.id) };\n}\n\nasync function sendViaMailjet(args: ProviderSendArgs): Promise<{ remoteMessageId?: string }> {\n\tconst apiKey = requireString(args.settings, \"apiKey\", \"API Key\");\n\tconst apiSecret = requireString(args.settings, \"apiSecret\", \"API Secret Key\");\n\tconst body = {\n\t\tMessages: [\n\t\t\t{\n\t\t\t\tTo: args.message.to.map((email) => ({ Email: email })),\n\t\t\t\tFrom: {\n\t\t\t\t\tEmail: args.message.fromEmail,\n\t\t\t\t\t...(args.message.fromName ? { Name: args.message.fromName } : {}),\n\t\t\t\t},\n\t\t\t\tSubject: args.message.subject,\n\t\t\t\t...(args.message.html\n\t\t\t\t\t? { HTMLPart: args.message.html, TextPart: getMessageText(args.message) }\n\t\t\t\t\t: { TextPart: args.message.text }),\n\t\t\t\t...(args.message.replyTo?.[0]\n\t\t\t\t\t? { Headers: { \"Reply-To\": args.message.replyTo[0] } }\n\t\t\t\t\t: {}),\n\t\t\t},\n\t\t],\n\t};\n\tconst basic = toBase64(new TextEncoder().encode(`${apiKey}:${apiSecret}`));\n\tconst { json } = await requestJson({\n\t\turl: \"https://api.mailjet.com/v3.1/send\",\n\t\truntime: args.runtime,\n\t\tinit: {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: {\n\t\t\t\taccept: \"application/json\",\n\t\t\t\t\"content-type\": \"application/json\",\n\t\t\t\tAuthorization: `Basic ${basic}`,\n\t\t\t},\n\t\t\tbody: JSON.stringify(body),\n\t\t},\n\t});\n\tconst record = asRecord(json);\n\treturn { remoteMessageId: asString(getPath(record, \"Messages\", 0, \"To\", 0, \"MessageUUID\")) };\n}\n\nasync function sendViaMicrosoft(args: ProviderSendArgs): Promise<{ remoteMessageId?: string }> {\n\tconst sendRequest = async (accessToken: string) => {\n\t\tawait requestJson({\n\t\t\turl: \"https://graph.microsoft.com/v1.0/me/sendMail\",\n\t\t\truntime: args.runtime,\n\t\t\tok: [202],\n\t\t\tinit: {\n\t\t\t\tmethod: \"POST\",\n\t\t\t\theaders: {\n\t\t\t\t\tAuthorization: `Bearer ${accessToken}`,\n\t\t\t\t\t\"content-type\": \"application/json\",\n\t\t\t\t},\n\t\t\t\tbody: JSON.stringify({\n\t\t\t\t\tmessage: {\n\t\t\t\t\t\tsubject: args.message.subject,\n\t\t\t\t\t\tbody: {\n\t\t\t\t\t\t\tcontentType: args.message.html ? \"HTML\" : \"Text\",\n\t\t\t\t\t\t\tcontent: args.message.html || args.message.text,\n\t\t\t\t\t\t},\n\t\t\t\t\t\ttoRecipients: args.message.to.map((email) => ({ emailAddress: { address: email } })),\n\t\t\t\t\t\t...(args.message.replyTo?.[0]\n\t\t\t\t\t\t\t? { replyTo: [{ emailAddress: { address: args.message.replyTo[0] } }] }\n\t\t\t\t\t\t\t: {}),\n\t\t\t\t\t},\n\t\t\t\t\tsaveToSentItems: false,\n\t\t\t\t}),\n\t\t\t},\n\t\t});\n\t\treturn {};\n\t};\n\tconst canRefresh = hasAllSettings(args.settings, [\"clientId\", \"clientSecret\", \"refreshToken\"]);\n\ttry {\n\t\treturn await sendRequest(await resolveMicrosoftAccessToken(args));\n\t} catch (error) {\n\t\tif (!canRefresh || !shouldRetryAfterRefresh(error)) throw error;\n\t\treturn sendRequest(await resolveMicrosoftAccessToken(args, true));\n\t}\n}\n\nasync function sendViaPhpMail(args: ProviderSendArgs): Promise<{ remoteMessageId?: string }> {\n\tconst sendmailSend = ensureSendmail(args.runtime);\n\treturn sendmailSend(\n\t\t{\n\t\t\tsendmailPath: stringValue(args.settings, \"sendmailPath\") ?? \"sendmail\",\n\t\t\tfromEmail: args.message.fromEmail || \"\",\n\t\t\tfromName: args.message.fromName,\n\t\t},\n\t\targs.message,\n\t);\n}\n\nasync function sendViaPostmark(args: ProviderSendArgs): Promise<{ remoteMessageId?: string }> {\n\tconst serverApiToken = requireString(args.settings, \"serverApiToken\", \"Server API Token\");\n\tconst body: Record<string, unknown> = {\n\t\tfrom: formatAddress(args.message.fromEmail || \"\", args.message.fromName),\n\t\tto: args.message.to.join(\",\"),\n\t\tsubject: args.message.subject,\n\t\ttextBody: getMessageText(args.message),\n\t\t...(args.message.html ? { htmlBody: args.message.html } : {}),\n\t\t...(args.message.replyTo?.[0] ? { ReplyTo: args.message.replyTo[0] } : {}),\n\t};\n\tconst { json } = await requestJson({\n\t\turl: \"https://api.postmarkapp.com/email\",\n\t\truntime: args.runtime,\n\t\tok: [200],\n\t\tinit: {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: {\n\t\t\t\tAccept: \"application/json\",\n\t\t\t\t\"Content-Type\": \"application/json\",\n\t\t\t\t\"X-Postmark-Server-Token\": serverApiToken,\n\t\t\t},\n\t\t\tbody: JSON.stringify(body),\n\t\t},\n\t});\n\tconst record = asRecord(json);\n\treturn { remoteMessageId: asString(record?.MessageID) };\n}\n\nasync function sendViaResend(args: ProviderSendArgs): Promise<{ remoteMessageId?: string }> {\n\tconst apiKey = requireString(args.settings, \"apiKey\", \"API Key\");\n\tconst body: Record<string, unknown> = {\n\t\tto: [...args.message.to],\n\t\tfrom: formatAddress(args.message.fromEmail || \"\", args.message.fromName),\n\t\tsubject: args.message.subject,\n\t\t...(args.message.html\n\t\t\t? { html: args.message.html, text: getMessageText(args.message) }\n\t\t\t: { text: args.message.text }),\n\t\t...(args.message.replyTo?.[0] ? { reply_to: args.message.replyTo[0] } : {}),\n\t};\n\tconst { json } = await requestJson({\n\t\turl: \"https://api.resend.com/emails\",\n\t\truntime: args.runtime,\n\t\tinit: {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: {\n\t\t\t\taccept: \"application/json\",\n\t\t\t\t\"content-type\": \"application/json\",\n\t\t\t\tAuthorization: `Bearer ${apiKey}`,\n\t\t\t},\n\t\t\tbody: JSON.stringify(body),\n\t\t},\n\t});\n\tconst record = asRecord(json);\n\treturn { remoteMessageId: asString(record?.id) };\n}\n\nasync function sendViaSendgrid(args: ProviderSendArgs): Promise<{ remoteMessageId?: string }> {\n\tconst apiKey = requireString(args.settings, \"apiKey\", \"SendGrid API Key\");\n\tawait requestJson({\n\t\turl: \"https://api.sendgrid.com/v3/mail/send\",\n\t\truntime: args.runtime,\n\t\tok: [202],\n\t\tinit: {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: {\n\t\t\t\tAuthorization: `Bearer ${apiKey}`,\n\t\t\t\t\"Content-Type\": \"application/json\",\n\t\t\t},\n\t\t\tbody: JSON.stringify({\n\t\t\t\tfrom: {\n\t\t\t\t\temail: args.message.fromEmail,\n\t\t\t\t\t...(args.message.fromName ? { name: args.message.fromName } : {}),\n\t\t\t\t},\n\t\t\t\tpersonalizations: [\n\t\t\t\t\t{\n\t\t\t\t\t\tto: args.message.to.map((email) => ({ email })),\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\tsubject: args.message.subject,\n\t\t\t\tcontent: [\n\t\t\t\t\t{\n\t\t\t\t\t\ttype: args.message.html ? \"text/html\" : \"text/plain\",\n\t\t\t\t\t\tvalue: args.message.html || args.message.text,\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\t...(args.message.replyTo?.length\n\t\t\t\t\t? { reply_to_list: args.message.replyTo.map((email) => ({ email })) }\n\t\t\t\t\t: {}),\n\t\t\t}),\n\t\t},\n\t});\n\treturn {};\n}\n\nasync function sendViaSmtp2go(args: ProviderSendArgs): Promise<{ remoteMessageId?: string }> {\n\tconst apiKey = requireString(args.settings, \"apiKey\", \"API Key\");\n\tconst body: Record<string, unknown> = {\n\t\tsender: formatAddress(args.message.fromEmail || \"\", args.message.fromName),\n\t\tsubject: args.message.subject,\n\t\tto: [...args.message.to],\n\t\t...(args.message.html ? { html_body: args.message.html } : { text_body: args.message.text }),\n\t};\n\tif (args.message.replyTo?.[0]) {\n\t\tbody.custom_headers = [{ header: \"Reply-To\", value: args.message.replyTo[0] }];\n\t}\n\tconst { json } = await requestJson({\n\t\turl: \"https://api.smtp2go.com/v3/email/send\",\n\t\truntime: args.runtime,\n\t\tinit: {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: {\n\t\t\t\taccept: \"application/json\",\n\t\t\t\t\"content-type\": \"application/json\",\n\t\t\t\t\"X-Smtp2go-Api-Key\": apiKey,\n\t\t\t},\n\t\t\tbody: JSON.stringify(body),\n\t\t},\n\t});\n\tconst record = asRecord(json);\n\treturn { remoteMessageId: asString(getPath(record, \"data\", \"email_id\")) ?? asString(record?.request_id) };\n}\n\nasync function sendViaSparkpost(args: ProviderSendArgs): Promise<{ remoteMessageId?: string }> {\n\tconst apiKey = requireString(args.settings, \"apiKey\", \"API Key\");\n\tconst accountLocation = stringValue(args.settings, \"accountLocation\") ?? \"us\";\n\tconst base = accountLocation === \"eu\"\n\t\t? \"https://api.eu.sparkpost.com/api/v1\"\n\t\t: \"https://api.sparkpost.com/api/v1\";\n\tconst body: Record<string, unknown> = {\n\t\trecipients: args.message.to.map((email) => ({ address: { email } })),\n\t\tcontent: {\n\t\t\tfrom: {\n\t\t\t\temail: args.message.fromEmail,\n\t\t\t\t...(args.message.fromName ? { name: args.message.fromName } : {}),\n\t\t\t},\n\t\t\tsubject: args.message.subject,\n\t\t\t...(args.message.html ? { html: args.message.html } : { text: args.message.text }),\n\t\t\t...(args.message.replyTo?.[0] ? { reply_to: args.message.replyTo[0] } : {}),\n\t\t},\n\t\toptions: { transactional: true },\n\t};\n\tconst { json } = await requestJson({\n\t\turl: `${base}/transmissions/`,\n\t\truntime: args.runtime,\n\t\tinit: {\n\t\t\tmethod: \"POST\",\n\t\t\theaders: {\n\t\t\t\taccept: \"application/json\",\n\t\t\t\t\"content-type\": \"application/json\",\n\t\t\t\tAuthorization: apiKey,\n\t\t\t},\n\t\t\tbody: JSON.stringify(body),\n\t\t},\n\t});\n\tconst record = asRecord(json);\n\treturn { remoteMessageId: asString(getPath(record, \"results\", \"id\")) };\n}\n\nfunction getZohoBaseUrl(region: string): string {\n\tswitch (region) {\n\t\tcase \"eu\":\n\t\t\treturn \"https://mail.zoho.eu\";\n\t\tcase \"in\":\n\t\t\treturn \"https://mail.zoho.in\";\n\t\tcase \"com.au\":\n\t\t\treturn \"https://mail.zoho.com.au\";\n\t\tcase \"jp\":\n\t\t\treturn \"https://mail.zoho.jp\";\n\t\tcase \"sa\":\n\t\t\treturn \"https://mail.zoho.sa\";\n\t\tcase \"ca\":\n\t\t\treturn \"https://mail.zohocloud.ca\";\n\t\tcase \"us\":\n\t\tdefault:\n\t\t\treturn \"https://mail.zoho.com\";\n\t}\n}\n\nasync function sendViaZoho(args: ProviderSendArgs): Promise<{ remoteMessageId?: string }> {\n\tconst accountId = requireString(args.settings, \"accountId\", \"Account ID\");\n\tconst region = stringValue(args.settings, \"dataCenterRegion\") ?? \"us\";\n\tconst body: Record<string, unknown> = {\n\t\tfromAddress: args.message.fromEmail,\n\t\ttoAddress: args.message.to.join(\",\"),\n\t\tsubject: args.message.subject,\n\t\tcontent: args.message.html || args.message.text,\n\t\tencoding: \"UTF-8\",\n\t\tmailFormat: args.message.html ? \"html\" : \"plaintext\",\n\t\t...(args.message.replyTo?.[0] ? { replyToAddress: args.message.replyTo[0] } : {}),\n\t};\n\tconst sendRequest = async (accessToken: string) => {\n\t\tconst { json } = await requestJson({\n\t\t\turl: `${getZohoBaseUrl(region)}/api/accounts/${accountId}/messages`,\n\t\t\truntime: args.runtime,\n\t\t\tinit: {\n\t\t\t\tmethod: \"POST\",\n\t\t\t\theaders: {\n\t\t\t\t\tAuthorization: `Zoho-oauthtoken ${accessToken}`,\n\t\t\t\t\t\"Content-Type\": \"application/json\",\n\t\t\t\t},\n\t\t\t\tbody: JSON.stringify(body),\n\t\t\t},\n\t\t});\n\t\tconst record = asRecord(json);\n\t\treturn {\n\t\t\tremoteMessageId:\n\t\t\t\tasString(getPath(record, \"data\", \"messageId\")) ?? asString(getPath(record, \"data\", \"message_id\")),\n\t\t};\n\t};\n\tconst canRefresh = hasAllSettings(args.settings, [\"clientId\", \"clientSecret\", \"refreshToken\"]);\n\ttry {\n\t\treturn await sendRequest(await resolveZohoAccessToken(args));\n\t} catch (error) {\n\t\tif (!canRefresh || !shouldRetryAfterRefresh(error)) throw error;\n\t\treturn sendRequest(await resolveZohoAccessToken(args, true));\n\t}\n}\n\nfunction option(label: string, value: string): { label: string; value: string } {\n\treturn { label, value };\n}\n\nfunction fields(...defs: ProviderFieldDefinition[]): ProviderFieldDefinition[] {\n\treturn defs;\n}\n\nexport const SMTP_PROVIDER_DEFINITIONS: ProviderDefinition[] = [\n\t{\n\t\tid: \"amazon\",\n\t\tlabel: \"Amazon SES\",\n\t\tdescription: \"Amazon Simple Email Service using signed AWS API requests.\",\n\t\tavailability: { trusted: true, marketplace: true },\n\t\tallowedHosts: [\"*.amazonaws.com\"],\n\t\tfields: fields(\n\t\t\t{ key: \"accessKeyId\", label: \"Access Key ID\", type: \"secret\", required: true },\n\t\t\t{ key: \"secretAccessKey\", label: \"Secret Access Key\", type: \"secret\", required: true },\n\t\t\t{\n\t\t\t\tkey: \"region\",\n\t\t\t\tlabel: \"Region\",\n\t\t\t\ttype: \"select\",\n\t\t\t\trequired: true,\n\t\t\t\tdefaultValue: \"us-east-1\",\n\t\t\t\toptions: [\n\t\t\t\t\toption(\"US East (N. Virginia)\", \"us-east-1\"),\n\t\t\t\t\toption(\"US East (Ohio)\", \"us-east-2\"),\n\t\t\t\t\toption(\"US West (N. California)\", \"us-west-1\"),\n\t\t\t\t\toption(\"US West (Oregon)\", \"us-west-2\"),\n\t\t\t\t\toption(\"Europe (Ireland)\", \"eu-west-1\"),\n\t\t\t\t\toption(\"Europe (Frankfurt)\", \"eu-central-1\"),\n\t\t\t\t\toption(\"Europe (London)\", \"eu-west-2\"),\n\t\t\t\t\toption(\"Asia Pacific (Sydney)\", \"ap-southeast-2\"),\n\t\t\t\t\toption(\"Asia Pacific (Singapore)\", \"ap-southeast-1\"),\n\t\t\t\t],\n\t\t\t},\n\t\t),\n\t\tsend: sendViaAmazon,\n\t},\n\t{\n\t\tid: \"brevo\",\n\t\tlabel: \"Brevo\",\n\t\tdescription: \"Transactional email via the Brevo SMTP API.\",\n\t\tavailability: { trusted: true, marketplace: true },\n\t\tallowedHosts: [\"api.brevo.com\"],\n\t\tfields: fields({ key: \"apiKey\", label: \"API Key\", type: \"secret\", required: true }),\n\t\tsend: sendViaBrevo,\n\t},\n\t{\n\t\tid: \"elastic_email\",\n\t\tlabel: \"Elastic Email\",\n\t\tdescription: \"Transactional email via the Elastic Email v4 API.\",\n\t\tavailability: { trusted: true, marketplace: true },\n\t\tallowedHosts: [\"api.elasticemail.com\"],\n\t\tfields: fields({ key: \"apiKey\", label: \"API Key\", type: \"secret\", required: true }),\n\t\tsend: sendViaElasticEmail,\n\t},\n\t{\n\t\tid: \"emailit\",\n\t\tlabel: \"Emailit\",\n\t\tdescription: \"Transactional email via the Emailit API.\",\n\t\tavailability: { trusted: true, marketplace: true },\n\t\tallowedHosts: [\"api.emailit.com\"],\n\t\tfields: fields({ key: \"apiKey\", label: \"API Key\", type: \"secret\", required: true }),\n\t\tsend: sendViaEmailit,\n\t},\n\t{\n\t\tid: \"generic\",\n\t\tlabel: \"Generic SMTP\",\n\t\tdescription: \"Custom SMTP server using Nodemailer in the trusted package.\",\n\t\tavailability: { trusted: true, marketplace: false },\n\t\tallowedHosts: [],\n\t\tfields: fields(\n\t\t\t{ key: \"host\", label: \"SMTP Hostname\", type: \"text\", required: true, placeholder: \"smtp.example.com\" },\n\t\t\t{ key: \"port\", label: \"SMTP Port\", type: \"number\", required: true, defaultValue: 587 },\n\t\t\t{\n\t\t\t\tkey: \"security\",\n\t\t\t\tlabel: \"Encryption\",\n\t\t\t\ttype: \"select\",\n\t\t\t\tdefaultValue: \"starttls\",\n\t\t\t\toptions: [option(\"STARTTLS / Auto\", \"starttls\"), option(\"SSL/TLS\", \"ssl\"), option(\"None\", \"none\")],\n\t\t\t},\n\t\t\t{ key: \"username\", label: \"Authentication Username\", type: \"text\" },\n\t\t\t{ key: \"password\", label: \"Authentication Password\", type: \"secret\" },\n\t\t),\n\t\tsend: sendViaGenericSmtp,\n\t},\n\t{\n\t\tid: \"google\",\n\t\tlabel: \"Google / Gmail\",\n\t\tdescription: \"Gmail API delivery using an access token or refresh-token credentials.\",\n\t\tavailability: { trusted: true, marketplace: true },\n\t\tallowedHosts: [\"gmail.googleapis.com\", \"oauth2.googleapis.com\"],\n\t\tfields: fields(\n\t\t\t{ key: \"accessToken\", label: \"Access Token\", type: \"secret\" },\n\t\t\t{ key: \"refreshToken\", label: \"Refresh Token\", type: \"secret\" },\n\t\t\t{ key: \"clientId\", label: \"Client ID\", type: \"text\" },\n\t\t\t{ key: \"clientSecret\", label: \"Client Secret\", type: \"secret\" },\n\t\t),\n\t\tisConfigured: (settings) =>\n\t\t\tBoolean(stringValue(settings, \"accessToken\")) ||\n\t\t\thasAllSettings(settings, [\"clientId\", \"clientSecret\", \"refreshToken\"]),\n\t\tsend: sendViaGoogle,\n\t},\n\t{\n\t\tid: \"mailchimp\",\n\t\tlabel: \"Mailchimp Transactional\",\n\t\tdescription: \"Mandrill/Mailchimp Transactional email delivery.\",\n\t\tavailability: { trusted: true, marketplace: true },\n\t\tallowedHosts: [\"mandrillapp.com\"],\n\t\tfields: fields({ key: \"apiKey\", label: \"API Key\", type: \"secret\", required: true }),\n\t\tsend: sendViaMailchimp,\n\t},\n\t{\n\t\tid: \"mailersend\",\n\t\tlabel: \"MailerSend\",\n\t\tdescription: \"Transactional email via the MailerSend API.\",\n\t\tavailability: { trusted: true, marketplace: true },\n\t\tallowedHosts: [\"api.mailersend.com\"],\n\t\tfields: fields({ key: \"apiKey\", label: \"API Key\", type: \"secret\", required: true }),\n\t\tsend: sendViaMailerSend,\n\t},\n\t{\n\t\tid: \"mailgun\",\n\t\tlabel: \"Mailgun\",\n\t\tdescription: \"Transactional email via the Mailgun Messages API.\",\n\t\tavailability: { trusted: true, marketplace: true },\n\t\tallowedHosts: [\"api.mailgun.net\", \"api.eu.mailgun.net\"],\n\t\tfields: fields(\n\t\t\t{ key: \"apiKey\", label: \"Mailgun API Key\", type: \"secret\", required: true },\n\t\t\t{ key: \"domain\", label: \"Sending Domain\", type: \"text\", required: true, placeholder: \"mg.example.com\" },\n\t\t\t{\n\t\t\t\tkey: \"region\",\n\t\t\t\tlabel: \"Region\",\n\t\t\t\ttype: \"select\",\n\t\t\t\tdefaultValue: \"us\",\n\t\t\t\toptions: [option(\"US\", \"us\"), option(\"EU\", \"eu\")],\n\t\t\t},\n\t\t),\n\t\tsend: sendViaMailgun,\n\t},\n\t{\n\t\tid: \"mailjet\",\n\t\tlabel: \"Mailjet\",\n\t\tdescription: \"Transactional email via the Mailjet v3.1 API.\",\n\t\tavailability: { trusted: true, marketplace: true },\n\t\tallowedHosts: [\"api.mailjet.com\"],\n\t\tfields: fields(\n\t\t\t{ key: \"apiKey\", label: \"API Key\", type: \"secret\", required: true },\n\t\t\t{ key: \"apiSecret\", label: \"API Secret Key\", type: \"secret\", required: true },\n\t\t),\n\t\tsend: sendViaMailjet,\n\t},\n\t{\n\t\tid: \"microsoft\",\n\t\tlabel: \"365 / Outlook\",\n\t\tdescription: \"Microsoft Graph delivery using an access token or refresh-token credentials.\",\n\t\tavailability: { trusted: true, marketplace: true },\n\t\tallowedHosts: [\"graph.microsoft.com\", \"login.microsoftonline.com\"],\n\t\tfields: fields(\n\t\t\t{ key: \"accessToken\", label: \"Access Token\", type: \"secret\" },\n\t\t\t{ key: \"refreshToken\", label: \"Refresh Token\", type: \"secret\" },\n\t\t\t{ key: \"clientId\", label: \"Application ID\", type: \"text\" },\n\t\t\t{ key: \"clientSecret\", label: \"Client Secret\", type: \"secret\" },\n\t\t\t{ key: \"tenantId\", label: \"Tenant ID\", type: \"text\", defaultValue: \"common\", placeholder: \"common\" },\n\t\t),\n\t\tisConfigured: (settings) =>\n\t\t\tBoolean(stringValue(settings, \"accessToken\")) ||\n\t\t\thasAllSettings(settings, [\"clientId\", \"clientSecret\", \"refreshToken\"]),\n\t\tsend: sendViaMicrosoft,\n\t},\n\t{\n\t\tid: \"phpmail\",\n\t\tlabel: \"PHP Mail / local sendmail\",\n\t\tdescription: \"Local sendmail transport for trusted installs.\",\n\t\tavailability: { trusted: true, marketplace: false },\n\t\tallowedHosts: [],\n\t\tfields: fields({ key: \"sendmailPath\", label: \"Sendmail Path\", type: \"text\", defaultValue: \"sendmail\" }),\n\t\tsend: sendViaPhpMail,\n\t},\n\t{\n\t\tid: \"postmark\",\n\t\tlabel: \"Postmark\",\n\t\tdescription: \"Transactional email via the Postmark send email endpoint.\",\n\t\tavailability: { trusted: true, marketplace: true },\n\t\tallowedHosts: [\"api.postmarkapp.com\"],\n\t\tfields: fields({ key: \"serverApiToken\", label: \"Server API Token\", type: \"secret\", required: true }),\n\t\tsend: sendViaPostmark,\n\t},\n\t{\n\t\tid: \"resend\",\n\t\tlabel: \"Resend\",\n\t\tdescription: \"Transactional email via the Resend API.\",\n\t\tavailability: { trusted: true, marketplace: true },\n\t\tallowedHosts: [\"api.resend.com\"],\n\t\tfields: fields({ key: \"apiKey\", label: \"API Key\", type: \"secret\", required: true }),\n\t\tsend: sendViaResend,\n\t},\n\t{\n\t\tid: \"sendgrid\",\n\t\tlabel: \"SendGrid\",\n\t\tdescription: \"Transactional email via Twilio SendGrid.\",\n\t\tavailability: { trusted: true, marketplace: true },\n\t\tallowedHosts: [\"api.sendgrid.com\"],\n\t\tfields: fields({ key: \"apiKey\", label: \"SendGrid API Key\", type: \"secret\", required: true }),\n\t\tsend: sendViaSendgrid,\n\t},\n\t{\n\t\tid: \"smtp2go\",\n\t\tlabel: \"SMTP2GO\",\n\t\tdescription: \"Transactional email via SMTP2GO's HTTP API.\",\n\t\tavailability: { trusted: true, marketplace: true },\n\t\tallowedHosts: [\"api.smtp2go.com\"],\n\t\tfields: fields({ key: \"apiKey\", label: \"API Key\", type: \"secret\", required: true }),\n\t\tsend: sendViaSmtp2go,\n\t},\n\t{\n\t\tid: \"sparkpost\",\n\t\tlabel: \"SparkPost\",\n\t\tdescription: \"Transactional email via the SparkPost Transmissions API.\",\n\t\tavailability: { trusted: true, marketplace: true },\n\t\tallowedHosts: [\"api.sparkpost.com\", \"api.eu.sparkpost.com\"],\n\t\tfields: fields(\n\t\t\t{\n\t\t\t\tkey: \"accountLocation\",\n\t\t\t\tlabel: \"Account Location\",\n\t\t\t\ttype: \"select\",\n\t\t\t\tdefaultValue: \"us\",\n\t\t\t\toptions: [option(\"United States\", \"us\"), option(\"Europe\", \"eu\")],\n\t\t\t},\n\t\t\t{ key: \"apiKey\", label: \"API Key\", type: \"secret\", required: true },\n\t\t),\n\t\tsend: sendViaSparkpost,\n\t},\n\t{\n\t\tid: \"zoho\",\n\t\tlabel: \"Zoho Mail\",\n\t\tdescription: \"Zoho Mail API delivery using an access token or refresh-token credentials.\",\n\t\tavailability: { trusted: true, marketplace: true },\n\t\tallowedHosts: [\n\t\t\t\"mail.zoho.com\",\n\t\t\t\"mail.zoho.eu\",\n\t\t\t\"mail.zoho.in\",\n\t\t\t\"mail.zoho.com.au\",\n\t\t\t\"mail.zoho.jp\",\n\t\t\t\"mail.zoho.sa\",\n\t\t\t\"mail.zohocloud.ca\",\n\t\t\t\"accounts.zoho.com\",\n\t\t],\n\t\tfields: fields(\n\t\t\t{\n\t\t\t\tkey: \"dataCenterRegion\",\n\t\t\t\tlabel: \"Datacenter Region\",\n\t\t\t\ttype: \"select\",\n\t\t\t\tdefaultValue: \"us\",\n\t\t\t\toptions: [\n\t\t\t\t\toption(\"United States\", \"us\"),\n\t\t\t\t\toption(\"Europe\", \"eu\"),\n\t\t\t\t\toption(\"India\", \"in\"),\n\t\t\t\t\toption(\"Australia\", \"com.au\"),\n\t\t\t\t\toption(\"Japan\", \"jp\"),\n\t\t\t\t\toption(\"Saudi Arabia\", \"sa\"),\n\t\t\t\t\toption(\"Canada\", \"ca\"),\n\t\t\t\t],\n\t\t\t},\n\t\t\t{ key: \"clientId\", label: \"Client ID\", type: \"text\" },\n\t\t\t{ key: \"clientSecret\", label: \"Client Secret\", type: \"secret\" },\n\t\t\t{ key: \"refreshToken\", label: \"Refresh Token\", type: \"secret\" },\n\t\t\t{ key: \"accessToken\", label: \"Access Token\", type: \"secret\" },\n\t\t\t{ key: \"redirectUri\", label: \"Redirect URI\", type: \"text\", placeholder: \"Optional unless required by your token setup\" },\n\t\t\t{ key: \"accountId\", label: \"Account ID\", type: \"text\", required: true },\n\t\t),\n\t\tisConfigured: (settings) =>\n\t\t\tBoolean(stringValue(settings, \"accountId\")) &&\n\t\t\t(Boolean(stringValue(settings, \"accessToken\")) ||\n\t\t\t\thasAllSettings(settings, [\"clientId\", \"clientSecret\", \"refreshToken\"])),\n\t\tsend: sendViaZoho,\n\t},\n];\n\nexport function getProviderById(providerId: string): ProviderDefinition | undefined {\n\treturn SMTP_PROVIDER_DEFINITIONS.find((provider) => provider.id === providerId);\n}\n\nexport function isProviderAvailable(provider: ProviderDefinition, variant: PluginVariant): boolean {\n\treturn provider.availability[variant];\n}\n\nexport function isProviderConfigured(\n\tprovider: ProviderDefinition,\n\tsettings: Record<string, unknown>,\n): boolean {\n\tif (provider.isConfigured) {\n\t\treturn provider.isConfigured(settings);\n\t}\n\treturn provider.fields.every((field) => {\n\t\tif (!field.required) return true;\n\t\tif (field.type === \"number\") return numberValue(settings, field.key) !== undefined;\n\t\tif (field.type === \"toggle\") return settings[field.key] !== undefined;\n\t\treturn Boolean(stringValue(settings, field.key));\n\t});\n}\n\nexport function getProviderLabel(providerId: string | undefined): string {\n\tif (!providerId) return \"Not configured\";\n\treturn getProviderById(providerId)?.label ?? providerId;\n}\n\nexport function getAvailableProviderSelectOptions(variant: PluginVariant): Array<{ label: string; value: string }> {\n\treturn SMTP_PROVIDER_DEFINITIONS.filter((provider) => isProviderAvailable(provider, variant)).map((provider) => ({\n\t\tlabel: provider.label,\n\t\tvalue: provider.id,\n\t}));\n}\n\nexport function getProviderPickerOptions(variant: PluginVariant): Array<{ label: string; value: string }> {\n\treturn SMTP_PROVIDER_DEFINITIONS.map((provider) => ({\n\t\tlabel: isProviderAvailable(provider, variant) ? provider.label : `${provider.label} (trusted-only)`,\n\t\tvalue: provider.id,\n\t}));\n}\n\nexport function collectAllowedHosts(variant: PluginVariant): string[] {\n\treturn unique(\n\t\tSMTP_PROVIDER_DEFINITIONS.filter((provider) => isProviderAvailable(provider, variant)).flatMap(\n\t\t\t(provider) => provider.allowedHosts,\n\t\t),\n\t);\n}\n","import {\n\tgetAvailableProviderSelectOptions,\n\tgetProviderById,\n\tisProviderAvailable,\n\tisProviderConfigured,\n\tSMTP_PROVIDER_DEFINITIONS,\n} from \"./providers.js\";\nimport { getGlobalSettings, getProviderSettings } from \"./storage.js\";\nimport type {\n\tDeliveryMessage,\n\tDeliveryResult,\n\tDeliveryRuntime,\n\tGlobalSettings,\n\tProviderDefinition,\n\tSmtpPluginContextLike,\n} from \"./types.js\";\n\nfunction trimmed(value: string | undefined): string | undefined {\n\tif (!value) return undefined;\n\tconst next = value.trim();\n\treturn next === \"\" ? undefined : next;\n}\n\nfunction stripHtml(html: string): string {\n\treturn html\n\t\t.replace(/<style[\\s\\S]*?<\\/style>/gi, \"\")\n\t\t.replace(/<script[\\s\\S]*?<\\/script>/gi, \"\")\n\t\t.replace(/<[^>]+>/g, \" \")\n\t\t.replace(/\\s+/g, \" \")\n\t\t.trim();\n}\n\nfunction normalizeMessageInput(\n\tmessage: {\n\t\tto: string | string[];\n\t\tsubject: string;\n\t\ttext: string;\n\t\thtml?: string;\n\t},\n\tsettings: GlobalSettings,\n): DeliveryMessage {\n\tconst to = (Array.isArray(message.to) ? message.to : String(message.to).split(\",\"))\n\t\t.map((entry) => entry.trim())\n\t\t.filter(Boolean);\n\tif (to.length === 0) {\n\t\tthrow new Error(\"At least one recipient email address is required.\");\n\t}\n\tconst fromEmail = trimmed(settings.fromEmail);\n\tif (!fromEmail) {\n\t\tthrow new Error(\"A default from email must be configured before sending.\");\n\t}\n\tconst text = trimmed(message.text) ?? (message.html ? stripHtml(message.html) : \"\");\n\tif (!text && !trimmed(message.html)) {\n\t\tthrow new Error(\"A message body is required.\");\n\t}\n\treturn {\n\t\tto,\n\t\tsubject: message.subject,\n\t\ttext,\n\t\thtml: trimmed(message.html),\n\t\tfromEmail,\n\t\tfromName: trimmed(settings.fromName),\n\t\treplyTo: trimmed(settings.replyTo) ? [settings.replyTo!.trim()] : undefined,\n\t};\n}\n\nasync function resolvePrimaryProvider(\n\tctx: SmtpPluginContextLike,\n\truntime: DeliveryRuntime,\n\tsettings: GlobalSettings,\n): Promise<{ provider: ProviderDefinition; providerSettings: Record<string, unknown> }> {\n\tconst preferred = settings.primaryProviderId ? getProviderById(settings.primaryProviderId) : undefined;\n\tif (preferred && isProviderAvailable(preferred, runtime.variant)) {\n\t\tconst providerSettings = await getProviderSettings(ctx, preferred.id);\n\t\tif (isProviderConfigured(preferred, providerSettings)) {\n\t\t\treturn { provider: preferred, providerSettings };\n\t\t}\n\t}\n\n\tfor (const provider of SMTP_PROVIDER_DEFINITIONS) {\n\t\tif (!isProviderAvailable(provider, runtime.variant)) continue;\n\t\tconst providerSettings = await getProviderSettings(ctx, provider.id);\n\t\tif (isProviderConfigured(provider, providerSettings)) {\n\t\t\treturn { provider, providerSettings };\n\t\t}\n\t}\n\n\tconst variantLabel = runtime.variant === \"marketplace\" ? \"marketplace-compatible\" : \"trusted\";\n\tthrow new Error(`No configured ${variantLabel} SMTP provider is available.`);\n}\n\nasync function resolveFallbackProvider(\n\tctx: SmtpPluginContextLike,\n\truntime: DeliveryRuntime,\n\tsettings: GlobalSettings,\n\tprimaryProviderId: string,\n): Promise<{ provider: ProviderDefinition; providerSettings: Record<string, unknown> } | undefined> {\n\tif (!settings.fallbackProviderId || settings.fallbackProviderId === primaryProviderId) return undefined;\n\tconst provider = getProviderById(settings.fallbackProviderId);\n\tif (!provider || !isProviderAvailable(provider, runtime.variant)) return undefined;\n\tconst providerSettings = await getProviderSettings(ctx, provider.id);\n\tif (!isProviderConfigured(provider, providerSettings)) return undefined;\n\treturn { provider, providerSettings };\n}\n\nasync function sendWithProvider(\n\tctx: SmtpPluginContextLike,\n\tprovider: ProviderDefinition,\n\tproviderSettings: Record<string, unknown>,\n\tmessage: DeliveryMessage,\n\truntime: DeliveryRuntime,\n): Promise<DeliveryResult> {\n\tconst start = Date.now();\n\tconst result = await provider.send({\n\t\tctx,\n\t\tproviderId: provider.id,\n\t\tsettings: providerSettings,\n\t\tmessage,\n\t\truntime,\n\t});\n\treturn {\n\t\tproviderId: provider.id,\n\t\tremoteMessageId: result.remoteMessageId,\n\t\tdurationMs: Date.now() - start,\n\t};\n}\n\nexport async function deliverWithConfiguredProvider(args: {\n\tctx: SmtpPluginContextLike;\n\truntime: DeliveryRuntime;\n\tmessage: {\n\t\tto: string | string[];\n\t\tsubject: string;\n\t\ttext: string;\n\t\thtml?: string;\n\t};\n\tsource: string;\n}): Promise<DeliveryResult> {\n\tconst settings = await getGlobalSettings(args.ctx);\n\tconst normalizedMessage = normalizeMessageInput(args.message, settings);\n\tconst primary = await resolvePrimaryProvider(args.ctx, args.runtime, settings);\n\tconst fallback = await resolveFallbackProvider(args.ctx, args.runtime, settings, primary.provider.id);\n\n\ttry {\n\t\treturn await sendWithProvider(args.ctx, primary.provider, primary.providerSettings, normalizedMessage, args.runtime);\n\t} catch (primaryError) {\n\t\tif (!fallback) {\n\t\t\tthrow primaryError;\n\t\t}\n\t\targs.ctx.log?.warn(\"Primary SMTP provider failed, attempting fallback provider.\", {\n\t\t\tprimaryProviderId: primary.provider.id,\n\t\t\tfallbackProviderId: fallback.provider.id,\n\t\t\terror: primaryError instanceof Error ? primaryError.message : String(primaryError),\n\t\t});\n\t\treturn sendWithProvider(args.ctx, fallback.provider, fallback.providerSettings, normalizedMessage, args.runtime);\n\t}\n}\n\nexport async function isDeliveryReady(args: {\n\tctx: SmtpPluginContextLike;\n\truntime: DeliveryRuntime;\n}): Promise<boolean> {\n\tconst settings = await getGlobalSettings(args.ctx);\n\tif (!trimmed(settings.fromEmail)) {\n\t\treturn false;\n\t}\n\n\ttry {\n\t\tawait resolvePrimaryProvider(args.ctx, args.runtime, settings);\n\t\treturn true;\n\t} catch {\n\t\treturn false;\n\t}\n}\n","import {\n\tgetProviderById,\n\tgetProviderLabel,\n\tgetProviderPickerOptions,\n\tisProviderAvailable,\n\tisProviderConfigured,\n\tSMTP_PROVIDER_DEFINITIONS,\n} from \"./providers.js\";\nimport {\n\tcountDeliveryLogs,\n\tcreateDeliveryLogRecord,\n\tgetGlobalSettings,\n\tgetLastTestResult,\n\tgetProviderSettings,\n\tgetSelectedProviderId,\n\tqueryRecentDeliveryLogs,\n\tsaveGlobalSettingsFromValues,\n\tsaveProviderSettingsFromValues,\n\tsetLastTestResult,\n\tsetSelectedProviderId,\n\twriteDeliveryLog,\n\tclearProviderSecret,\n} from \"./storage.js\";\nimport { deliverWithConfiguredProvider } from \"./delivery.js\";\nimport type {\n\tActionsBlock,\n\tAdminInteraction,\n\tBlock,\n\tBlockElement,\n\tBlockResponse,\n\tContextBlock,\n\tCountSummary,\n\tDeliveryRuntime,\n\tFormBlock,\n\tGlobalSettings,\n\tLastTestResult,\n\tPluginVariant,\n\tProviderDefinition,\n\tProviderFieldDefinition,\n\tSmtpPluginContextLike,\n\tTableBlock,\n} from \"./types.js\";\n\nexport const SMTP_PLUGIN_ID = \"emdash-smtp\";\nexport const SMTP_PLUGIN_VERSION = \"0.3.4\";\nconst RECOMMENDED_PROVIDER_IDS = [\"resend\", \"postmark\", \"sendgrid\", \"mailgun\", \"generic\"] as const;\n\nexport const SMTP_ADMIN_PAGES = [\n\t{ path: \"/providers\", label: \"SMTP Providers\", icon: \"mail\" },\n\t{ path: \"/logs\", label: \"SMTP Logs\", icon: \"activity\" },\n] as const;\n\nexport const SMTP_ADMIN_WIDGETS = [{ id: \"smtp-overview\", title: \"SMTP\", size: \"third\" }] as const;\n\nfunction header(text: string): Block {\n\treturn { type: \"header\", text };\n}\n\nfunction divider(): Block {\n\treturn { type: \"divider\" };\n}\n\nfunction context(text: string): ContextBlock {\n\treturn { type: \"context\", text };\n}\n\nfunction banner(title: string, description: string, variant: \"default\" | \"alert\" | \"error\" = \"default\"): Block {\n\treturn { type: \"banner\", title, description, variant };\n}\n\nfunction stats(summary: CountSummary): Block {\n\treturn {\n\t\ttype: \"stats\",\n\t\titems: [\n\t\t\t{ label: \"Active provider\", value: summary.activeProviderLabel },\n\t\t\t{ label: \"Sent\", value: summary.sentCount, trend: summary.sentCount > 0 ? \"up\" : \"neutral\" },\n\t\t\t{ label: \"Failed\", value: summary.failedCount, trend: summary.failedCount > 0 ? \"down\" : \"neutral\" },\n\t\t],\n\t};\n}\n\nfunction actions(elements: BlockElement[]): ActionsBlock {\n\treturn { type: \"actions\", elements };\n}\n\nfunction button(\n\tactionId: string,\n\tlabel: string,\n\topts?: {\n\t\tstyle?: \"primary\" | \"danger\" | \"secondary\";\n\t\tvalue?: unknown;\n\t\tconfirm?: { title: string; text: string; confirm: string; deny: string; style?: \"danger\" };\n\t},\n): BlockElement {\n\treturn {\n\t\ttype: \"button\",\n\t\taction_id: actionId,\n\t\tlabel,\n\t\t...(opts?.style ? { style: opts.style } : {}),\n\t\t...(opts?.value !== undefined ? { value: opts.value } : {}),\n\t\t...(opts?.confirm ? { confirm: opts.confirm } : {}),\n\t};\n}\n\nfunction textField(field: ProviderFieldDefinition, value?: string): FormBlock[\"fields\"][number] {\n\treturn {\n\t\ttype: \"text_input\",\n\t\taction_id: field.key,\n\t\tlabel: field.label,\n\t\t...(field.placeholder ? { placeholder: field.placeholder } : {}),\n\t\t...(value !== undefined ? { initial_value: value } : {}),\n\t\t...(field.type === \"textarea\" || field.multiline ? { multiline: true } : {}),\n\t};\n}\n\nfunction secretField(field: ProviderFieldDefinition, hasValue: boolean): FormBlock[\"fields\"][number] {\n\treturn {\n\t\ttype: \"secret_input\",\n\t\taction_id: field.key,\n\t\tlabel: field.label,\n\t\t...(field.placeholder ? { placeholder: field.placeholder } : {}),\n\t\thas_value: hasValue,\n\t};\n}\n\nfunction numberField(field: ProviderFieldDefinition, value?: number): FormBlock[\"fields\"][number] {\n\treturn {\n\t\ttype: \"number_input\",\n\t\taction_id: field.key,\n\t\tlabel: field.label,\n\t\t...(value !== undefined ? { initial_value: value } : {}),\n\t};\n}\n\nfunction selectField(\n\tfield: ProviderFieldDefinition,\n\tvalue?: string,\n\toverrideOptions?: Array<{ label: string; value: string }>,\n): FormBlock[\"fields\"][number] {\n\treturn {\n\t\ttype: \"select\",\n\t\taction_id: field.key,\n\t\tlabel: field.label,\n\t\toptions: overrideOptions ?? field.options ?? [],\n\t\t...(value !== undefined ? { initial_value: value } : {}),\n\t};\n}\n\nfunction toggleField(field: ProviderFieldDefinition, value?: boolean): FormBlock[\"fields\"][number] {\n\treturn {\n\t\ttype: \"toggle\",\n\t\taction_id: field.key,\n\t\tlabel: field.label,\n\t\t...(field.description ? { description: field.description } : {}),\n\t\t...(value !== undefined ? { initial_value: value } : {}),\n\t};\n}\n\nfunction stringValue(value: unknown): string | undefined {\n\tif (typeof value !== \"string\") return undefined;\n\tconst next = value.trim();\n\treturn next === \"\" ? undefined : next;\n}\n\nfunction numberValue(value: unknown): number | undefined {\n\tif (typeof value === \"number\" && Number.isFinite(value)) return value;\n\tif (typeof value === \"string\" && value.trim() !== \"\") {\n\t\tconst parsed = Number(value);\n\t\tif (Number.isFinite(parsed)) return parsed;\n\t}\n\treturn undefined;\n}\n\nfunction booleanValue(value: unknown): boolean {\n\tif (typeof value === \"boolean\") return value;\n\tif (typeof value === \"string\") return value === \"true\" || value === \"1\" || value === \"on\";\n\treturn Boolean(value);\n}\n\nasync function buildSummary(ctx: SmtpPluginContextLike): Promise<CountSummary> {\n\tconst settings = await getGlobalSettings(ctx);\n\tconst sentCount = await countDeliveryLogs(ctx, \"sent\");\n\tconst failedCount = await countDeliveryLogs(ctx, \"failed\");\n\treturn {\n\t\tactiveProviderLabel: getProviderLabel(settings.primaryProviderId),\n\t\tsentCount,\n\t\tfailedCount,\n\t};\n}\n\nasync function getCurrentProvider(\n\tctx: SmtpPluginContextLike,\n\tvariant: PluginVariant,\n\tprimaryProviderId?: string,\n): Promise<ProviderDefinition> {\n\tconst selected = await getSelectedProviderId(ctx);\n\tconst preferred = selected ? getProviderById(selected) : primaryProviderId ? getProviderById(primaryProviderId) : undefined;\n\tif (preferred) return preferred;\n\tfor (const providerId of RECOMMENDED_PROVIDER_IDS) {\n\t\tconst recommended = getProviderById(providerId);\n\t\tif (recommended && isProviderAvailable(recommended, variant)) return recommended;\n\t}\n\treturn (\n\t\tSMTP_PROVIDER_DEFINITIONS.find((provider) => isProviderAvailable(provider, variant)) ??\n\t\tSMTP_PROVIDER_DEFINITIONS[0]!\n\t);\n}\n\nfunction buildSenderSettingsForm(settings: GlobalSettings): FormBlock {\n\tconst logLevelOptions = [\n\t\t{ label: \"All deliveries\", value: \"all\" },\n\t\t{ label: \"Errors only\", value: \"errors\" },\n\t\t{ label: \"Disabled\", value: \"off\" },\n\t];\n\treturn {\n\t\ttype: \"form\",\n\t\tblock_id: \"global-settings\",\n\t\tfields: [\n\t\t\ttextField({ key: \"fromEmail\", label: \"Default From Email\", type: \"text\", required: true, placeholder: \"noreply@example.com\" }, settings.fromEmail),\n\t\t\ttextField({ key: \"fromName\", label: \"Default From Name\", type: \"text\", placeholder: \"Example Site\" }, settings.fromName),\n\t\t\ttextField({ key: \"replyTo\", label: \"Default Reply-To Email\", type: \"text\", placeholder: \"support@example.com\" }, settings.replyTo),\n\t\t\tselectField({ key: \"logLevel\", label: \"Log Level\", type: \"select\", options: logLevelOptions }, settings.logLevel ?? \"all\", logLevelOptions),\n\t\t],\n\t\tsubmit: { label: \"Save Sender Settings\", action_id: \"save_global\" },\n\t};\n}\n\nfunction buildProviderPickerForm(providerId: string, variant: PluginVariant): FormBlock {\n\tconst options = getProviderPickerOptions(variant);\n\treturn {\n\t\ttype: \"form\",\n\t\tblock_id: \"provider-browser\",\n\t\tfields: [\n\t\t\tselectField(\n\t\t\t\t{ key: \"providerId\", label: \"Browse every provider\", type: \"select\", options },\n\t\t\t\tproviderId,\n\t\t\t\toptions,\n\t\t\t),\n\t\t],\n\t\tsubmit: { label: \"Switch Provider\", action_id: \"select_provider\" },\n\t};\n}\n\ntype ProviderRoutingRole = \"primary\" | \"fallback\" | \"none\";\n\ninterface ProviderCatalogEntry {\n\tprovider: ProviderDefinition;\n\tavailable: boolean;\n\tconfigured: boolean;\n\tselected: boolean;\n\troutingRole: ProviderRoutingRole;\n}\n\nfunction getProviderRoutingRole(provider: ProviderDefinition, settings: GlobalSettings): ProviderRoutingRole {\n\tif (settings.primaryProviderId === provider.id) return \"primary\";\n\tif (settings.fallbackProviderId === provider.id) return \"fallback\";\n\treturn \"none\";\n}\n\nfunction routingRoleLabel(role: ProviderRoutingRole): string {\n\tif (role === \"primary\") return \"Primary\";\n\tif (role === \"fallback\") return \"Fallback\";\n\treturn \"Not routed\";\n}\n\nfunction setupNextStep(settings: GlobalSettings, configured: boolean, routingRole: ProviderRoutingRole): string {\n\tif (!configured) return \"Add credentials\";\n\tif (routingRole === \"none\") return \"Set delivery route\";\n\tif (!settings.fromEmail) return \"Add sender\";\n\treturn \"Ready to test\";\n}\n\nfunction routeSummary(provider: ProviderDefinition, routingRole: ProviderRoutingRole): string {\n\tif (routingRole === \"primary\") return `${provider.label} handles delivery`;\n\tif (routingRole === \"fallback\") return `${provider.label} is the fallback`;\n\treturn \"Not routed\";\n}\n\nasync function buildProviderCatalogEntries(\n\tctx: SmtpPluginContextLike,\n\tvariant: PluginVariant,\n\tsettings: GlobalSettings,\n\tcurrentProvider: ProviderDefinition,\n): Promise<ProviderCatalogEntry[]> {\n\treturn Promise.all(\n\t\tSMTP_PROVIDER_DEFINITIONS.map(async (provider) => {\n\t\t\tconst providerSettings = await getProviderSettings(ctx, provider.id);\n\t\t\treturn {\n\t\t\t\tprovider,\n\t\t\t\tavailable: isProviderAvailable(provider, variant),\n\t\t\t\tconfigured: isProviderConfigured(provider, providerSettings),\n\t\t\t\tselected: provider.id === currentProvider.id,\n\t\t\t\troutingRole: getProviderRoutingRole(provider, settings),\n\t\t\t};\n\t\t}),\n\t);\n}\n\nfunction buildProviderQuickPicks(entries: ProviderCatalogEntry[]): Block[] {\n\tconst quickPicks = RECOMMENDED_PROVIDER_IDS\n\t\t.map((providerId) => entries.find((entry) => entry.provider.id === providerId && entry.available))\n\t\t.filter((entry): entry is ProviderCatalogEntry => Boolean(entry));\n\n\tconst blocks: Block[] = [\n\t\t{\n\t\t\ttype: \"section\",\n\t\t\ttext: \"Provider\",\n\t\t},\n\t];\n\n\tif (quickPicks.length > 0) {\n\t\tblocks.push(\n\t\t\tactions(\n\t\t\t\tquickPicks.map((entry) =>\n\t\t\t\t\tbutton(`select_provider:${entry.provider.id}`, entry.provider.label, {\n\t\t\t\t\t\tstyle: entry.selected ? \"primary\" : \"secondary\",\n\t\t\t\t\t\tvalue: entry.provider.id,\n\t\t\t\t\t}),\n\t\t\t\t),\n\t\t\t),\n\t\t);\n\t}\n\n\treturn blocks;\n}\n\nfunction buildRoutingActions(settings: GlobalSettings, currentProvider: ProviderDefinition): Block[] {\n\tconst elements: BlockElement[] = [];\n\n\tif (settings.primaryProviderId !== currentProvider.id) {\n\t\telements.push(\n\t\t\tbutton(\"set_primary_provider\", `Use ${currentProvider.label} for delivery`, {\n\t\t\t\tstyle: \"primary\",\n\t\t\t\tvalue: currentProvider.id,\n\t\t\t}),\n\t\t);\n\t} else {\n\t\telements.push(\n\t\t\tbutton(\"set_primary_provider\", \"Primary provider\", {\n\t\t\t\tstyle: \"secondary\",\n\t\t\t\tvalue: currentProvider.id,\n\t\t\t}),\n\t\t);\n\t}\n\n\tif (settings.fallbackProviderId === currentProvider.id) {\n\t\telements.push(button(\"clear_fallback_provider\", \"Remove fallback\", { style: \"secondary\" }));\n\t} else if (settings.primaryProviderId && settings.primaryProviderId !== currentProvider.id) {\n\t\telements.push(\n\t\t\tbutton(\"set_fallback_provider\", \"Use as fallback\", {\n\t\t\t\tstyle: \"secondary\",\n\t\t\t\tvalue: currentProvider.id,\n\t\t\t}),\n\t\t);\n\t} else if (settings.fallbackProviderId) {\n\t\telements.push(button(\"clear_fallback_provider\", \"Clear fallback\", { style: \"secondary\" }));\n\t}\n\n\treturn elements.length ? [actions(elements)] : [];\n}\n\nfunction buildSetupOverview(\n\tsettings: GlobalSettings,\n\tcurrentProvider: ProviderDefinition,\n\tconfigured: boolean,\n\troutingRole: ProviderRoutingRole,\n): Block[] {\n\treturn [\n\t\t{\n\t\t\ttype: \"section\",\n\t\t\ttext: \"Current setup\",\n\t\t},\n\t\t{\n\t\t\ttype: \"table\",\n\t\t\tpage_action_id: \"go_providers\",\n\t\t\tcolumns: [\n\t\t\t\t{ key: \"area\", label: \"Area\" },\n\t\t\t\t{ key: \"status\", label: \"Status\" },\n\t\t\t\t{ key: \"next\", label: \"Next\" },\n\t\t\t],\n\t\t\trows: [\n\t\t\t\t{\n\t\t\t\t\tarea: currentProvider.label,\n\t\t\t\t\tstatus: configured ? \"Ready\" : \"Needs setup\",\n\t\t\t\t\tnext: setupNextStep(settings, configured, routingRole),\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tarea: \"Delivery route\",\n\t\t\t\t\tstatus: routeSummary(currentProvider, routingRole),\n\t\t\t\t\tnext: routingRole === \"none\" ? `Use ${currentProvider.label}` : \"Set\",\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tarea: \"Sender\",\n\t\t\t\t\tstatus: settings.fromEmail ?? \"Not set\",\n\t\t\t\t\tnext: settings.fromEmail ? \"Saved\" : \"Add default\",\n\t\t\t\t},\n\t\t\t],\n\t\t},\n\t];\n}\n\nfunction buildProviderDetails(\n\tprovider: ProviderDefinition,\n\tvariant: PluginVariant,\n\tconfigured: boolean,\n\troutingRole: ProviderRoutingRole,\n): Block[] {\n\tconst available = isProviderAvailable(provider, variant);\n\tconst statusParts = [\n\t\tavailable ? \"Available\" : \"Trusted only\",\n\t\tconfigured ? \"settings ready\" : \"needs credentials\",\n\t\trouteSummary(provider, routingRole),\n\t];\n\treturn [\n\t\tcontext(statusParts.join(\" · \")),\n\t\tcontext(provider.description),\n\t];\n}\n\nfunction buildProviderSettingsForm(\n\tprovider: ProviderDefinition,\n\tsettings: Record<string, unknown>,\n): FormBlock {\n\tconst fields = provider.fields.map((field) => {\n\t\tif (field.type === \"secret\") return secretField(field, Boolean(stringValue(settings[field.key])));\n\t\tif (field.type === \"number\") return numberField(field, numberValue(settings[field.key]) ?? (typeof field.defaultValue === \"number\" ? field.defaultValue : undefined));\n\t\tif (field.type === \"select\") return selectField(field, stringValue(settings[field.key]) ?? (typeof field.defaultValue === \"string\" ? field.defaultValue : undefined));\n\t\tif (field.type === \"toggle\") return toggleField(field, typeof settings[field.key] === \"boolean\" ? booleanValue(settings[field.key]) : (typeof field.defaultValue === \"boolean\" ? field.defaultValue : undefined));\n\t\treturn textField(field, stringValue(settings[field.key]) ?? (typeof field.defaultValue === \"string\" ? field.defaultValue : undefined));\n\t});\n\treturn {\n\t\ttype: \"form\",\n\t\tblock_id: \"provider-settings\",\n\t\tfields,\n\t\tsubmit: { label: \"Save Provider Settings\", action_id: \"save_provider\" },\n\t};\n}\n\nfunction buildProviderSecretActions(\n\tprovider: ProviderDefinition,\n\tsettings: Record<string, unknown>,\n): ActionsBlock | null {\n\tconst elements = provider.fields\n\t\t.filter((field) => field.type === \"secret\" && Boolean(stringValue(settings[field.key])))\n\t\t.map((field) =>\n\t\t\tbutton(`clear_secret:${provider.id}:${field.key}`, `Clear ${field.label}`, {\n\t\t\t\tstyle: \"danger\",\n\t\t\t\tconfirm: {\n\t\t\t\t\ttitle: `Clear ${field.label}?`,\n\t\t\t\t\ttext: `This will remove the stored ${field.label.toLowerCase()} from ${provider.label}.`,\n\t\t\t\t\tconfirm: \"Clear\",\n\t\t\t\t\tdeny: \"Cancel\",\n\t\t\t\t\tstyle: \"danger\",\n\t\t\t\t},\n\t\t\t}),\n\t\t);\n\treturn elements.length ? actions(elements) : null;\n}\n\nfunction buildTestSendForm(lastResult: LastTestResult | null): Block[] {\n\tconst blocks: Block[] = [\n\t\t{\n\t\t\ttype: \"form\",\n\t\t\tblock_id: \"test-send\",\n\t\t\tfields: [\n\t\t\t\t{ type: \"text_input\", action_id: \"to\", label: \"Recipient Email\", placeholder: \"you@example.com\" },\n\t\t\t\t{ type: \"text_input\", action_id: \"subject\", label: \"Subject\", initial_value: \"EmDash SMTP test email\" },\n\t\t\t\t{ type: \"text_input\", action_id: \"text\", label: \"Message\", multiline: true, initial_value: \"This is a test email sent from EmDash SMTP.\" },\n\t\t\t],\n\t\t\tsubmit: { label: \"Send Test Email\", action_id: \"send_test\" },\n\t\t},\n\t];\n\tif (lastResult) {\n\t\tblocks.push(\n\t\t\tbanner(\n\t\t\t\tlastResult.status === \"sent\" ? \"Last test succeeded\" : \"Last test failed\",\n\t\t\t\t`${lastResult.createdAt}: ${lastResult.message}`,\n\t\t\t\tlastResult.status === \"sent\" ? \"default\" : \"error\",\n\t\t\t),\n\t\t);\n\t}\n\treturn blocks;\n}\n\nasync function buildLogsTable(ctx: SmtpPluginContextLike): Promise<TableBlock> {\n\tconst logs = await queryRecentDeliveryLogs(ctx, 25);\n\treturn {\n\t\ttype: \"table\",\n\t\tpage_action_id: \"go_logs\",\n\t\tempty_text: \"No delivery logs yet.\",\n\t\tcolumns: [\n\t\t\t{ key: \"createdAt\", label: \"Created\", format: \"relative_time\", sortable: true },\n\t\t\t{ key: \"status\", label: \"Status\", format: \"badge\" },\n\t\t\t{ key: \"provider\", label: \"Provider\" },\n\t\t\t{ key: \"to\", label: \"To\" },\n\t\t\t{ key: \"subject\", label: \"Subject\" },\n\t\t\t{ key: \"source\", label: \"Source\" },\n\t\t\t{ key: \"details\", label: \"Details\", format: \"code\" },\n\t\t],\n\t\trows: logs.map(({ data }) => ({\n\t\t\tcreatedAt: data.createdAt,\n\t\t\tstatus: data.status,\n\t\t\tprovider: getProviderLabel(data.providerId),\n\t\t\tto: data.message.to,\n\t\t\tsubject: data.message.subject,\n\t\t\tsource: data.source,\n\t\t\tdetails: data.errorMessage ?? data.remoteMessageId ?? \"—\",\n\t\t})),\n\t};\n}\n\nasync function buildProvidersPage(\n\tctx: SmtpPluginContextLike,\n\tvariant: PluginVariant,\n\truntime: DeliveryRuntime,\n\ttoast?: BlockResponse[\"toast\"],\n): Promise<BlockResponse> {\n\tconst summary = await buildSummary(ctx);\n\tconst settings = await getGlobalSettings(ctx);\n\tconst currentProvider = await getCurrentProvider(ctx, variant, settings.primaryProviderId);\n\tconst currentProviderSettings = await getProviderSettings(ctx, currentProvider.id);\n\tconst configured = isProviderConfigured(currentProvider, currentProviderSettings);\n\tconst currentRoutingRole = getProviderRoutingRole(currentProvider, settings);\n\tconst catalogEntries = await buildProviderCatalogEntries(ctx, variant, settings, currentProvider);\n\tconst lastTestResult = await getLastTestResult(ctx);\n\tconst secretActions = buildProviderSecretActions(currentProvider, currentProviderSettings);\n\n\tconst blocks: Block[] = [header(\"SMTP Providers\")];\n\tif (variant === \"marketplace\") {\n\t\tblocks.push(banner(\"Marketplace install\", \"HTTP API providers are available.\", \"alert\"));\n\t}\n\tblocks.push(\n\t\tstats(summary),\n\t\tactions([\n\t\t\tbutton(\"go_providers\", \"Providers\", { style: \"secondary\" }),\n\t\t\tbutton(\"go_logs\", \"View Logs\", { style: \"primary\" }),\n\t\t]),\n\t\t...buildSetupOverview(settings, currentProvider, configured, currentRoutingRole),\n\t\t...buildProviderQuickPicks(catalogEntries),\n\t\tdivider(),\n\t\t{\n\t\t\ttype: \"section\",\n\t\t\ttext: `${currentProvider.label} setup`,\n\t\t},\n\t\t...buildProviderDetails(currentProvider, variant, configured, currentRoutingRole),\n\t);\n\n\tif (!isProviderAvailable(currentProvider, variant)) {\n\t\tblocks.push(\n\t\t\tbanner(\n\t\t\t\t`${currentProvider.label} is not available in the marketplace variant`,\n\t\t\t\t\"Use the trusted emdash-smtp package in astro.config.mjs if you need this transport.\",\n\t\t\t\t\"alert\",\n\t\t\t),\n\t\t);\n\t} else {\n\t\tblocks.push(buildProviderSettingsForm(currentProvider, currentProviderSettings));\n\t\tif (secretActions) blocks.push(secretActions);\n\t}\n\n\tblocks.push(divider());\n\tblocks.push({ type: \"section\", text: \"Sender identity\" });\n\tblocks.push(...buildRoutingActions(settings, currentProvider));\n\tblocks.push(buildSenderSettingsForm(settings));\n\tblocks.push(divider());\n\tblocks.push({ type: \"section\", text: \"Need a different provider?\" });\n\tblocks.push(buildProviderPickerForm(currentProvider.id, variant));\n\tblocks.push(divider());\n\tblocks.push({ type: \"section\", text: \"Test delivery\" });\n\tblocks.push(...buildTestSendForm(lastTestResult));\n\n\treturn { blocks, ...(toast ? { toast } : {}) };\n}\n\nasync function buildLogsPage(\n\tctx: SmtpPluginContextLike,\n\ttoast?: BlockResponse[\"toast\"],\n): Promise<BlockResponse> {\n\tconst summary = await buildSummary(ctx);\n\treturn {\n\t\tblocks: [\n\t\t\theader(\"SMTP Logs\"),\n\t\t\tstats(summary),\n\t\t\tactions([\n\t\t\t\tbutton(\"go_providers\", \"Providers\", { style: \"primary\" }),\n\t\t\t\tbutton(\"go_logs\", \"Refresh Logs\", { style: \"secondary\" }),\n\t\t\t]),\n\t\t\tawait buildLogsTable(ctx),\n\t\t],\n\t\t...(toast ? { toast } : {}),\n\t};\n}\n\nasync function buildWidgetPage(ctx: SmtpPluginContextLike): Promise<BlockResponse> {\n\tconst summary = await buildSummary(ctx);\n\treturn {\n\t\tblocks: [\n\t\t\tstats(summary),\n\t\t\tcontext(\"EmDash SMTP monitors the active provider and recent delivery outcomes.\"),\n\t\t],\n\t};\n}\n\nexport async function handleAdminInteraction(args: {\n\tctx: SmtpPluginContextLike;\n\tvariant: PluginVariant;\n\truntime: DeliveryRuntime;\n\tinteraction: AdminInteraction;\n}): Promise<BlockResponse> {\n\tconst { ctx, interaction, variant, runtime } = args;\n\n\tif (interaction.type === \"page_load\") {\n\t\tif (interaction.page === \"/logs\") return buildLogsPage(ctx);\n\t\tif (interaction.page === \"widget:smtp-overview\") return buildWidgetPage(ctx);\n\t\treturn buildProvidersPage(ctx, variant, runtime);\n\t}\n\n\tif (interaction.type === \"block_action\" || interaction.type === \"action\") {\n\t\tif (interaction.action_id === \"go_logs\") return buildLogsPage(ctx);\n\t\tif (interaction.action_id === \"go_providers\") return buildProvidersPage(ctx, variant, runtime);\n\t\tif (interaction.action_id === \"select_provider\" || interaction.action_id.startsWith(\"select_provider:\")) {\n\t\t\tconst providerId =\n\t\t\t\tstringValue(interaction.value) ??\n\t\t\t\t(interaction.action_id.startsWith(\"select_provider:\")\n\t\t\t\t\t? stringValue(interaction.action_id.split(\":\")[1])\n\t\t\t\t\t: undefined);\n\t\t\tif (providerId && getProviderById(providerId)) {\n\t\t\t\tawait setSelectedProviderId(ctx, providerId);\n\t\t\t\treturn buildProvidersPage(ctx, variant, runtime, {\n\t\t\t\t\tmessage: `Editing ${getProviderLabel(providerId)}.`,\n\t\t\t\t\ttype: \"info\",\n\t\t\t\t});\n\t\t\t}\n\t\t\treturn buildProvidersPage(ctx, variant, runtime, {\n\t\t\t\tmessage: \"Provider could not be selected.\",\n\t\t\t\ttype: \"error\",\n\t\t\t});\n\t\t}\n\t\tif (interaction.action_id === \"set_primary_provider\") {\n\t\t\tconst providerId = stringValue(interaction.value);\n\t\t\tconst provider = providerId ? getProviderById(providerId) : undefined;\n\t\t\tif (provider && isProviderAvailable(provider, variant)) {\n\t\t\t\tconst settings = await getGlobalSettings(ctx);\n\t\t\t\tawait saveGlobalSettingsFromValues(ctx, {\n\t\t\t\t\tprimaryProviderId: provider.id,\n\t\t\t\t\t...(settings.fallbackProviderId === provider.id ? { fallbackProviderId: \"\" } : {}),\n\t\t\t\t});\n\t\t\t\treturn buildProvidersPage(ctx, variant, runtime, {\n\t\t\t\t\tmessage: `${provider.label} is now the delivery provider.`,\n\t\t\t\t\ttype: \"success\",\n\t\t\t\t});\n\t\t\t}\n\t\t\treturn buildProvidersPage(ctx, variant, runtime, {\n\t\t\t\tmessage: \"Provider could not be routed.\",\n\t\t\t\ttype: \"error\",\n\t\t\t});\n\t\t}\n\t\tif (interaction.action_id === \"set_fallback_provider\") {\n\t\t\tconst providerId = stringValue(interaction.value);\n\t\t\tconst provider = providerId ? getProviderById(providerId) : undefined;\n\t\t\tconst settings = await getGlobalSettings(ctx);\n\t\t\tif (provider && isProviderAvailable(provider, variant) && settings.primaryProviderId !== provider.id) {\n\t\t\t\tawait saveGlobalSettingsFromValues(ctx, { fallbackProviderId: provider.id });\n\t\t\t\treturn buildProvidersPage(ctx, variant, runtime, {\n\t\t\t\t\tmessage: `${provider.label} is now the fallback provider.`,\n\t\t\t\t\ttype: \"success\",\n\t\t\t\t});\n\t\t\t}\n\t\t\treturn buildProvidersPage(ctx, variant, runtime, {\n\t\t\t\tmessage: \"Fallback provider could not be routed.\",\n\t\t\t\ttype: \"error\",\n\t\t\t});\n\t\t}\n\t\tif (interaction.action_id === \"clear_fallback_provider\") {\n\t\t\tawait saveGlobalSettingsFromValues(ctx, { fallbackProviderId: \"\" });\n\t\t\treturn buildProvidersPage(ctx, variant, runtime, {\n\t\t\t\tmessage: \"Fallback provider cleared.\",\n\t\t\t\ttype: \"success\",\n\t\t\t});\n\t\t}\n\t\tif (interaction.action_id.startsWith(\"clear_secret:\")) {\n\t\t\tconst [, providerId, fieldKey] = interaction.action_id.split(\":\");\n\t\t\tif (providerId && fieldKey) {\n\t\t\t\tawait clearProviderSecret(ctx, providerId, fieldKey);\n\t\t\t\treturn buildProvidersPage(ctx, variant, runtime, {\n\t\t\t\t\tmessage: `Cleared stored secret for ${fieldKey}.`,\n\t\t\t\t\ttype: \"success\",\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t\treturn buildProvidersPage(ctx, variant, runtime);\n\t}\n\n\tif (interaction.type === \"form_submit\") {\n\t\tif (interaction.action_id === \"save_global\") {\n\t\t\tawait saveGlobalSettingsFromValues(ctx, interaction.values);\n\t\t\treturn buildProvidersPage(ctx, variant, runtime, {\n\t\t\t\tmessage: \"Sender settings saved.\",\n\t\t\t\ttype: \"success\",\n\t\t\t});\n\t\t}\n\n\t\tif (interaction.action_id === \"select_provider\") {\n\t\t\tconst providerId = stringValue(interaction.values.providerId);\n\t\t\tif (providerId) {\n\t\t\t\tawait setSelectedProviderId(ctx, providerId);\n\t\t\t}\n\t\t\treturn buildProvidersPage(ctx, variant, runtime, {\n\t\t\t\tmessage: \"Provider selection updated.\",\n\t\t\t\ttype: \"info\",\n\t\t\t});\n\t\t}\n\n\t\tif (interaction.action_id === \"save_provider\") {\n\t\t\tconst provider = await getCurrentProvider(ctx, variant, (await getGlobalSettings(ctx)).primaryProviderId);\n\t\t\tawait saveProviderSettingsFromValues(ctx, provider, interaction.values);\n\t\t\treturn buildProvidersPage(ctx, variant, runtime, {\n\t\t\t\tmessage: `${provider.label} settings saved.`,\n\t\t\t\ttype: \"success\",\n\t\t\t});\n\t\t}\n\n\t\tif (interaction.action_id === \"send_test\") {\n\t\t\tconst to = stringValue(interaction.values.to);\n\t\t\tconst subject = stringValue(interaction.values.subject) ?? \"EmDash SMTP test email\";\n\t\t\tconst text = stringValue(interaction.values.text) ?? \"This is a test email sent from EmDash SMTP.\";\n\t\t\tif (!to) {\n\t\t\t\treturn buildProvidersPage(ctx, variant, runtime, {\n\t\t\t\t\tmessage: \"A recipient email address is required for test sends.\",\n\t\t\t\t\ttype: \"error\",\n\t\t\t\t});\n\t\t\t}\n\n\t\t\ttry {\n\t\t\t\tconst result = await deliverWithConfiguredProvider({\n\t\t\t\t\tctx,\n\t\t\t\t\truntime,\n\t\t\t\t\tmessage: { to, subject, text },\n\t\t\t\t\tsource: `${ctx.plugin.id}:test`,\n\t\t\t\t});\n\t\t\t\tawait writeDeliveryLog(\n\t\t\t\t\tctx,\n\t\t\t\t\tcreateDeliveryLogRecord({\n\t\t\t\t\t\tproviderId: result.providerId,\n\t\t\t\t\t\tstatus: \"sent\",\n\t\t\t\t\t\tsource: `${ctx.plugin.id}:test`,\n\t\t\t\t\t\tdurationMs: result.durationMs,\n\t\t\t\t\t\tmessage: { to, subject },\n\t\t\t\t\t\tremoteMessageId: result.remoteMessageId,\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t\tawait setLastTestResult(ctx, {\n\t\t\t\t\tstatus: \"sent\",\n\t\t\t\t\tproviderId: result.providerId,\n\t\t\t\t\tmessage: `Sent with ${getProviderLabel(result.providerId)}${result.remoteMessageId ? ` (${result.remoteMessageId})` : \"\"}.`,\n\t\t\t\t\tcreatedAt: new Date().toISOString(),\n\t\t\t\t});\n\t\t\t\treturn buildProvidersPage(ctx, variant, runtime, {\n\t\t\t\t\tmessage: `Test email sent with ${getProviderLabel(result.providerId)}.`,\n\t\t\t\t\ttype: \"success\",\n\t\t\t\t});\n\t\t\t} catch (error) {\n\t\t\t\tconst message = error instanceof Error ? error.message : String(error);\n\t\t\t\tawait writeDeliveryLog(\n\t\t\t\t\tctx,\n\t\t\t\t\tcreateDeliveryLogRecord({\n\t\t\t\t\t\tproviderId: \"unknown\",\n\t\t\t\t\t\tstatus: \"failed\",\n\t\t\t\t\t\tsource: `${ctx.plugin.id}:test`,\n\t\t\t\t\t\tdurationMs: 0,\n\t\t\t\t\t\tmessage: { to, subject },\n\t\t\t\t\t\terrorMessage: message,\n\t\t\t\t\t}),\n\t\t\t\t);\n\t\t\t\tawait setLastTestResult(ctx, {\n\t\t\t\t\tstatus: \"failed\",\n\t\t\t\t\tmessage,\n\t\t\t\t\tcreatedAt: new Date().toISOString(),\n\t\t\t\t});\n\t\t\t\treturn buildProvidersPage(ctx, variant, runtime, {\n\t\t\t\t\tmessage,\n\t\t\t\t\ttype: \"error\",\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t}\n\n\treturn buildProvidersPage(ctx, variant, runtime);\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED