emdash-smtp-core 0.2.0 → 0.2.1
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/README.md +5 -0
- package/dist/index.d.mts +1 -1
- package/dist/index.mjs +1 -1
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
package/README.md
ADDED
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.2.
|
|
374
|
+
declare const SMTP_PLUGIN_VERSION = "0.2.1";
|
|
375
375
|
declare const SMTP_ADMIN_PAGES: readonly [{
|
|
376
376
|
readonly path: "/providers";
|
|
377
377
|
readonly label: "SMTP Providers";
|
package/dist/index.mjs
CHANGED
|
@@ -1571,7 +1571,7 @@ async function isDeliveryReady(args) {
|
|
|
1571
1571
|
//#endregion
|
|
1572
1572
|
//#region src/admin.ts
|
|
1573
1573
|
const SMTP_PLUGIN_ID = "emdash-smtp";
|
|
1574
|
-
const SMTP_PLUGIN_VERSION = "0.2.
|
|
1574
|
+
const SMTP_PLUGIN_VERSION = "0.2.1";
|
|
1575
1575
|
const SMTP_ADMIN_PAGES = [{
|
|
1576
1576
|
path: "/providers",
|
|
1577
1577
|
label: "SMTP Providers",
|
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.2.0\";\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 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.2.1\";\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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"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "emdash-smtp-core",
|
|
3
|
-
"version": "0.2.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "0.2.1",
|
|
4
|
+
"description": "Internal shared runtime for EmDash SMTP. End users should install emdash-smtp or emdash-smtp-marketplace.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.mjs",
|
|
7
7
|
"types": "dist/index.d.mts",
|