diff --git a/process_email.php b/process_email.php index 4294622..86b6a45 100644 --- a/process_email.php +++ b/process_email.php @@ -5,86 +5,84 @@ ini_set('display_startup_errors', 1); error_reporting(E_ALL); // Erhöhen Sie das Speicherlimit und die Ausführungszeit für potenziell große E-Mails -// NEUE WERTE: 512MB Speicher, 300 Sekunden (5 Minuten) Ausführungszeit ini_set('memory_limit', '512M'); -set_time_limit(300); +set_time_limit(600); // Setze die interne Zeichenkodierung auf UTF-8 für alle Multi-Byte-String-Funktionen -// Dies ist entscheidend für die korrekte Verarbeitung von Emojis und Sonderzeichen. mb_internal_encoding("UTF-8"); mb_regex_encoding("UTF-8"); // Auch für Regex-Funktionen +// --- Eigene Log-Funktion --- +function log_message($message) { + $log_file = __DIR__ . '/email_analysis.log'; + $timestamp = date('Y-m-d H:i:s'); + file_put_contents($log_file, "$timestamp: $message\n", FILE_APPEND | LOCK_EX); +} + function parseEmailHeaders($emailContent) { + log_message("Starting parseEmailHeaders function."); $headers = []; - // Stellen Sie sicher, dass $emailContent ein String ist, bevor explode aufgerufen wird. if (!is_string($emailContent)) { + log_message("ERROR: emailContent is not a string in parseEmailHeaders."); return $headers; } $lines = explode("\n", $emailContent); $inHeaders = true; $currentHeader = ''; - $headerValueBuffer = ''; // Puffer für mehrzeilige Header-Werte + $headerValueBuffer = ''; foreach ($lines as $line) { - $line = rtrim($line, "\r"); // Entferne CR am Ende - $line = trim($line); // Trimmt Leerzeichen am Anfang und Ende + $line = rtrim($line, "\r"); + $line = trim($line); if (empty($line)) { - // Leere Zeile bedeutet Ende der Header. Verarbeite den letzten Header im Puffer. if ($currentHeader !== '' && $headerValueBuffer !== '') { $headers[$currentHeader] = trim($headerValueBuffer); + log_message("Parsed header: " . $currentHeader . " = " . mb_substr(trim($headerValueBuffer), 0, 100) . "..."); } $inHeaders = false; continue; } if ($inHeaders) { - // Wenn die Zeile mit Leerzeichen oder Tab beginnt, ist es eine Fortsetzung des vorherigen Headers if (preg_match('/^\s/', $line)) { if ($currentHeader !== '') { - $headerValueBuffer .= ' ' . $line; // Füge zur Puffer hinzu + $headerValueBuffer .= ' ' . $line; } } else { - // Neuer Header: Verarbeite zuerst den vorherigen Header, falls vorhanden if ($currentHeader !== '' && $headerValueBuffer !== '') { $headers[$currentHeader] = trim($headerValueBuffer); + log_message("Parsed header: " . $currentHeader . " = " . mb_substr(trim($headerValueBuffer), 0, 100) . "..."); } - // Parsen des neuen Headers - if (preg_match('/^([^:]+):(.*)$/U', $line, $matches)) { // /U für ungreedy + if (preg_match('/^([^:]+):(.*)$/U', $line, $matches)) { $headerName = trim($matches[1]); - $headerValueBuffer = trim($matches[2]); // Initialisiere Puffer mit neuem Wert - $headers[$headerName] = $headerValueBuffer; // vorläufig speichern + $headerValueBuffer = trim($matches[2]); $currentHeader = $headerName; } else { - // Zeile sieht nicht nach einem Header aus, könnte aber Teil des Bodies sein, - // der fälschlicherweise in den Header-Bereich gerutscht ist. - // Oder ein fehlerhafter Header. - // Ignoriere die Zeile oder hänge sie an den letzten Header an, - // aber sei vorsichtig, um unendliche Schleifen oder Speicherprobleme zu vermeiden. - // Hier wird sie ignoriert, um Robustheit zu gewährleisten. - $currentHeader = ''; // Setze aktuellen Header zurück, um weitere Anhängungen zu verhindern + log_message("WARNING: Line in header section did not match header format: " . mb_substr($line, 0, 100) . "..."); + $currentHeader = ''; $headerValueBuffer = ''; } } } else { - // Nach den Headern sind wir im Body, wir brauchen nur die Header break; } } - // Nach der Schleife den letzten gesammelten Header hinzufügen, falls vorhanden if ($currentHeader !== '' && $headerValueBuffer !== '' && !isset($headers[$currentHeader])) { $headers[$currentHeader] = trim($headerValueBuffer); + log_message("Parsed final header: " . $currentHeader . " = " . mb_substr(trim($headerValueBuffer), 0, 100) . "..."); } + log_message("Finished parseEmailHeaders function. Total headers: " . count($headers)); return $headers; } function checkPhishing($headers, $emailContent) { + log_message("Starting checkPhishing function."); $warnings = []; - $phishingScore = 0; // Ein einfacher Zähler für Phishing-Indikatoren + $phishingScore = 0; - // --- Sicherstellen, dass Headers und Content als Strings behandelt werden --- $subject = (string)($headers['Subject'] ?? ''); $from = (string)($headers['From'] ?? ''); $returnPath = (string)($headers['Return-Path'] ?? ''); @@ -92,31 +90,27 @@ function checkPhishing($headers, $emailContent) { $xMailer = (string)($headers['X-Mailer'] ?? ''); $userAgent = (string)($headers['User-Agent'] ?? ''); $authResults = (string)($headers['Authentication-Results'] ?? ''); - $emailContent = (string)$emailContent; // Sicherstellen, dass $emailContent ein String ist + $emailContent = (string)$emailContent; // --- Prüfung des E-Mail-Inhalts (Body und Betreff) - Priorität 1 --- - // 1. Häufige Phishing-Keywords im Betreff oder Body $keywords = ['bestätigung', 'konto', 'passwort', 'sicherheit', 'aktualisieren', 'blockiert', 'dringend', 'zahlung', 'rechnung', 'gewinn', 'glückwunsch', 'probleme', 'verifizierung', 'warnung']; $foundContentKeywords = 0; foreach ($keywords as $keyword) { - if (mb_stripos($subject, $keyword) !== false) { // mb_stripos für Multi-Byte-Zeichen + if (mb_stripos($subject, $keyword) !== false) { $warnings[] = "Hinweis (Inhalt): Das Wort '" . htmlspecialchars($keyword) . "' wurde im Betreff gefunden. Dies ist oft in Phishing-Mails zu finden."; $foundContentKeywords++; } - if (mb_stripos($emailContent, $keyword) !== false) { // mb_stripos für Multi-Byte-Zeichen + if (mb_stripos($emailContent, $keyword) !== false) { $warnings[] = "Hinweis (Inhalt): Das Wort '" . htmlspecialchars($keyword) . "' wurde im E-Mail-Text gefunden. Dies ist oft in Phishing-Mails zu finden."; $foundContentKeywords++; } } - if ($foundContentKeywords > 0) $phishingScore += min($foundContentKeywords, 3); // Max 3 Punkte für Keywords + if ($foundContentKeywords > 0) { + $phishingScore += min($foundContentKeywords, 3); + log_message("Phishing check: Found " . $foundContentKeywords . " keywords."); + } - // 2. Ungewöhnliche Zeichen oder Encoding im Betreff (könnte auf Verschleierung hindeuten) - // Diese Prüfung wird jetzt weniger stark gewichtet, da mb_internal_encoding hilft. - // Falls immer noch Probleme auftreten, kann man hier spezifischer nach fehlerhaften Encodings suchen. - - - // 3. Links prüfen (verbessert: prüft auf offensichtliche URL-Diskrepanzen, IPs, Shortener) $fromDomain = ''; if (preg_match('/@([^>]+)/', $from, $fromDomainMatch)) { $fromDomain = trim($fromDomainMatch[1]); @@ -124,31 +118,27 @@ function checkPhishing($headers, $emailContent) { $foundSuspiciousLinks = 0; if (preg_match_all('/https?:\/\/[^\s"\']+/i', $emailContent, $matches)) { - foreach (array_unique($matches[0]) as $url) { // Einzigartige URLs prüfen + log_message("Phishing check: Found " . count($matches[0]) . " URLs."); + foreach (array_unique($matches[0]) as $url) { $urlParts = parse_url($url); - $urlDomain = isset($urlParts['host']) ? mb_strtolower($urlParts['host']) : ''; // mb_strtolower für Multi-Byte-Zeichen + $urlDomain = isset($urlParts['host']) ? mb_strtolower($urlParts['host']) : ''; - // Check for direct IP address in URL if (filter_var($urlDomain, FILTER_VALIDATE_IP)) { $warnings[] = "Kritische Warnung (Inhalt/Links): Ein Link enthält eine direkte IP-Adresse ('" . htmlspecialchars($url) . "'). Dies ist oft verdächtig."; $phishingScore += 2; $foundSuspiciousLinks++; } - // Check if the URL domain is significantly different from the From domain if ($urlDomain && $fromDomain && !empty($fromDomain)) { - // Eine robustere Prüfung könnte hier auch Subdomain-Tricks erkennen - // z.B. bank.com.malicious.example.com - if (mb_strpos($urlDomain, $fromDomain) === false && mb_strpos($fromDomain, $urlDomain) === false) { // mb_strpos für Multi-Byte-Zeichen + if (mb_strpos($urlDomain, $fromDomain) === false && mb_strpos($fromDomain, $urlDomain) === false) { $warnings[] = "Kritische Warnung (Inhalt/Links): Die Domain im Link ('" . htmlspecialchars($urlDomain) . "') weicht von der Absenderdomain ('" . htmlspecialchars($fromDomain) . "') ab. Vorsicht!"; $phishingScore += 3; $foundSuspiciousLinks++; } } - // Add check for URL shorteners (simple regex) - $shortenerDomains = ['bit.ly', 'goo.gl', 'tinyurl.com', 'ow.ly', 't.co', 'cutt.ly', 'is.gd', 's.id']; // Add more as needed + $shortenerDomains = ['bit.ly', 'goo.gl', 'tinyurl.com', 'ow.ly', 't.co', 'cutt.ly', 'is.gd', 's.id']; foreach ($shortenerDomains as $shortener) { - if (mb_strpos($urlDomain, $shortener) !== false) { // mb_strpos für Multi-Byte-Zeichen + if (mb_strpos($urlDomain, $shortener) !== false) { $warnings[] = "Hinweis (Inhalt/Links): Ein Link verwendet einen URL-Shortener ('" . htmlspecialchars($url) . "'). Dies kann zur Verschleierung bösartiger Ziele genutzt werden."; $phishingScore += 1; $foundSuspiciousLinks++; @@ -157,11 +147,13 @@ function checkPhishing($headers, $emailContent) { } } } - if ($foundSuspiciousLinks > 0) $phishingScore += 2; // Zusätzlicher Punkt für Links + if ($foundSuspiciousLinks > 0) { + $phishingScore += 2; + log_message("Phishing check: Found " . $foundSuspiciousLinks . " suspicious links."); + } // --- Prüfung der Header-Daten - Priorität 2 --- - // 4. Absenderprüfung (From vs. Return-Path vs. Reply-To) $returnPathDomain = ''; if (preg_match('/@([^>]+)/', $returnPath, $returnPathDomainMatch)) { $returnPathDomain = trim($returnPathDomainMatch[1]); @@ -175,26 +167,28 @@ function checkPhishing($headers, $emailContent) { if ($fromDomain && $returnPathDomain && $fromDomain !== $returnPathDomain) { $warnings[] = "Warnung (Header): Die Absenderdomain ('" . htmlspecialchars($fromDomain) . "') stimmt nicht mit der 'Return-Path'-Domain ('" . htmlspecialchars($returnPathDomain) . "') überein. Dies könnte ein Indikator für Spoofing sein."; $phishingScore += 2; + log_message("Phishing check: From vs Return-Path mismatch."); } if ($fromDomain && $replyToDomain && $fromDomain !== $replyToDomain) { $warnings[] = "Warnung (Header): Die Absenderdomain ('" . htmlspecialchars($fromDomain) . "') stimmt nicht mit der 'Reply-To'-Domain ('" . htmlspecialchars($replyToDomain) . "') überein. Eine Diskrepanz kann auf Betrug hindeuten."; $phishingScore += 2; + log_message("Phishing check: From vs Reply-To mismatch."); } - // 5. Fehlende oder seltsame Header $importantHeaders = ['From', 'To', 'Subject', 'Date', 'Message-ID']; foreach ($importantHeaders as $header) { - if (!isset($headers[$header]) || empty($headers[$header])) { // Prüfe auch auf leere Header + if (!isset($headers[$header]) || empty($headers[$header])) { $warnings[] = "Hinweis (Header): Der wichtige Header '" . htmlspecialchars($header) . "' fehlt oder ist leer."; $phishingScore += 0.5; + log_message("Phishing check: Missing/empty important header: " . $header); } } - // 6. X-Mailer / User-Agent Prüfung if (empty($xMailer) && empty($userAgent)) { $warnings[] = "Hinweis (Header): 'X-Mailer' oder 'User-Agent' Header fehlen. Dies ist manchmal bei automatisierten oder ungewöhnlichen Mail-Systemen der Fall."; $phishingScore += 0.5; + log_message("Phishing check: Missing X-Mailer/User-Agent."); } else { $foundUnusualMailer = false; $commonMailers = ['microsoft outlook', 'thunderbird', 'mail.app', 'gmail']; @@ -202,7 +196,7 @@ function checkPhishing($headers, $emailContent) { if (!empty($xMailer)) { $isCommon = false; foreach($commonMailers as $mailer) { - if (mb_strpos($xMailer, $mailer) !== false) { + if (mb_strpos(mb_strtolower($xMailer), $mailer) !== false) { $isCommon = true; break; } @@ -215,7 +209,7 @@ function checkPhishing($headers, $emailContent) { if (!$foundUnusualMailer && !empty($userAgent)) { $isCommon = false; foreach($commonMailers as $mailer) { - if (mb_strpos($userAgent, $mailer) !== false) { + if (mb_strpos(mb_strtolower($userAgent), $mailer) !== false) { $isCommon = true; break; } @@ -228,126 +222,151 @@ function checkPhishing($headers, $emailContent) { if ($foundUnusualMailer) { $warnings[] = "Hinweis (Header): Ungewöhnlicher oder unbekannter E-Mail-Client im 'X-Mailer'/'User-Agent' Header erkannt ('" . htmlspecialchars($xMailer . $userAgent) . "'). Kann ein Indikator für Massenversand oder Phishing sein."; $phishingScore += 1; + log_message("Phishing check: Unusual X-Mailer/User-Agent."); } } - // 7. Prüfung von Authentication-Results Header (SPF, DKIM, DMARC) if (!empty($authResults)) { if (mb_stripos($authResults, 'spf=fail') !== false || mb_stripos($authResults, 'spf=softfail') !== false) { $warnings[] = "Kritische Warnung (Header): SPF-Authentifizierung fehlgeschlagen oder Softfail. Die Absenderdomain ist möglicherweise gefälscht."; $phishingScore += 3; + log_message("Phishing check: SPF fail/softfail."); } if (mb_stripos($authResults, 'dkim=fail') !== false) { $warnings[] = "Kritische Warnung (Header): DKIM-Authentifizierung fehlgeschlagen. Die E-Mail wurde möglicherweise manipuliert oder ist gefälscht."; $phishingScore += 3; + log_message("Phishing check: DKIM fail."); } if (mb_stripos($authResults, 'dmarc=fail') !== false || mb_stripos($authResults, 'dmarc=quarantine') !== false || mb_stripos($authResults, 'dmarc=reject') !== false) { $warnings[] = "Kritische Warnung (Header): DMARC-Authentifizierung fehlgeschlagen oder Aktion ausgelöst (Quarantine/Reject). Dies ist ein starkes Anzeichen für Phishing."; - $phishingScore += 4; // Höchster Wert für DMARC Fail + $phishingScore += 4; + log_message("Phishing check: DMARC fail/quarantine/reject."); } } else { $warnings[] = "Hinweis (Header): 'Authentication-Results' Header fehlen. Dies kann auf eine fehlende oder nicht standardmäßige E-Mail-Authentifizierung hindeuten."; $phishingScore += 1; + log_message("Phishing check: Missing Authentication-Results."); } - // --- Bestimmung der Phishing-Tendenz --- - // Dies ist ein einfacher Schwellenwert. Sie können die Werte und Schwellenwerte anpassen. - // Ein Wert > 3 deutet auf eine hohe Phishing-Wahrscheinlichkeit hin. - $isPhishingTendency = $phishingScore >= 3.0; // Schwellenwert für "hoch" - + $isPhishingTendency = $phishingScore >= 3.0; + log_message("Finished checkPhishing function. Phishing Score: " . $phishingScore . ", Tendency: " . ($isPhishingTendency ? "HIGH" : "LOW")); return ['warnings' => $warnings, 'is_phishing_tendency' => $isPhishingTendency]; } if ($_SERVER['REQUEST_METHOD'] === 'POST') { - if (isset($_FILES['email_file']) && $_FILES['email_file']['error'] === UPLOAD_ERR_OK) { - $fileTmpPath = $_FILES['email_file']['tmp_name']; - $fileName = $_FILES['email_file']['name']; // Original-Dateiname, der Emojis enthalten könnte - $fileSize = $_FILES['email_file']['size']; - $fileType = $_FILES['email_file']['type']; - - // Versuche, die Dateiendung robust zu extrahieren - $fileExtension = ''; - $fileNameParts = explode(".", $fileName); - if (count($fileNameParts) > 1) { - $fileExtension = mb_strtolower(end($fileNameParts)); - } + log_message("Script started via POST request."); + try { + if (isset($_FILES['email_file']) && $_FILES['email_file']['error'] === UPLOAD_ERR_OK) { + $fileTmpPath = $_FILES['email_file']['tmp_name']; + $fileName = $_FILES['email_file']['name']; + $fileSize = $_FILES['email_file']['size']; + $fileType = $_FILES['email_file']['type']; + + log_message("File uploaded: " . $fileName . ", size: " . $fileSize . " bytes."); - $allowedfileExtensions = array('eml', 'txt'); + $fileExtension = ''; + $fileNameParts = explode(".", $fileName); + if (count($fileNameParts) > 1) { + $fileExtension = mb_strtolower(end($fileNameParts)); + } - if (in_array($fileExtension, $allowedfileExtensions)) { - $emailContent = @file_get_contents($fileTmpPath); // @ zur Unterdrückung von Warnungen + $allowedfileExtensions = array('eml', 'txt'); - if ($emailContent === false) { - header('Location: index.php?error=' . rawurlencode('Fehler beim Lesen der hochgeladenen Datei oder Datei ist leer.')); + if (in_array($fileExtension, $allowedfileExtensions)) { + log_message("File extension is allowed: " . $fileExtension); + $emailContent = @file_get_contents($fileTmpPath); + + if ($emailContent === false) { + log_message("ERROR: Failed to read file content from " . $fileTmpPath); + header('Location: index.php?error=' . rawurlencode('Fehler beim Lesen der hochgeladenen Datei oder Datei ist leer.')); + exit(); + } + log_message("File content read successfully. Length: " . mb_strlen($emailContent) . " bytes."); + + + if (!mb_check_encoding($emailContent, 'UTF-8')) { + log_message("WARNING: Email content not initially UTF-8. Attempting conversion."); + $emailContent = mb_convert_encoding($emailContent, 'UTF-8', 'auto'); + if (!mb_check_encoding($emailContent, 'UTF-8')) { + log_message("ERROR: Failed to convert email content to UTF-8 after attempt."); + } else { + log_message("Successfully converted email content to UTF-8."); + } + } + + + $headers = parseEmailHeaders($emailContent); + $phishingResult = checkPhishing($headers, $emailContent); + + $fullEmailPreview = mb_substr($emailContent, 0, 2000); + $fullEmailPreview = preg_replace('/[^\x{0009}\x{000A}\x{000D}\x{0020}-\x{D7FF}\x{E000}-\x{FFFD}\x{10000}-\x{10FFFF}]/u', '', $fullEmailPreview); + + + $result = [ + 'headers' => $headers, + 'phishing_check' => $phishingResult['warnings'], + 'is_phishing_tendency' => $phishingResult['is_phishing_tendency'], + 'full_email_preview' => $fullEmailPreview + ]; + + // --- NEUE LOGIK: Ergebnis in temporäre Datei schreiben --- + $tempDir = __DIR__ . '/temp_results/'; // Temporäres Verzeichnis + if (!is_dir($tempDir)) { + mkdir($tempDir, 0755, true); // Verzeichnis erstellen, wenn es nicht existiert + log_message("Created temp_results directory: " . $tempDir); + } + + $resultId = uniqid('email_analysis_', true) . '.json'; // Eindeutiger Dateiname + $tempFilePath = $tempDir . $resultId; + + // Speichern des JSON-Ergebnisses in der temporären Datei + $jsonResult = json_encode($result, JSON_UNESCAPED_UNICODE | JSON_PARTIAL_OUTPUT_ON_ERROR); + if ($jsonResult === false) { + log_message("ERROR: JSON encoding failed: " . json_last_error_msg()); + throw new Exception("Fehler beim Kodieren der Analyseergebnisse."); + } + + if (file_put_contents($tempFilePath, $jsonResult) === false) { + log_message("ERROR: Failed to write result to temp file: " . $tempFilePath); + throw new Exception("Fehler beim Speichern der Analyseergebnisse."); + } + log_message("Analysis result saved to temp file: " . $tempFilePath); + + // Weiterleitung mit dem Dateinamen als Parameter + log_message("Analysis completed. Redirecting to index.php with result ID: " . $resultId); + header('Location: index.php?result_id=' . rawurlencode($resultId)); + exit(); + + } else { + log_message("ERROR: Invalid file type uploaded: " . $fileExtension); + header('Location: index.php?error=' . rawurlencode('Ungültiger Dateityp. Bitte laden Sie eine .eml- oder .txt-Datei hoch.')); exit(); } - - // Sicherstellen, dass $emailContent gültiges UTF-8 ist - if (!mb_check_encoding($emailContent, 'UTF-8')) { - // Versuche, es von ISO-8859-1 oder einer anderen gängigen Kodierung nach UTF-8 zu konvertieren - $emailContent = mb_convert_encoding($emailContent, 'UTF-8', 'auto'); - } - - - $headers = parseEmailHeaders($emailContent); - $phishingResult = checkPhishing($headers, $emailContent); // Holt jetzt Array mit Warnings und Tendenz - - // Eine Vorschau des E-Mail-Inhalts für die Debugging-Zwecke - // Sicherstellen, dass der Preview-Inhalt auch UTF-8 ist und gültige Zeichen hat - $fullEmailPreview = mb_substr($emailContent, 0, 2000); // Max. 2000 Zeichen - // Entferne potenziell ungültige UTF-8-Sequenzen, die später Probleme verursachen könnten - $fullEmailPreview = preg_replace('/[^\x{0009}\x{000A}\x{000D}\x{0020}-\x{D7FF}\x{E000}-\x{FFFD}\x{10000}-\x{10FFFF}]/u', '', $fullEmailPreview); - - - $result = [ - 'headers' => $headers, - 'phishing_check' => $phishingResult['warnings'], - 'is_phishing_tendency' => $phishingResult['is_phishing_tendency'], - 'full_email_preview' => $fullEmailPreview - ]; - - // Ergebnisse als JSON enkodieren und base64 enkodieren, um sie in der URL zu übergeben - // NEU: rawurlencode() statt urlencode() für robustere URL-Parameter - $encodedResult = rawurlencode(base64_encode(json_encode($result, JSON_UNESCAPED_UNICODE | JSON_PARTIAL_OUTPUT_ON_ERROR))); - header('Location: index.php?result=' . $encodedResult); - exit(); - } else { - header('Location: index.php?error=' . rawurlencode('Ungültiger Dateityp. Bitte laden Sie eine .eml- oder .txt-Datei hoch.')); + $uploadError = 'Unbekannter Fehler beim Hochladen der Datei.'; + if (isset($_FILES['email_file']) && $_FILES['email_file']['error'] !== UPLOAD_ERR_NO_FILE) { + switch ($_FILES['email_file']['error']) { + case UPLOAD_ERR_INI_SIZE: $uploadError = 'Die hochgeladene Datei überschreitet die in der php.ini festgelegte maximale Dateigröße.'; break; + case UPLOAD_ERR_FORM_SIZE: $uploadError = 'Die hochgeladene Datei überschreitet die im HTML-Formular festgelegte maximale Dateigröße.'; break; + case UPLOAD_ERR_PARTIAL: $uploadError = 'Die Datei wurde nur teilweise hochgeladen.'; break; + case UPLOAD_ERR_NO_FILE: $uploadError = 'Es wurde keine Datei hochgeladen.'; break; + case UPLOAD_ERR_NO_TMP_DIR: $uploadError = 'Temporäres Verzeichnis fehlt.'; break; + case UPLOAD_ERR_CANT_WRITE: $uploadError = 'Fehler beim Schreiben der Datei auf die Festplatte.'; break; + case UPLOAD_ERR_EXTENSION: $uploadError = 'Eine PHP-Erweiterung hat das Hochladen der Datei gestoppt.'; break; + } + } + log_message("ERROR: File upload error: " . $uploadError); + header('Location: index.php?error=' . rawurlencode('Fehler beim Hochladen der Datei: ' . $uploadError)); exit(); } - } else { - $uploadError = 'Unbekannter Fehler beim Hochladen der Datei.'; - if (isset($_FILES['email_file']) && $_FILES['email_file']['error'] !== UPLOAD_ERR_NO_FILE) { - switch ($_FILES['email_file']['error']) { - case UPLOAD_ERR_INI_SIZE: - $uploadError = 'Die hochgeladene Datei überschreitet die in der php.ini festgelegte maximale Dateigröße.'; - break; - case UPLOAD_ERR_FORM_SIZE: - $uploadError = 'Die hochgeladene Datei überschreitet die im HTML-Formular festgelegte maximale Dateigröße.'; - break; - case UPLOAD_ERR_PARTIAL: - $uploadError = 'Die Datei wurde nur teilweise hochgeladen.'; - break; - case UPLOAD_ERR_NO_FILE: - $uploadError = 'Es wurde keine Datei hochgeladen.'; - break; - case UPLOAD_ERR_NO_TMP_DIR: - $uploadError = 'Temporäres Verzeichnis fehlt.'; - break; - case UPLOAD_ERR_CANT_WRITE: - $uploadError = 'Fehler beim Schreiben der Datei auf die Festplatte.'; - break; - case UPLOAD_ERR_EXTENSION: - $uploadError = 'Eine PHP-Erweiterung hat das Hochladen der Datei gestoppt.'; - break; - } - } - header('Location: index.php?error=' . rawurlencode('Fehler beim Hochladen der Datei: ' . $uploadError)); + } catch (Throwable $e) { + log_message("FATAL ERROR CAUGHT: " . $e->getMessage() . " in " . $e->getFile() . " on line " . $e->getLine()); + header('Location: index.php?error=' . rawurlencode('Ein unerwarteter Fehler ist aufgetreten: ' . $e->getMessage())); exit(); } } else { + log_message("Script accessed directly without POST data."); header('Location: index.php'); exit(); } \ No newline at end of file