feat: pagina contatti e api email con validazione testata
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,31 @@
|
||||
export interface ContactData {
|
||||
firstName: string; lastName: string; phone: string;
|
||||
email: string; message: string; website: string;
|
||||
}
|
||||
|
||||
const EMAIL_RE = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
||||
|
||||
function str(v: unknown, max: number): string {
|
||||
return typeof v === 'string' ? v.trim().slice(0, max + 1) : '';
|
||||
}
|
||||
|
||||
export function validateContact(data: unknown):
|
||||
| { ok: true; value: ContactData }
|
||||
| { ok: false; error: string } {
|
||||
if (typeof data !== 'object' || data === null) return { ok: false, error: 'Dati non validi.' };
|
||||
const d = data as Record<string, unknown>;
|
||||
const value: ContactData = {
|
||||
firstName: str(d.firstName, 100),
|
||||
lastName: str(d.lastName, 100),
|
||||
phone: str(d.phone, 40),
|
||||
email: str(d.email, 200),
|
||||
message: str(d.message, 5000),
|
||||
website: str(d.website, 200),
|
||||
};
|
||||
if (value.website) return { ok: false, error: 'Richiesta non valida.' };
|
||||
if (!value.firstName) return { ok: false, error: 'Il nome è obbligatorio.' };
|
||||
if (!EMAIL_RE.test(value.email)) return { ok: false, error: 'Inserisci una e-mail valida.' };
|
||||
if (!value.message) return { ok: false, error: 'Il messaggio è obbligatorio.' };
|
||||
if (value.message.length > 5000) return { ok: false, error: 'Messaggio troppo lungo.' };
|
||||
return { ok: true, value };
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
import nodemailer from 'nodemailer';
|
||||
import { getEnv } from './env';
|
||||
import type { ContactData } from './contact';
|
||||
|
||||
export async function sendContactEmail(data: ContactData): Promise<void> {
|
||||
const transporter = nodemailer.createTransport({
|
||||
host: getEnv('SMTP_HOST'),
|
||||
port: Number(getEnv('SMTP_PORT', '587')),
|
||||
secure: Number(getEnv('SMTP_PORT', '587')) === 465,
|
||||
auth: { user: getEnv('SMTP_USER'), pass: getEnv('SMTP_PASS') },
|
||||
});
|
||||
await transporter.sendMail({
|
||||
from: getEnv('CONTACT_FROM'),
|
||||
to: getEnv('CONTACT_TO', 'info@insanitylab.it'),
|
||||
replyTo: data.email,
|
||||
subject: `Nuovo contatto dal sito: ${data.firstName} ${data.lastName}`.trim(),
|
||||
text: [
|
||||
`Nome: ${data.firstName} ${data.lastName}`.trim(),
|
||||
data.phone && `Telefono: ${data.phone}`,
|
||||
`E-mail: ${data.email}`,
|
||||
'',
|
||||
data.message,
|
||||
].filter(Boolean).join('\n'),
|
||||
});
|
||||
}
|
||||
Reference in New Issue
Block a user