200) { $fails[] = 'name'; } if (empty($email) || !filter_var($email, FILTER_VALIDATE_EMAIL)) { $fails[] = 'email'; } if (empty($message) || strlen($message) > 5000) { $fails[] = 'message'; } if ($expected === -1) { $fails[] = 'captcha-no-session'; } elseif ($captcha !== $expected) { $fails[] = 'captcha-mismatch'; } if ($fails) { error_log('fraxle contact form rejected: ' . implode(',', $fails) . ' | got=' . $captcha . ' expected=' . $expected . ' | sid=' . session_id() . ' | host=' . ($_SERVER['HTTP_HOST'] ?? '?') . ' | ref=' . ($_SERVER['HTTP_REFERER'] ?? '?')); header('Location: /?error=details#contact'); exit; } // Sanitize for email body $safeName = strip_tags($name); $safeEmail = strip_tags($email); $safeMessage = strip_tags($message); $to = 'wizard@fraxle.net'; $subject = "Fraxle.net enquiry from $safeName"; $body = "You have a new enquiry from your website.\n\n" . "Name: $safeName\n" . "Email: $safeEmail\n" . "Message:\n$safeMessage\n\n" . "---\nSent via fraxle.net contact form"; $headers = "From: noreply@fraxle.net\r\n"; $headers .= "Reply-To: $safeEmail\r\n"; $headers .= "X-Mailer: PHP/" . phpversion() . "\r\n"; $headers .= "Content-Type: text/plain; charset=UTF-8\r\n"; if (mail($to, $subject, $body, $headers)) { $_SESSION['last_submission'] = time(); header('Location: /?sent=1#contact'); } else { error_log('fraxle contact form: mail() failed for ' . $safeEmail . ' — ' . (error_get_last()['message'] ?? 'no PHP error reported')); header('Location: /?error=mail#contact'); } exit;