get()->filter( fn (MailOAuthConnection $connection): bool => $connection->usable(), ); if ($connections->isEmpty()) { $this->info('No connected OAuth mailboxes; nothing to refresh.'); return self::SUCCESS; } foreach ($connections as $connection) { $hadError = $connection->last_error !== null; try { $brokers->for($connection->provider)->refresh($connection); $this->info("Refreshed {$connection->provider->value} ({$connection->account_email})."); // Back from the dead (an admin fixed things upstream // without reconnecting): the applier may have been // resolving "not ready" and must see the recovery. if ($hadError) { $mailConfig->flush(); } } catch (MailOAuthException $e) { $this->error("Could not refresh {$connection->provider->value}: {$e->getMessage()}"); if (! $e->needsReconnect) { continue; } // Only on the transition into the broken state — the // notification would otherwise repeat daily for as long // as nobody reconnects, and a nagging alert trains // people to ignore the one that matters. if (! $hadError) { $recipients = array_values(User::query()->where('type', UserType::Staff)->get() ->filter(fn (User $staff): bool => $permissions->allows($staff, Permission::EditSettings)) ->all()); $notifier->send('mail_oauth_connection_broken', $recipients, data: [ 'provider' => $connection->provider->label(), 'account' => (string) $connection->account_email, ]); } $mailConfig->flush(); } } return self::SUCCESS; } }