Diagnose fuer den PayPal-Postfachzugang
Vor dem ersten Abruf soll klar sein, ob der Host das Postfach ueberhaupt erreicht - und auf welchem Weg. Das Skript meldet PHP-Version, ob die imap-Erweiterung geladen ist, ob die PAYPAL_*-Einstellungen gesetzt sind, und oeffnet das Postfach testweise ueber eine reine TLS-Verbindung. Damit ist auch ohne die Erweiterung belegbar, dass ein Abruf moeglich waere - seit PHP 8.4 ist imap kein Bestandteil von PHP mehr und laesst sich auf einem Webhosting nicht einfach nachruesten. Bewusst nur lesend: EXAMINE statt SELECT, kein Flag wird gesetzt. Das Passwort wird nie ausgegeben, nur seine Laenge als Tippfehler-Probe. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,176 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* Diagnose fuer den PayPal-Mailabruf: klaert in einem Lauf, ob dieser Host
|
||||
* das Postfach ueberhaupt erreichen kann - und auf welchem Weg.
|
||||
*
|
||||
* Geprueft wird:
|
||||
* 1. PHP-Version und ob die imap-Erweiterung geladen ist (seit PHP 8.4 ist
|
||||
* sie nicht mehr Teil von PHP, sondern nur noch ueber PECL zu haben).
|
||||
* 2. Ob die PAYPAL_*-Einstellungen in der env.local.php gesetzt sind.
|
||||
* 3. Ob sich das Postfach ohne die Erweiterung erreichen laesst - ueber
|
||||
* eine reine TLS-Verbindung, wie sie auch ein Fallback nutzen wuerde.
|
||||
*
|
||||
* Der Test ist bewusst nur lesend: EXAMINE statt SELECT, kein Flag wird
|
||||
* gesetzt, keine Mail veraendert. Das Passwort wird nie ausgegeben.
|
||||
*
|
||||
* Aufruf (Plesk: Geplante Aufgabe vom Typ "PHP-Skript"):
|
||||
* /httpdocs/scripts/check-imap-support.php
|
||||
*/
|
||||
|
||||
if (PHP_SAPI !== 'cli') {
|
||||
http_response_code(403);
|
||||
exit("Dieses Skript ist nur fuer die Kommandozeile gedacht.\n");
|
||||
}
|
||||
|
||||
require_once __DIR__ . '/../app/bootstrap.php';
|
||||
|
||||
function imap_check_line(string $label, string $value): void
|
||||
{
|
||||
printf("%-28s %s\n", $label . ':', $value);
|
||||
}
|
||||
|
||||
echo "=== PHP ===\n";
|
||||
imap_check_line('Version', PHP_VERSION);
|
||||
imap_check_line('imap-Erweiterung', function_exists('imap_open') ? 'geladen' : 'FEHLT');
|
||||
imap_check_line('openssl', extension_loaded('openssl') ? 'vorhanden' : 'FEHLT');
|
||||
imap_check_line('Sockets/Streams', function_exists('stream_socket_client') ? 'vorhanden' : 'FEHLT');
|
||||
if (!function_exists('imap_open') && version_compare(PHP_VERSION, '8.4', '>=')) {
|
||||
echo "Hinweis: Ab PHP 8.4 ist imap kein Bestandteil von PHP mehr. Entweder den\n"
|
||||
. "PHP-Handler dieses Vhosts auf 8.3 stellen oder den Abruf ueber eine reine\n"
|
||||
. "TLS-Verbindung laufen lassen (siehe Test unten).\n";
|
||||
}
|
||||
|
||||
echo "\n=== Einstellungen (env.local.php) ===\n";
|
||||
$host = app_env('PAYPAL_IMAP_HOST');
|
||||
$user = app_env('PAYPAL_IMAP_USER');
|
||||
$pass = app_env('PAYPAL_IMAP_PASS');
|
||||
$port = (int) app_env('PAYPAL_IMAP_PORT', '993');
|
||||
$flags = (string) app_env('PAYPAL_IMAP_FLAGS', '/imap/ssl');
|
||||
$mailbox = (string) app_env('PAYPAL_IMAP_MAILBOX', 'INBOX');
|
||||
|
||||
imap_check_line('PAYPAL_INBOX_BASE', (string) (app_env('PAYPAL_INBOX_BASE') ?? '(nicht gesetzt)'));
|
||||
imap_check_line('PAYPAL_IMAP_HOST', (string) ($host ?? '(nicht gesetzt)'));
|
||||
imap_check_line('PAYPAL_IMAP_PORT', (string) $port);
|
||||
imap_check_line('PAYPAL_IMAP_FLAGS', $flags);
|
||||
imap_check_line('PAYPAL_IMAP_USER', (string) ($user ?? '(nicht gesetzt)'));
|
||||
// Das Passwort selbst gehoert nicht in ein Protokoll, das per Mail
|
||||
// verschickt oder weitergereicht wird - nur die Laenge als Tippfehler-Probe.
|
||||
imap_check_line('PAYPAL_IMAP_PASS', $pass === null ? '(nicht gesetzt)' : 'gesetzt (' . strlen($pass) . ' Zeichen)');
|
||||
imap_check_line('PAYPAL_IMAP_MAILBOX', $mailbox);
|
||||
|
||||
if ($host === null || $user === null || $pass === null) {
|
||||
echo "\nOhne Host, Benutzer und Passwort ist kein Verbindungstest moeglich.\n";
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Liest die Antwort bis zur Zeile mit dem gesuchten Tag.
|
||||
*
|
||||
* @return array{ok: bool, lines: list<string>}
|
||||
*/
|
||||
function imap_check_read($sock, string $tag): array
|
||||
{
|
||||
$lines = [];
|
||||
while (($line = fgets($sock)) !== false) {
|
||||
$line = rtrim($line, "\r\n");
|
||||
$lines[] = $line;
|
||||
if (str_starts_with($line, $tag . ' ')) {
|
||||
return ['ok' => str_starts_with($line, $tag . ' OK'), 'lines' => $lines];
|
||||
}
|
||||
}
|
||||
|
||||
return ['ok' => false, 'lines' => $lines];
|
||||
}
|
||||
|
||||
function imap_check_send($sock, string $tag, string $command): array
|
||||
{
|
||||
fwrite($sock, $tag . ' ' . $command . "\r\n");
|
||||
|
||||
return imap_check_read($sock, $tag);
|
||||
}
|
||||
|
||||
echo "\n=== Verbindungstest ohne imap-Erweiterung (nur lesend) ===\n";
|
||||
|
||||
// Port 993 = TLS von Anfang an; alles andere (typisch 143) = STARTTLS.
|
||||
$implizitesTls = $port === 993 || str_contains($flags, '/ssl');
|
||||
$adresse = ($implizitesTls ? 'ssl://' : 'tcp://') . $host . ':' . $port;
|
||||
imap_check_line('Verbindung', $adresse . ($implizitesTls ? ' (TLS sofort)' : ' (STARTTLS)'));
|
||||
|
||||
$fehlerNr = 0;
|
||||
$fehlerText = '';
|
||||
$sock = @stream_socket_client($adresse, $fehlerNr, $fehlerText, 15);
|
||||
if ($sock === false) {
|
||||
echo "FEHLER: Verbindung nicht moeglich ({$fehlerNr}: {$fehlerText})\n";
|
||||
echo "Moegliche Ursachen: Host/Port falsch, ausgehende Verbindungen gesperrt,\n"
|
||||
. "oder TLS-Zertifikat nicht akzeptiert.\n";
|
||||
exit(1);
|
||||
}
|
||||
stream_set_timeout($sock, 15);
|
||||
|
||||
$greeting = rtrim((string) fgets($sock), "\r\n");
|
||||
imap_check_line('Begruessung', $greeting !== '' ? $greeting : '(keine)');
|
||||
|
||||
if (!$implizitesTls) {
|
||||
$start = imap_check_send($sock, 'a0', 'STARTTLS');
|
||||
if (!$start['ok'] || !@stream_socket_enable_crypto($sock, true, STREAM_CRYPTO_METHOD_TLS_CLIENT)) {
|
||||
echo "FEHLER: STARTTLS fehlgeschlagen - ohne Verschluesselung wird nicht angemeldet.\n";
|
||||
exit(1);
|
||||
}
|
||||
imap_check_line('STARTTLS', 'ok');
|
||||
}
|
||||
|
||||
// Anfuehrungszeichen und Backslashes im Passwort maskieren (IMAP-Quoting).
|
||||
$quote = static fn(string $wert): string => '"' . str_replace(['\\', '"'], ['\\\\', '\\"'], $wert) . '"';
|
||||
|
||||
$login = imap_check_send($sock, 'a1', 'LOGIN ' . $quote($user) . ' ' . $quote($pass));
|
||||
if (!$login['ok']) {
|
||||
echo "FEHLER: Anmeldung abgelehnt.\n";
|
||||
echo ' Antwort: ' . end($login['lines']) . "\n";
|
||||
fwrite($sock, "a9 LOGOUT\r\n");
|
||||
fclose($sock);
|
||||
exit(1);
|
||||
}
|
||||
imap_check_line('Anmeldung', 'ok');
|
||||
|
||||
// EXAMINE statt SELECT: oeffnet das Postfach ausdruecklich nur lesend.
|
||||
$examine = imap_check_send($sock, 'a2', 'EXAMINE ' . $quote($mailbox));
|
||||
if (!$examine['ok']) {
|
||||
echo "FEHLER: Postfach '{$mailbox}' nicht zu oeffnen.\n";
|
||||
echo ' Antwort: ' . end($examine['lines']) . "\n";
|
||||
fwrite($sock, "a9 LOGOUT\r\n");
|
||||
fclose($sock);
|
||||
exit(1);
|
||||
}
|
||||
$gesamt = 0;
|
||||
foreach ($examine['lines'] as $line) {
|
||||
if (preg_match('/^\* (\d+) EXISTS/', $line, $m)) {
|
||||
$gesamt = (int) $m[1];
|
||||
}
|
||||
}
|
||||
imap_check_line('Postfach', $mailbox . ' geoeffnet');
|
||||
imap_check_line('Mails gesamt', (string) $gesamt);
|
||||
|
||||
$search = imap_check_send($sock, 'a3', 'SEARCH UNSEEN');
|
||||
$ungelesen = 0;
|
||||
foreach ($search['lines'] as $line) {
|
||||
if (str_starts_with($line, '* SEARCH')) {
|
||||
$ids = trim(substr($line, strlen('* SEARCH')));
|
||||
$ungelesen = $ids === '' ? 0 : count(preg_split('/\s+/', $ids) ?: []);
|
||||
}
|
||||
}
|
||||
imap_check_line('davon ungelesen', (string) $ungelesen);
|
||||
|
||||
fwrite($sock, "a9 LOGOUT\r\n");
|
||||
fclose($sock);
|
||||
|
||||
echo "\nErgebnis: Postfach erreichbar und Zugangsdaten gueltig.\n";
|
||||
if (function_exists('imap_open')) {
|
||||
echo "Die imap-Erweiterung ist vorhanden - scripts/fetch-paypal-payments.php\n"
|
||||
. "laeuft ohne weitere Aenderung. Naechster Schritt: derselbe Task mit --dry-run.\n";
|
||||
} else {
|
||||
echo "Die imap-Erweiterung fehlt, das Postfach ist aber ueber die reine\n"
|
||||
. "TLS-Verbindung erreichbar - ein Abruf ohne Erweiterung ist also moeglich.\n";
|
||||
}
|
||||
Reference in New Issue
Block a user