diff --git a/src/components/ContactFormInline.astro b/src/components/ContactFormInline.astro
index 54ad4f9..76a9f53 100644
--- a/src/components/ContactFormInline.astro
+++ b/src/components/ContactFormInline.astro
@@ -230,7 +230,7 @@ const fieldClass =
diff --git a/src/pages/api/contact.ts b/src/pages/api/contact.ts
index 6bd9d57..80745e3 100644
--- a/src/pages/api/contact.ts
+++ b/src/pages/api/contact.ts
@@ -13,10 +13,16 @@ function getRuntimeEnv(): RuntimeEnv {
function readEnv(name: string, runtimeEnv: RuntimeEnv): string {
const runtimeValue = runtimeEnv[name];
if (typeof runtimeValue === 'string' && runtimeValue.trim().length > 0) {
- return runtimeValue.trim();
+ return runtimeValue.trim().replace(/^['"]+|['"]+$/g, '').trim();
}
const staticValue = import.meta.env[name];
- return typeof staticValue === 'string' ? staticValue.trim() : '';
+ return typeof staticValue === 'string'
+ ? staticValue.trim().replace(/^['"]+|['"]+$/g, '').trim()
+ : '';
+}
+
+function looksLikeEmail(value: string): boolean {
+ return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value);
}
function sanitizeRedirect(candidate: string, requestUrl: URL): string {
@@ -87,23 +93,36 @@ async function verifyTurnstile(token: string, secret: string, ip?: string | null
return payload.success === true;
}
-function resolveDepartmentRecipient(runtimeEnv: RuntimeEnv, defaultRecipient: string, department: string): string {
+/**
+ * Destinatario per area. Override solo se l'indirizzo è valido;
+ * altrimenti usa sempre CONTACT_FORM_TO_EMAIL (evita secret INFO/PRIVACY malformati).
+ */
+function resolveDepartmentRecipient(
+ runtimeEnv: RuntimeEnv,
+ defaultRecipient: string,
+ department: string,
+): string {
const normalized = department.trim().toLowerCase();
- const map: Record = {
- info: readEnv('CONTACT_FORM_TO_EMAIL_INFO', runtimeEnv) || defaultRecipient,
- privacy: readEnv('CONTACT_FORM_TO_EMAIL_PRIVACY', runtimeEnv),
- careers: readEnv('CONTACT_FORM_TO_EMAIL_CAREERS', runtimeEnv),
- };
- return map[normalized] || defaultRecipient;
+ if (!normalized || normalized === 'info') {
+ return defaultRecipient;
+ }
+ const override =
+ normalized === 'privacy'
+ ? readEnv('CONTACT_FORM_TO_EMAIL_PRIVACY', runtimeEnv)
+ : normalized === 'careers'
+ ? readEnv('CONTACT_FORM_TO_EMAIL_CAREERS', runtimeEnv)
+ : '';
+ return looksLikeEmail(override) ? override : defaultRecipient;
}
export const POST: APIRoute = async ({ request, url }) => {
try {
const runtimeEnv = getRuntimeEnv();
const mode = readEnv('CONTACT_FORM_MODE', runtimeEnv).toLowerCase() || 'dev';
+ // Preferisci il mittente newsletter (secret già usato con successo) sul Variable del form.
const fromEmail =
- readEnv('CONTACT_FORM_FROM_EMAIL', runtimeEnv) ||
- readEnv('NEWSLETTER_FROM_EMAIL', runtimeEnv);
+ readEnv('NEWSLETTER_FROM_EMAIL', runtimeEnv) ||
+ readEnv('CONTACT_FORM_FROM_EMAIL', runtimeEnv);
const toEmail =
readEnv('CONTACT_FORM_TO_EMAIL', runtimeEnv) ||
readEnv('NEWSLETTER_NOTIFY_TO_EMAIL', runtimeEnv);
@@ -176,8 +195,12 @@ export const POST: APIRoute = async ({ request, url }) => {
return fail(request, USER_SEND_ERROR, 500);
}
const destination = resolveDepartmentRecipient(runtimeEnv, toEmail, department);
- if (!destination) {
- console.error('[contact] empty department recipient', { department });
+ if (!looksLikeEmail(fromEmail) || !looksLikeEmail(destination)) {
+ console.error('[contact] invalid from/to email shape', {
+ fromOk: looksLikeEmail(fromEmail),
+ toOk: looksLikeEmail(destination),
+ department,
+ });
return fail(request, USER_SEND_ERROR, 500);
}
@@ -190,7 +213,13 @@ export const POST: APIRoute = async ({ request, url }) => {
replyTo: email,
});
} catch (error) {
- console.error('[contact] email failed', error);
+ console.error('[contact] email failed', {
+ code: emailErrorCode(error),
+ fromDomain: fromEmail.split('@')[1] || '',
+ toDomain: destination.split('@')[1] || '',
+ department,
+ error,
+ });
// Retry without replyTo: some payloads reject Reply-To even when From/To are valid.
try {
await sendCloudflareEmail(emailBinding, {
@@ -202,6 +231,8 @@ export const POST: APIRoute = async ({ request, url }) => {
} catch (retryError) {
console.error('[contact] email retry failed', {
code: emailErrorCode(retryError),
+ fromDomain: fromEmail.split('@')[1] || '',
+ toDomain: destination.split('@')[1] || '',
error: retryError,
});
return fail(request, userEmailErrorMessage(retryError), 502);