option('account'); if (blank(config("imap.accounts.{$account}.host")) || blank(config("imap.accounts.{$account}.username"))) { $this->warn("IMAP-Konto „{$account}“ ist nicht konfiguriert (BOUNCE_IMAP_HOST/USERNAME/PASSWORD) — nichts zu tun."); return self::SUCCESS; } $dryRun = (bool) $this->option('dry-run'); $counts = [BounceMailProcessor::Processed => 0, BounceMailProcessor::Ignored => 0, BounceMailProcessor::Unparsed => 0]; $bounces = 0; try { $client = $clients->account($account); $client->connect(); $inbox = $client->getFolderByName('INBOX'); if ($inbox === null) { throw new \RuntimeException('INBOX nicht gefunden.'); } $messages = $inbox->query()->all()->setFetchBody(true)->limit(max(1, (int) $this->option('limit')))->get(); /** @var Message $message */ foreach ($messages as $message) { $raw = (string) $message->getHeader()?->raw."\r\n\r\n".$message->getRawBody(); $result = $processor->process($raw, $dryRun); $counts[$result['folder']]++; $bounces += $result['bounces']; $this->line(sprintf(' %-10s %s', $result['folder'], $result['subject'])); if (! $dryRun) { $this->moveTo($client->getFolderByName($result['folder']) ?? $client->createFolder($result['folder']), $message); } } $client->disconnect(); } catch (Throwable $e) { OperationalAlert::send('Bounce-Postfach konnte nicht gelesen werden', ['account' => $account, 'error' => $e->getMessage()]); $this->error($e->getMessage()); return self::FAILURE; } $this->info(sprintf( '%s%d Rückläufer verarbeitet (%d Bounces), %d ignoriert, %d nicht lesbar.', $dryRun ? '[Dry-Run] ' : '', $counts[BounceMailProcessor::Processed], $bounces, $counts[BounceMailProcessor::Ignored], $counts[BounceMailProcessor::Unparsed], )); return self::SUCCESS; } private function moveTo(Folder $folder, Message $message): void { $message->move($folder->path, expunge: true); } }