Closes #3600. Previously the From header on test emails and notifications showed only the raw email address. Adds an optional "Sender name" field so emails appear from a friendly name like "Checkmate notifications" <user@example.org>. ## Behaviour - Field is optional. When empty/null/whitespace, the From header falls back to the raw email address — identical to current behaviour, no regression for existing installs. - When set, the email service hands nodemailer { name, address } as the message from field. Nodemailer handles RFC-5322 encoding (quotes, commas, non-ASCII) so the display name is safe for any input. - Unsetting works: clearing the input transforms the value to null in the Zod parse step, and the settings repository already turns null values into a $unset operation. - Both client and server Zod schemas trim and empty-string-to-null, preventing whitespace-only display names from being stored. ## Surfaces - AppSettings schema, Settings type, EmailTransportConfig pick, server Zod validation, client Zod validation, client form defaults, and the Settings page form all carry the new systemEmailDisplayName field. - The transport preview pre-block on /settings now includes a `from` key showing exactly what the email service hands nodemailer — the string when no display name is set, or { name, address } when it is. - en.json carries the new label and placeholder. Other locales fall back until translated (16 locales pending — separate follow-up). ## Conventions conformance (per docs/frontend-conventions.md) - The pre-block I touched had three rule #1 violations (sx p, borderRadius, backgroundColor); hoisted those to native props using theme.shape.borderRadius. Other rule #1 violations elsewhere on this page are pre-existing and intentionally left alone. - No new sx-with-native-equivalents introduced. - No color="text.X" shorthand introduced. - No theme module import introduced.
62 lines
1.9 KiB
TypeScript
62 lines
1.9 KiB
TypeScript
import { CHECK_TTL_SENTINEL } from "@/Types/Check";
|
|
import { z } from "zod";
|
|
|
|
export const settingsSchema = z.object({
|
|
systemEmailIgnoreTLS: z.boolean(),
|
|
systemEmailRequireTLS: z.boolean(),
|
|
systemEmailRejectUnauthorized: z.boolean(),
|
|
systemEmailConnectionHost: z
|
|
.string()
|
|
.transform((val) => (val.trim() === "" ? null : val.trim()))
|
|
.optional(),
|
|
systemEmailSecure: z.boolean().optional(),
|
|
systemEmailPool: z.boolean().optional(),
|
|
showURL: z.boolean().optional(),
|
|
checkTTL: z
|
|
.number()
|
|
.int()
|
|
.min(1, "Please enter a value")
|
|
.max(CHECK_TTL_SENTINEL, `Maximum ${CHECK_TTL_SENTINEL}`),
|
|
pagespeedApiKey: z
|
|
.string()
|
|
.transform((val) => (val.trim() === "" ? null : val.trim()))
|
|
.optional(),
|
|
systemEmailHost: z
|
|
.string()
|
|
.regex(/^[a-zA-Z0-9.-]*$/, "Invalid hostname or IP address")
|
|
.transform((val) => (val.trim() === "" ? null : val.trim()))
|
|
.optional(),
|
|
systemEmailPort: z.number().int().min(1).max(65535).optional(),
|
|
systemEmailAddress: z
|
|
.email("Please enter a valid email address")
|
|
.or(z.literal(""))
|
|
.transform((val) => (val === "" ? null : val.toLowerCase().trim()))
|
|
.optional(),
|
|
systemEmailDisplayName: z
|
|
.string()
|
|
.max(100, "Display name must be 100 characters or fewer")
|
|
.transform((val) => (val.trim() === "" ? null : val.trim()))
|
|
.optional(),
|
|
systemEmailUser: z
|
|
.string()
|
|
.transform((val) => (val.trim() === "" ? null : val.trim()))
|
|
.optional(),
|
|
systemEmailPassword: z
|
|
.string()
|
|
.transform((val) => (val.trim() === "" ? null : val.trim()))
|
|
.optional(),
|
|
systemEmailTLSServername: z
|
|
.string()
|
|
.transform((val) => (val.trim() === "" ? null : val.trim()))
|
|
.optional(),
|
|
globalThresholds: z.object({
|
|
cpu: z.number().int().min(1).max(100),
|
|
memory: z.number().int().min(1).max(100),
|
|
disk: z.number().int().min(1).max(100),
|
|
temperature: z.number().int().min(1).max(150),
|
|
}),
|
|
});
|
|
|
|
export type SettingsFormInput = z.input<typeof settingsSchema>;
|
|
export type SettingsFormData = z.infer<typeof settingsSchema>;
|