Files
shop/server/utils/contactMail.ts
libretech fccff147ba
build / test (push) Successful in 10s
build / build (push) Successful in 1m5s
v0.1.2: checkout fixes for CMS v0.2.0 (#18)
Co-authored-by: Michael Czechowski <mail@librete.ch>
2026-10-15 10:23:27 +02:00

57 lines
2.4 KiB
TypeScript

// The mail of the contact form (components/ContactForm.vue → POST /api/contact). The mail service (libreshop/mail src/app.py)
// sends it from POST /v1/send/message, whose JSON body is { to_email, subject, message, html? }. It sets no Reply-To, so the
// sender's address is in the text. Pure: no Nuxt, Nitro or h3 imports, tested in tests/unit/contactMail.test.ts.
export const CONTACT_RECIPIENT = "paperwork@muellerprints.de";
export const MAIL_SEND_PATH = "/v1/send/message";
/** The body of POST /v1/send/message. */
export type ContactMail = { to_email: string; subject: string; message: string };
/** The mail to send, or the German message of the 400 for the form. */
export type ContactMailResult = { ok: true; mail: ContactMail } | { ok: false; message: string };
const EMAIL = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
const isObject = (value: unknown): value is Record<string, unknown> => typeof value === "object" && value !== null && !Array.isArray(value);
const isFilled = (value: unknown): value is string => typeof value === "string" && value.trim() !== "";
// A line break in the subject would end its header and start another one.
const oneLine = (text: string): string => text.replace(/[\r\n]+/g, " ").trim();
/** The URL of the mail service's send endpoint, from its base URL (runtimeConfig.mailApiUrl). */
export const mailSendUrl = (mailApiUrl: string): string => `${mailApiUrl.replace(/\/+$/, "")}${MAIL_SEND_PATH}`;
/** Checks the form's body { name, email, subject?, message } and builds the mail to the shop. */
export const contactMail = (body: unknown): ContactMailResult => {
const fields: Record<string, unknown> = isObject(body) ? body : {};
const { name, email, subject, message } = fields;
if (!isFilled(name) || !isFilled(email) || !isFilled(message)) {
return { ok: false, message: "Name, E-Mail und Nachricht sind erforderlich" };
}
if (!EMAIL.test(email)) {
return { ok: false, message: "Ungültige E-Mail-Adresse" };
}
const topic = typeof subject === "string" ? oneLine(subject) : "";
return {
ok: true,
mail: {
to_email: CONTACT_RECIPIENT,
subject: `Kontaktanfrage: ${topic || "Anfrage über Website"}`,
message: [
`Name: ${name}`,
`E-Mail: ${email}`,
`Betreff: ${topic || "Kontaktanfrage über Website"}`,
"",
"Nachricht:",
message,
"",
"---",
"Diese Nachricht wurde über das Kontaktformular auf muellerprints.de gesendet."
].join("\n")
}
};
};