feat(mail): add smtp email delivery
This commit is contained in:
parent
faddaa91d0
commit
3456b04ed4
25 changed files with 529 additions and 60 deletions
109
lib/mail/config.ts
Normal file
109
lib/mail/config.ts
Normal file
|
|
@ -0,0 +1,109 @@
|
|||
import { mkdir, readFile, writeFile } from "fs/promises";
|
||||
import path from "path";
|
||||
import { configDirectory } from "@/lib/runtime/config";
|
||||
import type { SmtpSettings } from "@/lib/admin/types";
|
||||
import type { PublicSmtpSettings } from "./types";
|
||||
|
||||
const smtpConfigFile = path.join(configDirectory, "smtp.json");
|
||||
|
||||
const defaultSmtpSettings: SmtpSettings = {
|
||||
host: "",
|
||||
port: "587",
|
||||
username: "",
|
||||
password: "",
|
||||
security: "starttls",
|
||||
fromAddress: "",
|
||||
replyToAddress: "",
|
||||
recipientAddress: "",
|
||||
bccAddress: "",
|
||||
};
|
||||
|
||||
function text(value: FormDataEntryValue | null) {
|
||||
return typeof value === "string" ? value.trim() : "";
|
||||
}
|
||||
|
||||
function normalizeSecurity(value: string): SmtpSettings["security"] {
|
||||
if (value === "tls" || value === "none") return value;
|
||||
return "starttls";
|
||||
}
|
||||
|
||||
async function ensureConfigDirectory() {
|
||||
await mkdir(configDirectory, { recursive: true });
|
||||
}
|
||||
|
||||
export async function getSmtpSettings(): Promise<SmtpSettings> {
|
||||
await ensureConfigDirectory();
|
||||
try {
|
||||
const file = await readFile(smtpConfigFile, "utf8");
|
||||
return { ...defaultSmtpSettings, ...JSON.parse(file) as SmtpSettings };
|
||||
} catch {
|
||||
return defaultSmtpSettings;
|
||||
}
|
||||
}
|
||||
|
||||
export function toPublicSmtpSettings(settings: SmtpSettings): PublicSmtpSettings {
|
||||
return {
|
||||
host: settings.host,
|
||||
port: settings.port,
|
||||
username: settings.username,
|
||||
security: settings.security,
|
||||
fromAddress: settings.fromAddress,
|
||||
replyToAddress: settings.replyToAddress,
|
||||
recipientAddress: settings.recipientAddress,
|
||||
bccAddress: settings.bccAddress,
|
||||
lastTestAt: settings.lastTestAt,
|
||||
lastTestStatus: settings.lastTestStatus,
|
||||
lastError: settings.lastError,
|
||||
hasPassword: Boolean(settings.password),
|
||||
};
|
||||
}
|
||||
|
||||
export function isSmtpConfigured(settings: SmtpSettings) {
|
||||
return Boolean(
|
||||
settings.host &&
|
||||
settings.port &&
|
||||
settings.username &&
|
||||
settings.password &&
|
||||
settings.fromAddress &&
|
||||
settings.recipientAddress,
|
||||
);
|
||||
}
|
||||
|
||||
export async function saveSmtpSettings(form: FormData) {
|
||||
const current = await getSmtpSettings();
|
||||
const nextPassword = text(form.get("password"));
|
||||
const settings: SmtpSettings = {
|
||||
...current,
|
||||
host: text(form.get("host")),
|
||||
port: text(form.get("port")) || "587",
|
||||
username: text(form.get("username")),
|
||||
password: nextPassword || current.password || "",
|
||||
security: normalizeSecurity(text(form.get("security"))),
|
||||
fromAddress: text(form.get("fromAddress")),
|
||||
replyToAddress: text(form.get("replyToAddress")),
|
||||
recipientAddress: text(form.get("recipientAddress")),
|
||||
bccAddress: text(form.get("bccAddress")),
|
||||
};
|
||||
|
||||
await ensureConfigDirectory();
|
||||
await writeFile(smtpConfigFile, `${JSON.stringify(settings, null, 2)}\n`, "utf8");
|
||||
return settings;
|
||||
}
|
||||
|
||||
export async function updateSmtpTestStatus(status: Pick<SmtpSettings, "lastTestAt" | "lastTestStatus" | "lastError">) {
|
||||
const current = await getSmtpSettings();
|
||||
const settings: SmtpSettings = { ...current, ...status };
|
||||
await ensureConfigDirectory();
|
||||
await writeFile(smtpConfigFile, `${JSON.stringify(settings, null, 2)}\n`, "utf8");
|
||||
return settings;
|
||||
}
|
||||
|
||||
export async function updateSmtpDeliveryStatus(status: Pick<SmtpSettings, "lastDeliveryAt" | "lastDeliveryStatus" | "lastError">) {
|
||||
const current = await getSmtpSettings();
|
||||
const settings: SmtpSettings = { ...current, ...status };
|
||||
await ensureConfigDirectory();
|
||||
await writeFile(smtpConfigFile, `${JSON.stringify(settings, null, 2)}\n`, "utf8");
|
||||
return settings;
|
||||
}
|
||||
|
||||
export { smtpConfigFile };
|
||||
Loading…
Add table
Add a link
Reference in a new issue