From 25de2ed7bc83e8006acecf2e17fcf9ac2fb439b4 Mon Sep 17 00:00:00 2001 From: isaacclad Date: Sat, 4 Jul 2026 10:59:59 +0000 Subject: [PATCH] Fix Ladill Mail calendar sync mailbox resolution and updates. Use the connected mail calendar mailbox when set, skip API calls when MAIL_API_KEY_MEET is unset, and call syncRoomUpdated on room edits. Co-authored-by: Cursor --- .../Meet/Calendar/MailCalendarProvider.php | 4 +++ app/Services/Meet/CalendarService.php | 36 +++++++++++++++---- app/Services/Meet/RoomService.php | 2 +- tests/Feature/MeetWebTest.php | 29 +++++++++++++++ 4 files changed, 64 insertions(+), 7 deletions(-) diff --git a/app/Services/Meet/Calendar/MailCalendarProvider.php b/app/Services/Meet/Calendar/MailCalendarProvider.php index 2de0ab1..cdfd3fe 100644 --- a/app/Services/Meet/Calendar/MailCalendarProvider.php +++ b/app/Services/Meet/Calendar/MailCalendarProvider.php @@ -22,6 +22,10 @@ class MailCalendarProvider public function createEventForMailbox(string $mailbox, Room $room): ?string { + if (! filled(config('meet.calendar.mail.api_key'))) { + return null; + } + $response = Http::withToken((string) config('meet.calendar.mail.api_key')) ->acceptJson() ->timeout(10) diff --git a/app/Services/Meet/CalendarService.php b/app/Services/Meet/CalendarService.php index 51e0887..726840c 100644 --- a/app/Services/Meet/CalendarService.php +++ b/app/Services/Meet/CalendarService.php @@ -24,8 +24,8 @@ class CalendarService return; } - if ($host->email) { - $eventId = $this->mail->createEventForMailbox($host->email, $room); + if ($mailbox = $this->resolveMailMailbox($host)) { + $eventId = $this->mail->createEventForMailbox($mailbox, $room); if ($eventId) { $room->update(['calendar_event_id' => $eventId]); } @@ -43,9 +43,9 @@ class CalendarService return; } - if ($host->email) { + if ($mailbox = $this->resolveMailMailbox($host)) { if ($room->calendar_event_id) { - $this->mail->updateEventForMailbox($host->email, $room); + $this->mail->updateEventForMailbox($mailbox, $room); } else { $this->syncRoomCreated($room, $host); } @@ -59,8 +59,10 @@ class CalendarService public function syncRoomCancelled(Room $room, User $host): void { - if ($host->email && $room->calendar_event_id) { - $this->mail->deleteEventForMailbox($host->email, $room); + if ($mailbox = $this->resolveMailMailbox($host)) { + if ($room->calendar_event_id) { + $this->mail->deleteEventForMailbox($mailbox, $room); + } } $connection = $this->connectionFor($host); @@ -71,6 +73,28 @@ class CalendarService $room->update(['calendar_event_id' => null]); } + public function mailCalendarConfigured(): bool + { + return filled(config('meet.calendar.mail.api_key')) + && filled(config('meet.calendar.mail.api_url')); + } + + protected function resolveMailMailbox(User $host): ?string + { + if (! $this->mailCalendarConfigured()) { + return null; + } + + $connection = $this->connectionFor($host, 'mail'); + if ($connection?->calendar_id) { + return strtolower(trim((string) $connection->calendar_id)); + } + + $email = strtolower(trim((string) $host->email)); + + return filter_var($email, FILTER_VALIDATE_EMAIL) ? $email : null; + } + public function connectionFor(User $user, ?string $provider = null): ?CalendarConnection { $query = CalendarConnection::where('user_ref', $user->ownerRef()); diff --git a/app/Services/Meet/RoomService.php b/app/Services/Meet/RoomService.php index f2dab9c..badd371 100644 --- a/app/Services/Meet/RoomService.php +++ b/app/Services/Meet/RoomService.php @@ -94,7 +94,7 @@ class RoomService AuditLogger::record($room->owner_ref, 'room.updated', $room->organization_id, $room->host_user_ref, Room::class, $room->id); if ($host && $room->scheduled_at) { - app(CalendarService::class)->syncRoomCreated($room->fresh(), $host); + app(CalendarService::class)->syncRoomUpdated($room->fresh(), $host); } return $room->fresh(); diff --git a/tests/Feature/MeetWebTest.php b/tests/Feature/MeetWebTest.php index 4e4d85c..22d66c4 100644 --- a/tests/Feature/MeetWebTest.php +++ b/tests/Feature/MeetWebTest.php @@ -740,6 +740,35 @@ class MeetWebTest extends TestCase ]); } + public function test_scheduled_room_uses_connected_mail_mailbox(): void + { + \Illuminate\Support\Facades\Http::fake([ + 'mail.ladill.com/*' => \Illuminate\Support\Facades\Http::response(['data' => ['id' => 42]], 201), + ]); + + config([ + 'meet.calendar.mail.api_url' => 'https://mail.ladill.com/api/service/v1', + 'meet.calendar.mail.api_key' => 'mail-test-key', + ]); + + $this->actingAs($this->user) + ->post('/settings/calendar/mail', ['mailbox_email' => 'host@customdomain.com']) + ->assertRedirect(route('meet.settings.calendar')); + + $this->actingAs($this->user) + ->post('/meetings', [ + 'title' => 'Custom mailbox sync', + 'scheduled_at' => now()->addDay()->format('Y-m-d H:i'), + 'duration_minutes' => 30, + ]) + ->assertRedirect(); + + \Illuminate\Support\Facades\Http::assertSent(function ($request) { + return str_contains($request->url(), '/calendar/events') + && $request['mailbox_email'] === 'host@customdomain.com'; + }); + } + public function test_host_can_create_conference(): void { $this->actingAs($this->user)