Enhance API functionality and security: Added rate limiting and domain validation across multiple API endpoints, improved error handling for missing or invalid parameters, and refactored email handling in contact form for better security and maintainability. Updated README.md with production build instructions and prerequisites.
This commit is contained in:
5
public/config/mail-config.php
Normal file
5
public/config/mail-config.php
Normal file
@@ -0,0 +1,5 @@
|
||||
<?php
|
||||
/**
|
||||
* Kompatibilitäts-Wrapper – leitet auf die zentrale Backend-Konfiguration um.
|
||||
*/
|
||||
require_once __DIR__ . '/../../backend/config/mail-config.php';
|
||||
@@ -4,55 +4,28 @@
|
||||
* E-Mail-Verarbeitung mit SMTP-Integration und Spam-Schutz
|
||||
*/
|
||||
|
||||
// Session starten für CSRF-Validierung
|
||||
if (session_status() === PHP_SESSION_NONE) {
|
||||
session_start();
|
||||
}
|
||||
|
||||
// Konfiguration laden
|
||||
require_once 'config/mail-config.php';
|
||||
require_once __DIR__ . '/../backend/includes/functions.php';
|
||||
require_once __DIR__ . '/../backend/config/mail-config.php';
|
||||
require_once __DIR__ . '/../backend/config/contact-config.php';
|
||||
|
||||
// PHPMailer Autoload (falls via Composer installiert)
|
||||
if (file_exists(__DIR__ . '/vendor/autoload.php')) {
|
||||
require_once __DIR__ . '/vendor/autoload.php';
|
||||
}
|
||||
|
||||
// Konfiguration verwenden
|
||||
$config = getHexaHostConfig();
|
||||
|
||||
// Betreff-Mapping (zentral definiert)
|
||||
const SUBJECT_MAP = [
|
||||
'allgemeine-anfrage' => 'Allgemeine Anfrage',
|
||||
'vpc-anfrage' => 'Virtual Private Container Anfrage',
|
||||
'vps-anfrage' => 'Virtual Private Server Anfrage',
|
||||
'mail-gateway-anfrage' => 'Mail Gateway Anfrage',
|
||||
'webhosting-anfrage' => 'Webhosting Anfrage',
|
||||
'support' => 'Technischer Support',
|
||||
'beratung' => 'Persönliche Beratung',
|
||||
'migration' => 'Migration/Umzug',
|
||||
'sonstiges' => 'Sonstige Anfrage'
|
||||
];
|
||||
|
||||
// CSRF-Token validieren und invalidieren (verhindert Replay-Attacks)
|
||||
function validateCSRFToken($token) {
|
||||
if (isset($_SESSION['csrf_token']) && hash_equals($_SESSION['csrf_token'], $token)) {
|
||||
// Token nach erfolgreicher Validierung invalidieren
|
||||
unset($_SESSION['csrf_token']);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// CORS Headers für AJAX-Requests (nur eigene Domain erlauben)
|
||||
$allowed_origins = [
|
||||
'https://hexahost.de',
|
||||
'https://www.hexahost.de',
|
||||
'http://localhost', // Für Entwicklung
|
||||
'http://127.0.0.1' // Für Entwicklung
|
||||
'https://dev.hexahost.de',
|
||||
'http://localhost',
|
||||
'http://127.0.0.1',
|
||||
];
|
||||
|
||||
$origin = $_SERVER['HTTP_ORIGIN'] ?? '';
|
||||
if (in_array($origin, $allowed_origins)) {
|
||||
if (in_array($origin, $allowed_origins, true)) {
|
||||
header('Access-Control-Allow-Origin: ' . $origin);
|
||||
}
|
||||
|
||||
@@ -60,104 +33,82 @@ header('Access-Control-Allow-Methods: POST');
|
||||
header('Access-Control-Allow-Headers: Content-Type');
|
||||
header('Content-Type: application/json; charset=utf-8');
|
||||
|
||||
// Nur POST-Requests erlauben
|
||||
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
|
||||
http_response_code(405);
|
||||
echo json_encode(['success' => false, 'message' => 'Method not allowed']);
|
||||
exit;
|
||||
}
|
||||
|
||||
// Rate Limiting
|
||||
function checkRateLimit($ip) {
|
||||
global $config;
|
||||
$cache_file = sys_get_temp_dir() . '/hexahost_contact_' . md5($ip) . '.txt';
|
||||
$current_time = time();
|
||||
|
||||
if (file_exists($cache_file)) {
|
||||
$data = json_decode(file_get_contents($cache_file), true);
|
||||
if ($data && isset($data['requests'])) {
|
||||
// Entferne alte Einträge (älter als 1 Stunde)
|
||||
$data['requests'] = array_filter($data['requests'], function($timestamp) use ($current_time) {
|
||||
return ($current_time - $timestamp) < 3600;
|
||||
});
|
||||
|
||||
if (count($data['requests']) >= $config['max_requests_per_hour']) {
|
||||
return false;
|
||||
$data = ['requests' => []];
|
||||
|
||||
$handle = @fopen($cache_file, 'c+');
|
||||
if ($handle === false) {
|
||||
return true;
|
||||
}
|
||||
|
||||
try {
|
||||
if (!flock($handle, LOCK_EX)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$contents = stream_get_contents($handle);
|
||||
if ($contents !== false && $contents !== '') {
|
||||
$decoded = json_decode($contents, true);
|
||||
if (is_array($decoded) && isset($decoded['requests'])) {
|
||||
$data = $decoded;
|
||||
}
|
||||
}
|
||||
|
||||
$data['requests'] = array_values(array_filter(
|
||||
$data['requests'],
|
||||
static fn($timestamp) => ($current_time - (int) $timestamp) < 3600
|
||||
));
|
||||
|
||||
if (count($data['requests']) >= $config['max_requests_per_hour']) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$data['requests'][] = $current_time;
|
||||
ftruncate($handle, 0);
|
||||
rewind($handle);
|
||||
fwrite($handle, json_encode($data));
|
||||
} finally {
|
||||
flock($handle, LOCK_UN);
|
||||
fclose($handle);
|
||||
}
|
||||
|
||||
// Füge aktuellen Request hinzu
|
||||
$data = isset($data) ? $data : ['requests' => []];
|
||||
$data['requests'][] = $current_time;
|
||||
file_put_contents($cache_file, json_encode($data));
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// Honeypot Check
|
||||
function checkHoneypot($data) {
|
||||
global $config;
|
||||
$honeypot_field = $config['honeypot_field'];
|
||||
|
||||
// Das Honeypot-Feld sollte leer sein (verstecktes Feld)
|
||||
if (!empty($data[$honeypot_field])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
return empty($data[$honeypot_field]);
|
||||
}
|
||||
|
||||
// E-Mail-Validierung
|
||||
function validateEmail($email) {
|
||||
return filter_var($email, FILTER_VALIDATE_EMAIL) !== false;
|
||||
function sanitizeFormField($input) {
|
||||
return strip_tags(trim((string) $input));
|
||||
}
|
||||
|
||||
// Input-Sanitization
|
||||
function sanitizeInput($input) {
|
||||
return htmlspecialchars(strip_tags(trim($input)), ENT_QUOTES, 'UTF-8');
|
||||
function getSubjectLabel($subjectKey) {
|
||||
$map = getContactSubjectMap();
|
||||
return $map[$subjectKey] ?? 'Neue Kontaktanfrage';
|
||||
}
|
||||
|
||||
// Sichere IP-Adressen-Erkennung (auch hinter Proxies/Cloudflare)
|
||||
function getClientIP() {
|
||||
$ip_keys = [
|
||||
'HTTP_CF_CONNECTING_IP', // Cloudflare
|
||||
'HTTP_X_FORWARDED_FOR', // Proxy
|
||||
'HTTP_X_REAL_IP', // Nginx Proxy
|
||||
'REMOTE_ADDR' // Standard
|
||||
];
|
||||
|
||||
foreach ($ip_keys as $key) {
|
||||
if (!empty($_SERVER[$key])) {
|
||||
// Bei X-Forwarded-For kann eine Liste von IPs kommen
|
||||
$ip = explode(',', $_SERVER[$key])[0];
|
||||
$ip = trim($ip);
|
||||
|
||||
// Validiere IP-Format
|
||||
if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE)) {
|
||||
return $ip;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback auf REMOTE_ADDR (auch private IPs für lokale Entwicklung)
|
||||
return $_SERVER['REMOTE_ADDR'] ?? '0.0.0.0';
|
||||
}
|
||||
|
||||
// SMTP E-Mail-Versand mit PHPMailer
|
||||
function sendEmail($data) {
|
||||
global $config;
|
||||
|
||||
// PHPMailer laden (falls verfügbar)
|
||||
|
||||
if (!class_exists('PHPMailer\PHPMailer\PHPMailer')) {
|
||||
// Fallback: Native PHP mail() Funktion
|
||||
return sendEmailNative($data);
|
||||
}
|
||||
|
||||
|
||||
try {
|
||||
$mail = new PHPMailer\PHPMailer\PHPMailer(true);
|
||||
|
||||
// Server-Einstellungen
|
||||
|
||||
$mail->isSMTP();
|
||||
$mail->Host = $config['smtp_host'];
|
||||
$mail->SMTPAuth = true;
|
||||
@@ -166,73 +117,60 @@ function sendEmail($data) {
|
||||
$mail->SMTPSecure = $config['smtp_encryption'];
|
||||
$mail->Port = $config['smtp_port'];
|
||||
$mail->CharSet = 'UTF-8';
|
||||
|
||||
// Absender
|
||||
|
||||
$mail->setFrom($config['from_email'], $config['from_name']);
|
||||
$mail->addReplyTo($data['email'], $data['firstName'] . ' ' . $data['lastName']);
|
||||
|
||||
// Empfänger
|
||||
$mail->addReplyTo(
|
||||
sanitizeHeaderValue($data['email']),
|
||||
sanitizeHeaderValue($data['firstName'] . ' ' . $data['lastName'])
|
||||
);
|
||||
$mail->addAddress($config['to_email'], $config['to_name']);
|
||||
|
||||
// Betreff (nutzt zentrale SUBJECT_MAP Konstante)
|
||||
$subject = SUBJECT_MAP[$data['subject']] ?? 'Neue Kontaktanfrage';
|
||||
|
||||
$subject = getSubjectLabel($data['subject']);
|
||||
$mail->Subject = '[HexaHost.de] ' . $subject;
|
||||
|
||||
// HTML E-Mail-Inhalt
|
||||
$html_content = generateEmailHTML($data);
|
||||
|
||||
$mail->isHTML(true);
|
||||
$mail->Body = $html_content;
|
||||
$mail->Body = generateEmailHTML($data);
|
||||
$mail->AltBody = generateEmailText($data);
|
||||
|
||||
// Anti-Spam Headers
|
||||
|
||||
$mail->addCustomHeader('X-Mailer', 'HexaHost Contact Form');
|
||||
$mail->addCustomHeader('X-Priority', '3');
|
||||
$mail->addCustomHeader('X-MSMail-Priority', 'Normal');
|
||||
$mail->addCustomHeader('Importance', 'Normal');
|
||||
$mail->addCustomHeader('X-Report-Abuse', 'Please report abuse here: abuse@hexahost.de');
|
||||
|
||||
// DKIM, SPF, DMARC werden über DNS konfiguriert
|
||||
|
||||
|
||||
$mail->send();
|
||||
return true;
|
||||
|
||||
} catch (Exception $e) {
|
||||
error_log('HexaHost Contact Form Error: ' . $e->getMessage());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Fallback: Native PHP mail() Funktion
|
||||
function sendEmailNative($data) {
|
||||
global $config;
|
||||
|
||||
// Betreff (nutzt zentrale SUBJECT_MAP Konstante)
|
||||
$subject = SUBJECT_MAP[$data['subject']] ?? 'Neue Kontaktanfrage';
|
||||
$subject = '[HexaHost.de] ' . $subject;
|
||||
|
||||
// Headers für Spam-Schutz
|
||||
|
||||
$subject = '[HexaHost.de] ' . getSubjectLabel($data['subject']);
|
||||
$replyName = sanitizeHeaderValue($data['firstName'] . ' ' . $data['lastName']);
|
||||
$replyEmail = sanitizeHeaderValue($data['email']);
|
||||
|
||||
$headers = [
|
||||
'From: ' . $config['from_name'] . ' <' . $config['from_email'] . '>',
|
||||
'Reply-To: ' . $data['firstName'] . ' ' . $data['lastName'] . ' <' . $data['email'] . '>',
|
||||
'Reply-To: ' . $replyName . ' <' . $replyEmail . '>',
|
||||
'MIME-Version: 1.0',
|
||||
'Content-Type: text/html; charset=UTF-8',
|
||||
'X-Mailer: HexaHost Contact Form',
|
||||
'X-Priority: 3',
|
||||
'X-MSMail-Priority: Normal',
|
||||
'Importance: Normal',
|
||||
'X-Report-Abuse: Please report abuse here: abuse@hexahost.de'
|
||||
'X-Report-Abuse: Please report abuse here: abuse@hexahost.de',
|
||||
];
|
||||
|
||||
$message = generateEmailHTML($data);
|
||||
|
||||
return mail($config['to_email'], $subject, $message, implode("\r\n", $headers));
|
||||
|
||||
return mail($config['to_email'], $subject, generateEmailHTML($data), implode("\r\n", $headers));
|
||||
}
|
||||
|
||||
// HTML E-Mail-Template
|
||||
function generateEmailHTML($data) {
|
||||
// Betreff (nutzt zentrale SUBJECT_MAP Konstante)
|
||||
$subject_text = SUBJECT_MAP[$data['subject']] ?? 'Neue Kontaktanfrage';
|
||||
|
||||
$subject_text = htmlspecialchars(getSubjectLabel($data['subject']), ENT_QUOTES, 'UTF-8');
|
||||
|
||||
$html = '
|
||||
<!DOCTYPE html>
|
||||
<html lang="de">
|
||||
@@ -267,39 +205,39 @@ function generateEmailHTML($data) {
|
||||
|
||||
<div class="field">
|
||||
<div class="label">Name:</div>
|
||||
<div class="value">' . $data['firstName'] . ' ' . $data['lastName'] . '</div>
|
||||
<div class="value">' . htmlspecialchars($data['firstName'] . ' ' . $data['lastName'], ENT_QUOTES, 'UTF-8') . '</div>
|
||||
</div>
|
||||
|
||||
<div class="field">
|
||||
<div class="label">E-Mail:</div>
|
||||
<div class="value">' . $data['email'] . '</div>
|
||||
<div class="value">' . htmlspecialchars($data['email'], ENT_QUOTES, 'UTF-8') . '</div>
|
||||
</div>';
|
||||
|
||||
|
||||
if (!empty($data['phone'])) {
|
||||
$html .= '
|
||||
<div class="field">
|
||||
<div class="label">Telefon:</div>
|
||||
<div class="value">' . $data['phone'] . '</div>
|
||||
<div class="value">' . htmlspecialchars($data['phone'], ENT_QUOTES, 'UTF-8') . '</div>
|
||||
</div>';
|
||||
}
|
||||
|
||||
|
||||
if (!empty($data['company'])) {
|
||||
$html .= '
|
||||
<div class="field">
|
||||
<div class="label">Unternehmen:</div>
|
||||
<div class="value">' . $data['company'] . '</div>
|
||||
<div class="value">' . htmlspecialchars($data['company'], ENT_QUOTES, 'UTF-8') . '</div>
|
||||
</div>';
|
||||
}
|
||||
|
||||
|
||||
$html .= '
|
||||
<div class="field">
|
||||
<div class="label">Nachricht:</div>
|
||||
<div class="message">' . nl2br($data['message']) . '</div>
|
||||
<div class="message">' . nl2br(htmlspecialchars($data['message'], ENT_QUOTES, 'UTF-8')) . '</div>
|
||||
</div>
|
||||
|
||||
<div class="field">
|
||||
<div class="label">IP-Adresse:</div>
|
||||
<div class="value">' . htmlspecialchars(getClientIP()) . '</div>
|
||||
<div class="value">' . htmlspecialchars(getClientIP(), ENT_QUOTES, 'UTF-8') . '</div>
|
||||
</div>
|
||||
|
||||
<div class="field">
|
||||
@@ -315,138 +253,159 @@ function generateEmailHTML($data) {
|
||||
</div>
|
||||
</body>
|
||||
</html>';
|
||||
|
||||
|
||||
return $html;
|
||||
}
|
||||
|
||||
// Text-Version der E-Mail
|
||||
function generateEmailText($data) {
|
||||
// Betreff (nutzt zentrale SUBJECT_MAP Konstante)
|
||||
$subject_text = SUBJECT_MAP[$data['subject']] ?? 'Neue Kontaktanfrage';
|
||||
|
||||
$text = "NEUE KONTAKTANFRAGE - HexaHost.de\n";
|
||||
$text .= "=====================================\n\n";
|
||||
$text .= "Betreff: " . $subject_text . "\n";
|
||||
$text .= "Betreff: " . getSubjectLabel($data['subject']) . "\n";
|
||||
$text .= "Name: " . $data['firstName'] . " " . $data['lastName'] . "\n";
|
||||
$text .= "E-Mail: " . $data['email'] . "\n";
|
||||
|
||||
|
||||
if (!empty($data['phone'])) {
|
||||
$text .= "Telefon: " . $data['phone'] . "\n";
|
||||
}
|
||||
|
||||
|
||||
if (!empty($data['company'])) {
|
||||
$text .= "Unternehmen: " . $data['company'] . "\n";
|
||||
}
|
||||
|
||||
|
||||
$text .= "\nNachricht:\n";
|
||||
$text .= "----------\n";
|
||||
$text .= $data['message'] . "\n\n";
|
||||
|
||||
$text .= "IP-Adresse: " . getClientIP() . "\n";
|
||||
$text .= "Zeitstempel: " . date('d.m.Y H:i:s') . "\n\n";
|
||||
|
||||
$text .= "---\n";
|
||||
$text .= "Diese E-Mail wurde automatisch vom HexaHost.de Kontaktformular generiert.\n";
|
||||
$text .= "© " . date('Y') . " HexaHost.de - Alle Rechte vorbehalten";
|
||||
|
||||
|
||||
return $text;
|
||||
}
|
||||
|
||||
// Hauptverarbeitung
|
||||
try {
|
||||
// CSRF-Token validieren
|
||||
if (empty($_POST['csrf_token']) || !validateCSRFToken($_POST['csrf_token'])) {
|
||||
http_response_code(403);
|
||||
echo json_encode([
|
||||
'success' => false,
|
||||
'message' => 'Ungültige Sitzung. Bitte laden Sie die Seite neu und versuchen Sie es erneut.'
|
||||
]);
|
||||
exit;
|
||||
if (!empty($config['enable_csrf'])) {
|
||||
if (empty($_POST['csrf_token']) || !validateCSRFToken($_POST['csrf_token'])) {
|
||||
http_response_code(403);
|
||||
echo json_encode([
|
||||
'success' => false,
|
||||
'message' => 'Ungültige Sitzung. Bitte laden Sie die Seite neu und versuchen Sie es erneut.',
|
||||
]);
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
// Rate Limiting Check
|
||||
$client_ip = getClientIP();
|
||||
if (!checkRateLimit($client_ip)) {
|
||||
|
||||
if (!checkRateLimit(getClientIP())) {
|
||||
http_response_code(429);
|
||||
echo json_encode([
|
||||
'success' => false,
|
||||
'message' => 'Zu viele Anfragen. Bitte versuchen Sie es später erneut.'
|
||||
'success' => false,
|
||||
'message' => 'Zu viele Anfragen. Bitte versuchen Sie es später erneut.',
|
||||
]);
|
||||
exit;
|
||||
}
|
||||
|
||||
// Honeypot Check
|
||||
|
||||
if (!checkHoneypot($_POST)) {
|
||||
http_response_code(400);
|
||||
echo json_encode([
|
||||
'success' => false,
|
||||
'message' => 'Ungültige Anfrage.'
|
||||
]);
|
||||
echo json_encode(['success' => false, 'message' => 'Ungültige Anfrage.']);
|
||||
exit;
|
||||
}
|
||||
|
||||
// Pflichtfelder prüfen
|
||||
|
||||
$required_fields = ['firstName', 'lastName', 'email', 'subject', 'message', 'privacy'];
|
||||
$missing_fields = [];
|
||||
|
||||
|
||||
foreach ($required_fields as $field) {
|
||||
if (empty($_POST[$field])) {
|
||||
$missing_fields[] = $field;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (!empty($missing_fields)) {
|
||||
http_response_code(400);
|
||||
echo json_encode([
|
||||
'success' => false,
|
||||
'success' => false,
|
||||
'message' => 'Bitte füllen Sie alle Pflichtfelder aus.',
|
||||
'missing_fields' => $missing_fields
|
||||
'missing_fields' => $missing_fields,
|
||||
]);
|
||||
exit;
|
||||
}
|
||||
|
||||
// E-Mail-Validierung
|
||||
if (!validateEmail($_POST['email'])) {
|
||||
|
||||
$subjectKey = trim((string) $_POST['subject']);
|
||||
if (!isAllowedContactSubject($subjectKey)) {
|
||||
http_response_code(400);
|
||||
echo json_encode([
|
||||
'success' => false,
|
||||
'message' => 'Bitte geben Sie eine gültige E-Mail-Adresse ein.'
|
||||
'success' => false,
|
||||
'message' => 'Bitte wählen Sie einen gültigen Betreff.',
|
||||
]);
|
||||
exit;
|
||||
}
|
||||
|
||||
// Daten sanitieren
|
||||
$data = [
|
||||
'firstName' => sanitizeInput($_POST['firstName']),
|
||||
'lastName' => sanitizeInput($_POST['lastName']),
|
||||
'email' => sanitizeInput($_POST['email']),
|
||||
'phone' => sanitizeInput($_POST['phone'] ?? ''),
|
||||
'company' => sanitizeInput($_POST['company'] ?? ''),
|
||||
'subject' => sanitizeInput($_POST['subject']),
|
||||
'message' => sanitizeInput($_POST['message']),
|
||||
'privacy' => isset($_POST['privacy']) ? true : false
|
||||
];
|
||||
|
||||
// E-Mail senden
|
||||
if (sendEmail($data)) {
|
||||
|
||||
$email = trim((string) $_POST['email']);
|
||||
if (!isValidEmail($email)) {
|
||||
http_response_code(400);
|
||||
echo json_encode([
|
||||
'success' => true,
|
||||
'message' => 'Ihre Nachricht wurde erfolgreich gesendet! Wir melden uns in Kürze bei Ihnen.'
|
||||
'success' => false,
|
||||
'message' => 'Bitte geben Sie eine gültige E-Mail-Adresse ein.',
|
||||
]);
|
||||
exit;
|
||||
}
|
||||
|
||||
$message = trim((string) $_POST['message']);
|
||||
$messageLength = mb_strlen($message, 'UTF-8');
|
||||
|
||||
if ($messageLength < $config['min_message_length']) {
|
||||
http_response_code(400);
|
||||
echo json_encode([
|
||||
'success' => false,
|
||||
'message' => 'Ihre Nachricht ist zu kurz.',
|
||||
]);
|
||||
exit;
|
||||
}
|
||||
|
||||
if ($messageLength > $config['max_message_length']) {
|
||||
http_response_code(400);
|
||||
echo json_encode([
|
||||
'success' => false,
|
||||
'message' => 'Ihre Nachricht ist zu lang.',
|
||||
]);
|
||||
exit;
|
||||
}
|
||||
|
||||
$data = [
|
||||
'firstName' => sanitizeFormField($_POST['firstName']),
|
||||
'lastName' => sanitizeFormField($_POST['lastName']),
|
||||
'email' => sanitizeHeaderValue($email),
|
||||
'phone' => sanitizeFormField($_POST['phone'] ?? ''),
|
||||
'company' => sanitizeFormField($_POST['company'] ?? ''),
|
||||
'subject' => $subjectKey,
|
||||
'message' => sanitizeFormField($message),
|
||||
'privacy' => isset($_POST['privacy']),
|
||||
];
|
||||
|
||||
if (sendEmail($data)) {
|
||||
if (LOG_EMAILS) {
|
||||
logEmail('sent', [
|
||||
'subject' => $subjectKey,
|
||||
'email' => $data['email'],
|
||||
'ip' => getClientIP(),
|
||||
]);
|
||||
}
|
||||
echo json_encode([
|
||||
'success' => true,
|
||||
'message' => 'Ihre Nachricht wurde erfolgreich gesendet! Wir melden uns in Kürze bei Ihnen.',
|
||||
]);
|
||||
} else {
|
||||
http_response_code(500);
|
||||
echo json_encode([
|
||||
'success' => false,
|
||||
'message' => 'Beim Senden der Nachricht ist ein Fehler aufgetreten. Bitte versuchen Sie es später erneut.'
|
||||
'success' => false,
|
||||
'message' => 'Beim Senden der Nachricht ist ein Fehler aufgetreten. Bitte versuchen Sie es später erneut.',
|
||||
]);
|
||||
}
|
||||
|
||||
} catch (Exception $e) {
|
||||
error_log('HexaHost Contact Form Error: ' . $e->getMessage());
|
||||
http_response_code(500);
|
||||
echo json_encode([
|
||||
'success' => false,
|
||||
'message' => 'Ein unerwarteter Fehler ist aufgetreten. Bitte versuchen Sie es später erneut.'
|
||||
'success' => false,
|
||||
'message' => 'Ein unerwarteter Fehler ist aufgetreten. Bitte versuchen Sie es später erneut.',
|
||||
]);
|
||||
}
|
||||
?>
|
||||
@@ -1,5 +1,8 @@
|
||||
<?php
|
||||
require_once __DIR__ . '/../backend/includes/functions.php';
|
||||
require_once __DIR__ . '/../backend/config/contact-config.php';
|
||||
|
||||
$preselected_subject = getPreselectedContactSubject();
|
||||
|
||||
// Page configuration
|
||||
$page_title = 'Kontakt - HexaHost.de | Hosting aus Niederbayern';
|
||||
@@ -129,21 +132,9 @@ includeHeader($page_title, $page_description, $current_page, $additional_scripts
|
||||
<label for="subject">Betreff *</label>
|
||||
<select id="subject" name="subject" required>
|
||||
<option value="">Bitte wählen...</option>
|
||||
<option value="allgemeine-anfrage">Allgemeine Anfrage</option>
|
||||
<option value="vpc-anfrage">Virtual Private Container</option>
|
||||
<option value="vps-anfrage">Virtual Private Server</option>
|
||||
<option value="mail-gateway-anfrage">Mail Gateway</option>
|
||||
<option value="webhosting-anfrage">Webhosting</option>
|
||||
<option value="it-beratung">IT-Beratung</option>
|
||||
<option value="it-support">IT-Support & Fehlerbehebung</option>
|
||||
<option value="netzwerk-wlan">Netzwerk & WLAN-Einrichtung</option>
|
||||
<option value="it-sicherheit-backup">IT-Sicherheit & Backup</option>
|
||||
<option value="webseiten-hosting-service">Webseiten- & Hosting-Service</option>
|
||||
<option value="wartung-betreuung">Wartung & Betreuung</option>
|
||||
<option value="support">Technischer Support</option>
|
||||
<option value="beratung">Persönliche Beratung</option>
|
||||
<option value="migration">Migration/Umzug</option>
|
||||
<option value="sonstiges">Sonstiges</option>
|
||||
<?php foreach (getContactSubjectMap() as $subjectKey => $subjectLabel): ?>
|
||||
<option value="<?php echo htmlspecialchars($subjectKey, ENT_QUOTES, 'UTF-8'); ?>"<?php echo $preselected_subject === $subjectKey ? ' selected' : ''; ?>><?php echo htmlspecialchars($subjectLabel, ENT_QUOTES, 'UTF-8'); ?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
|
||||
Reference in New Issue
Block a user