Files
deskhub/DeskHub-Webseite/includes/mail_fetch_manual.php
T
2026-11-04 07:55:19 +00:00

83 lines
3.9 KiB
PHP

<?php
/**
* includes/mail_fetch_manual.php
*
* E-Mail-Abruf von Hand starten (Knopf in der Ticketliste). Läuft über dieselbe Funktion wie der Cronjob. Damit der Abruf nicht doppelt
* läuft (Doppelklick, zugleich der eingebaute Zeitgeber oder ein anderer Mitarbeiter), wird vorher der Zeitstempel des letzten Abrufs
* atomar beansprucht: Wer ihn bekommt, ruft ab; alle anderen innerhalb der Sperrzeit bekommen eine Meldung.
*/
/** Mindestabstand zwischen zwei Abrufen von Hand, in Sekunden. */
const MAIL_FETCH_MANUAL_COOLDOWN = 20;
/** Gibt es etwas abzurufen (mindestens ein aktives Postfach)? */
function mail_fetch_available(PDO $pdo): bool
{
try {
return (int) $pdo->query('SELECT COUNT(*) FROM imap_accounts WHERE is_active = 1')->fetchColumn() > 0;
} catch (Throwable $e) {
return false;
}
}
/**
* Startet den Abruf. $runner ist nur für Tests austauschbar (liefert wie run_fetch_emails ['processed' => int, 'log' => string[]]).
*
* @return array{ok:bool,level:string,message:string,processed:int,new_tickets:int,replies:int,errors:string[]}
*/
function mail_fetch_manual(PDO $pdo, ?callable $runner = null): array
{
$res = ['ok' => false, 'level' => 'error', 'message' => '', 'processed' => 0, 'new_tickets' => 0, 'replies' => 0, 'errors' => []];
if (!function_exists('imap_open') && $runner === null) {
$res['message'] = 'Der Abruf ist nicht möglich: Die PHP-Erweiterung IMAP ist auf diesem Server nicht aktiv.';
return $res;
}
if (!mail_fetch_available($pdo)) {
$res['message'] = 'Es ist kein aktives Postfach eingerichtet (Adminportal → Postfächer (Abruf)).';
return $res;
}
if (!pseudo_cron_try_claim($pdo, 'cron_fetch_emails_last_run', MAIL_FETCH_MANUAL_COOLDOWN)) {
$res['level'] = 'info';
$res['message'] = 'Der E-Mail-Abruf lief gerade eben schon (oder läuft noch). Bitte einige Sekunden warten und dann erneut versuchen.';
return $res;
}
if ($runner === null) {
if (!defined('DESKHUB_CRON_RUNNER')) define('DESKHUB_CRON_RUNNER', true);
require_once __DIR__ . '/../cron/fetch_emails.php';
$runner = fn() => run_fetch_emails($pdo, true);
}
@set_time_limit(120);
try {
$out = $runner();
} catch (Throwable $e) {
error_log('Manueller E-Mail-Abruf: ' . $e->getMessage());
$res['message'] = 'Der E-Mail-Abruf ist mit einem Fehler abgebrochen: ' . mb_substr($e->getMessage(), 0, 200);
return $res;
}
$res['processed'] = (int) ($out['processed'] ?? 0);
foreach ((array) ($out['log'] ?? []) as $line) {
$line = (string) $line;
if (preg_match('/Neues Ticket #/', $line)) $res['new_tickets']++;
elseif (preg_match('/Antwort zu Ticket #/', $line)) $res['replies']++;
if (preg_match('/fehlgeschlagen|Abbruch|nicht installiert|Kein aktives Postfach/i', $line) && !str_contains($line, 'Anhang nicht übernommen')) {
$res['errors'][] = mb_substr(preg_replace('/^\[[^\]]*\]\s*/', '', $line) ?? $line, 0, 220);
}
}
$res['ok'] = $res['errors'] === [];
if ($res['errors']) {
$res['message'] = 'Der Abruf hatte Probleme: ' . implode(' | ', array_slice($res['errors'], 0, 3));
} elseif ($res['processed'] === 0) {
$res['level'] = 'info';
$res['message'] = 'Abruf fertig: Keine neuen E-Mails.';
} else {
$res['level'] = 'success';
$parts = [];
if ($res['new_tickets'] > 0) $parts[] = $res['new_tickets'] . ' neue(s) Ticket(s)';
if ($res['replies'] > 0) $parts[] = $res['replies'] . ' Antwort(en)';
$other = $res['processed'] - $res['new_tickets'] - $res['replies'];
if ($other > 0) $parts[] = $other . ' weitere (zum Beispiel Spam oder Systemmails, ohne Ticket)';
$res['message'] = 'Abruf fertig: ' . $res['processed'] . ' E-Mail(s) verarbeitet' . ($parts ? ' (' . implode(', ', $parts) . ')' : '') . '.';
}
return $res;
}