false, 'error' => 'method_not_allowed']); exit; } $field = function (string $key): string { return trim((string) ($_POST[$key] ?? '')); }; // Honeypot — hidden in the UI, so anything in it came from a bot. if ($field('website') !== '') { echo json_encode(['ok' => true]); exit; } $name = mb_substr($field('name'), 0, 120); $company = mb_substr($field('company'), 0, 120); $phone = mb_substr($field('phone'), 0, 40); $email = mb_substr($field('email'), 0, 160); $message = mb_substr($field('message'), 0, 4000); if ($name === '' || $phone === '') { http_response_code(400); echo json_encode(['ok' => false, 'error' => 'missing_fields']); exit; } // Never let a submitted value reach a mail header — that is how header // injection happens. Only the validated email is used as Reply-To. $replyTo = filter_var($email, FILTER_VALIDATE_EMAIL) ? $email : ''; $subject = '=?UTF-8?B?' . base64_encode('New website enquiry — ' . ($company !== '' ? $company : $name)) . '?='; $body = "New enquiry from the GrandShip Tech website\n\n" . "Name: {$name}\n" . 'Company: ' . ($company !== '' ? $company : '-') . "\n" . "Phone: {$phone}\n" . 'Email: ' . ($email !== '' ? $email : '-') . "\n\n" . "Message:\n" . ($message !== '' ? $message : '-') . "\n\n" . "---\n" . 'IP: ' . ($_SERVER['REMOTE_ADDR'] ?? '?') . "\n" . 'Time: ' . date('Y-m-d H:i:s') . "\n"; $headers = [ 'MIME-Version: 1.0', 'Content-Type: text/plain; charset=UTF-8', 'From: GrandShip Tech <' . FROM_EMAIL . '>', ]; if ($replyTo !== '') { $headers[] = 'Reply-To: ' . $replyTo; } $sent = @mail(TO_EMAIL, $subject, $body, implode("\r\n", $headers)); if (!$sent) { // Mail is not configured on the host. Keep the lead by appending it to a // local file so nothing is lost, and tell the browser to use its fallback. @file_put_contents( __DIR__ . '/contact-submissions.log', date('c') . ' | ' . $name . ' | ' . $company . ' | ' . $phone . ' | ' . $email . ' | ' . str_replace("\n", ' ', $message) . "\n", FILE_APPEND | LOCK_EX ); http_response_code(500); echo json_encode(['ok' => false, 'error' => 'mail_failed']); exit; } echo json_encode(['ok' => true]);