diff --git a/app/paypal-mail-parser.php b/app/paypal-mail-parser.php index 2487ccc..1a5a51d 100644 --- a/app/paypal-mail-parser.php +++ b/app/paypal-mail-parser.php @@ -15,9 +15,9 @@ declare(strict_types=1); */ /** - * Wandelt den (ggf. UTF-16-kodierten) Mail-Body in normalisierten UTF-8-Text um: - * Skript/Style raus, Tags durch Leerzeichen ersetzt, Entities dekodiert, NBSP - * und Mehrfach-Whitespace zusammengefasst. + * Wandelt den (ggf. UTF-16- oder Windows-1252-kodierten) Mail-Body in + * normalisierten UTF-8-Text um: Skript/Style raus, Tags durch Leerzeichen + * ersetzt, Entities dekodiert, NBSP und Mehrfach-Whitespace zusammengefasst. */ function paypal_mail_to_text(string $body): string { @@ -27,6 +27,16 @@ function paypal_mail_to_text(string $body): string if ($converted !== false) { $body = $converted; } + } elseif (preg_match('//u', $body) !== 1) { + // Outlook/Hotmail kennzeichnet weitergeleitete Nachrichten teils als + // UTF-8, liefert den Body aber tatsaechlich in Windows-1252. Dann + // schlagen alle folgenden Unicode-Regulaerausdruecke still fehl. Das + // Eurozeichen (0x80) ist zugleich ein typisches Erkennungsmerkmal fuer + // Windows-1252 statt ISO-8859-1. + $converted = @iconv('Windows-1252', 'UTF-8//IGNORE', $body); + if ($converted !== false) { + $body = $converted; + } } $body = preg_replace('#<(script|style)[^>]*>.*?#is', ' ', $body) ?? $body; diff --git a/scripts/check-paypal-inbox-flow.php b/scripts/check-paypal-inbox-flow.php index 2daa2ea..d221427 100644 --- a/scripts/check-paypal-inbox-flow.php +++ b/scripts/check-paypal-inbox-flow.php @@ -109,6 +109,28 @@ try { $codeA = 'TXNAUTO' . strtoupper(bin2hex(random_bytes(4))); $mailA = paypal_flow_mail("Erika Musterfrau {$namensSuffix}", '12,50', $codeA, 'Kaffeekasse', '12,15'); + // Outlook/Hotmail liefert weitergeleitete HTML-Mails mitunter als + // Windows-1252, obwohl die umgebende Mail UTF-8 behauptet. Der Parser muss + // insbesondere Umlaute und das dort einbyteige Eurozeichen konvertieren, + // bevor seine Unicode-Regulaerausdruecke laufen. + $codeWindows = 'TXNWIN' . strtoupper(bin2hex(random_bytes(4))); + $mailWindows = str_replace( + '€', + '€', + paypal_flow_mail('Jürgen Müller', '36,54', $codeWindows, 'Vielen Dank', null) + ); + $mailWindows = (string) iconv('UTF-8', 'Windows-1252//TRANSLIT', $mailWindows); + $parsedWindows = paypal_parse_notification($mailWindows); + paypal_flow_assert('Windows-1252-Mail wird erkannt', $parsedWindows !== null, $failures, $passes); + paypal_flow_assert( + 'Windows-1252-Mail liefert Name, Betrag und Transaktionscode', + ($parsedWindows['payer_name'] ?? '') === 'Jürgen Müller' + && ($parsedWindows['net_cents'] ?? 0) === 3654 + && ($parsedWindows['transaction_code'] ?? '') === $codeWindows, + $failures, + $passes + ); + // Erst die Vorschau: sie darf nichts anlegen. $vorschau = paypal_process_raw($pdo, $empfaengerA, $mailA, true); paypal_flow_assert('Vorschau meldet die geplante Buchung', ($vorschau['status'] ?? '') === 'would_book', $failures, $passes);